summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/runtime
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/ArgList.h3
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp41
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h34
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp218
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/ArrayStorage.h6
-rw-r--r--Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h8
-rw-r--r--Source/JavaScriptCore/runtime/BigInteger.h2
-rw-r--r--Source/JavaScriptCore/runtime/BooleanConstructor.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/BooleanConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/BooleanObject.h14
-rw-r--r--Source/JavaScriptCore/runtime/BooleanPrototype.cpp17
-rw-r--r--Source/JavaScriptCore/runtime/BooleanPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/Butterfly.h68
-rw-r--r--Source/JavaScriptCore/runtime/ButterflyInlines.h51
-rw-r--r--Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h2
-rw-r--r--Source/JavaScriptCore/runtime/CallData.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/CallData.h2
-rw-r--r--Source/JavaScriptCore/runtime/CodeCache.cpp143
-rw-r--r--Source/JavaScriptCore/runtime/CodeCache.h256
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h69
-rw-r--r--Source/JavaScriptCore/runtime/CommonSlowPaths.h4
-rw-r--r--Source/JavaScriptCore/runtime/Completion.cpp26
-rw-r--r--Source/JavaScriptCore/runtime/Completion.h7
-rw-r--r--Source/JavaScriptCore/runtime/ConstructData.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/ConstructData.h2
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.cpp35
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.cpp24
-rw-r--r--Source/JavaScriptCore/runtime/DateInstance.h12
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.cpp64
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp30
-rw-r--r--Source/JavaScriptCore/runtime/Error.h8
-rw-r--r--Source/JavaScriptCore/runtime/ErrorConstructor.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/ErrorConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/ErrorInstance.h20
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/ErrorPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.cpp93
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.h53
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp124
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h205
-rw-r--r--Source/JavaScriptCore/runtime/ExecutionHarness.h8
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/FunctionConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp37
-rw-r--r--Source/JavaScriptCore/runtime/FunctionExecutableDump.h49
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.cpp17
-rw-r--r--Source/JavaScriptCore/runtime/FunctionPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.cpp53
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallback.h22
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/GetterSetter.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/GetterSetter.h12
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp64
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.h52
-rw-r--r--Source/JavaScriptCore/runtime/IndexingHeader.h32
-rw-r--r--Source/JavaScriptCore/runtime/IndexingType.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/IndexingType.h25
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.cpp15
-rw-r--r--Source/JavaScriptCore/runtime/InternalFunction.h6
-rw-r--r--Source/JavaScriptCore/runtime/Intrinsic.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSAPIValueWrapper.h12
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.cpp19
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h30
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp185
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h70
-rw-r--r--Source/JavaScriptCore/runtime/JSBoundFunction.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/JSBoundFunction.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSCJSValue.cpp (renamed from Source/JavaScriptCore/runtime/JSValue.cpp)77
-rw-r--r--Source/JavaScriptCore/runtime/JSCJSValue.h (renamed from Source/JavaScriptCore/runtime/JSValue.h)26
-rw-r--r--Source/JavaScriptCore/runtime/JSCJSValueInlines.h810
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp29
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h189
-rw-r--r--Source/JavaScriptCore/runtime/JSCellInlines.h204
-rw-r--r--Source/JavaScriptCore/runtime/JSDateMath.cpp102
-rw-r--r--Source/JavaScriptCore/runtime/JSDestructibleObject.h39
-rw-r--r--Source/JavaScriptCore/runtime/JSExportMacros.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp73
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h66
-rw-r--r--Source/JavaScriptCore/runtime/JSFunctionInlines.h69
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp311
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h876
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h58
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.cpp54
-rw-r--r--Source/JavaScriptCore/runtime/JSLock.h29
-rw-r--r--Source/JavaScriptCore/runtime/JSNameScope.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/JSNameScope.h8
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.h8
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp103
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp712
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h610
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.h29
-rw-r--r--Source/JavaScriptCore/runtime/JSProxy.cpp18
-rw-r--r--Source/JavaScriptCore/runtime/JSProxy.h28
-rw-r--r--Source/JavaScriptCore/runtime/JSScope.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/JSScope.h20
-rw-r--r--Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h9
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h892
-rw-r--r--Source/JavaScriptCore/runtime/JSStringBuilder.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSStringJoiner.cpp22
-rw-r--r--Source/JavaScriptCore/runtime/JSStringJoiner.h13
-rw-r--r--Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/JSSymbolTableObject.h22
-rw-r--r--Source/JavaScriptCore/runtime/JSTypeInfo.h3
-rw-r--r--Source/JavaScriptCore/runtime/JSValueInlines.h497
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSWithScope.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSWithScope.h16
-rw-r--r--Source/JavaScriptCore/runtime/JSWrapperObject.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSWrapperObject.h32
-rw-r--r--Source/JavaScriptCore/runtime/LiteralParser.cpp42
-rw-r--r--Source/JavaScriptCore/runtime/LiteralParser.h2
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.cpp24
-rw-r--r--Source/JavaScriptCore/runtime/Lookup.h47
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.cpp45
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.h4
-rw-r--r--Source/JavaScriptCore/runtime/MemoryStatistics.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/MemoryStatistics.h2
-rw-r--r--Source/JavaScriptCore/runtime/NameConstructor.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/NameConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/NameInstance.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/NameInstance.h16
-rw-r--r--Source/JavaScriptCore/runtime/NamePrototype.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/NamePrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorConstructor.h12
-rw-r--r--Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/NumberConstructor.h4
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/NumberObject.h14
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.cpp38
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.cpp50
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.h30
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.cpp59
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.h17
-rw-r--r--Source/JavaScriptCore/runtime/Operations.cpp26
-rw-r--r--Source/JavaScriptCore/runtime/Operations.h526
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp63
-rw-r--r--Source/JavaScriptCore/runtime/Options.h47
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.h2
-rw-r--r--Source/JavaScriptCore/runtime/PropertyMapHashTable.h131
-rw-r--r--Source/JavaScriptCore/runtime/PropertyNameArray.h12
-rw-r--r--Source/JavaScriptCore/runtime/PropertyOffset.h21
-rw-r--r--Source/JavaScriptCore/runtime/PropertySlot.cpp1
-rw-r--r--Source/JavaScriptCore/runtime/PropertySlot.h2
-rw-r--r--Source/JavaScriptCore/runtime/PropertyTable.cpp146
-rw-r--r--Source/JavaScriptCore/runtime/Protect.h2
-rw-r--r--Source/JavaScriptCore/runtime/PrototypeMap.cpp75
-rw-r--r--Source/JavaScriptCore/runtime/PrototypeMap.h65
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp64
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.h26
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCache.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCache.h5
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCachedResult.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCachedResult.h12
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp11
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.h20
-rw-r--r--Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/RegExpMatchesArray.h8
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h12
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.h4
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.cpp32
-rw-r--r--Source/JavaScriptCore/runtime/SmallStrings.h27
-rw-r--r--Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp23
-rw-r--r--Source/JavaScriptCore/runtime/SparseArrayValueMap.h8
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/StrictEvalActivation.h6
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/StringConstructor.h6
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.h16
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp159
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.h19
-rw-r--r--Source/JavaScriptCore/runtime/StringRecursionChecker.cpp3
-rw-r--r--Source/JavaScriptCore/runtime/StringRecursionChecker.h10
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp469
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h843
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.h16
-rw-r--r--Source/JavaScriptCore/runtime/StructureInlines.h226
-rw-r--r--Source/JavaScriptCore/runtime/StructureRareData.cpp83
-rw-r--r--Source/JavaScriptCore/runtime/StructureRareData.h76
-rw-r--r--Source/JavaScriptCore/runtime/StructureRareDataInlines.h60
-rw-r--r--Source/JavaScriptCore/runtime/StructureTransitionTable.h22
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.h661
-rw-r--r--Source/JavaScriptCore/runtime/Terminator.h47
-rw-r--r--Source/JavaScriptCore/runtime/TimeoutChecker.cpp147
-rw-r--r--Source/JavaScriptCore/runtime/TimeoutChecker.h74
-rw-r--r--Source/JavaScriptCore/runtime/Uint16WithFraction.h2
-rw-r--r--Source/JavaScriptCore/runtime/VM.cpp (renamed from Source/JavaScriptCore/runtime/JSGlobalData.cpp)165
-rw-r--r--Source/JavaScriptCore/runtime/VM.h (renamed from Source/JavaScriptCore/runtime/JSGlobalData.h)157
-rw-r--r--Source/JavaScriptCore/runtime/VMStackBounds.h71
-rw-r--r--Source/JavaScriptCore/runtime/Watchdog.cpp199
-rw-r--r--Source/JavaScriptCore/runtime/Watchdog.h116
-rw-r--r--Source/JavaScriptCore/runtime/WatchdogMac.cpp72
-rw-r--r--Source/JavaScriptCore/runtime/WatchdogNone.cpp50
-rw-r--r--Source/JavaScriptCore/runtime/WeakGCMap.h118
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h34
219 files changed, 8101 insertions, 6420 deletions
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<Register, inlineCapacity> VectorType;
typedef HashSet<MarkedArgumentBuffer*> 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<Arguments*>(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<Arguments*>(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<Arguments*>(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<Arguments*>(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<Arguments*>(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<Arguments*>(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<Arguments>(globalData.heap)) Arguments(callFrame);
+ Arguments* arguments = new (NotNull, allocateCell<Arguments>(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<Arguments>(globalData.heap)) Arguments(callFrame);
+ Arguments* arguments = new (NotNull, allocateCell<Arguments>(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<Unknown>& 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<JSFunction*>(callFrame->callee());
m_numArguments = callFrame->argumentCount();
m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(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<WriteBarrierBase<Unknown>*>(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<JSArray::ShiftCountMode shiftCountMode>
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<JSArray::ShiftCountMode shiftCountMode>
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<RefPtr<StringImpl>, 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<LChar> 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<StringImpl> 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<UChar> 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<StringImpl> 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<uint32_t, 0, UnsafeVectorOverflow> 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<unsigned>(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<int>(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<ArrayStorage*>(butterfly); }
+ static ArrayStorage* from(Butterfly* butterfly) { return reinterpret_cast_ptr<ArrayStorage*>(butterfly); }
static ArrayStorage* from(IndexingHeader* indexingHeader) { return indexingHeader->arrayStorage(); }
Butterfly* butterfly() { return reinterpret_cast<Butterfly*>(this); }
@@ -72,7 +72,9 @@ public:
{
return m_sparseMap && m_sparseMap->sparseMode();
}
-
+
+ ContiguousJSValues vector() { return ContiguousJSValues(m_vector, vectorLength()); }
+
WriteBarrier<SparseArrayValueMap> 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<BooleanObject>(globalData.heap)) BooleanObject(globalData, structure);
- boolean->finishCreation(globalData);
+ BooleanObject* boolean = new (NotNull, allocateCell<BooleanObject>(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 <typename T> 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<double> ContiguousDoubles;
+typedef ContiguousData<WriteBarrier<Unknown> > 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<typename T>
- T* indexingPayload() { return reinterpret_cast<T*>(this); }
+ T* indexingPayload() { return reinterpret_cast_ptr<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> >(); }
+ ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
+
+ ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload<double>(), vectorLength()); }
+ ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
static Butterfly* fromContiguous(WriteBarrier<Unknown>* 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<int64_t>(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 <typename T> struct CacheTypes { };
template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
typedef JSC::ProgramNode RootNode;
- static const CodeCache::CodeType codeType = CodeCache::ProgramType;
+ static const SourceCodeKey::CodeType codeType = SourceCodeKey::ProgramType;
};
template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
typedef JSC::EvalNode RootNode;
- static const CodeCache::CodeType codeType = CodeCache::EvalType;
+ static const SourceCodeKey::CodeType codeType = SourceCodeKey::EvalType;
};
template <class UnlinkedCodeBlockType, class ExecutableType>
-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<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());
- unsigned firstLine = source.firstLine() + unlinkedCode->firstLine();
- executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount());
- return unlinkedCode;
- }
- storeInCache = true;
- }
-
typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
- RefPtr<RootNode> rootNode = parse<RootNode>(&globalData, source, 0, Identifier(), strictness, JSParseProgramCode, error);
+ RefPtr<RootNode> rootNode = parse<RootNode>(&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<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(globalData, rootNode.get(), unlinkedCode, debuggerMode, profilerMode)));
+ OwnPtr<BytecodeGenerator> 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<UnlinkedCodeBlock>(globalData, unlinkedCode));
-
return unlinkedCode;
}
-UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(JSGlobalData& globalData, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+template <class UnlinkedCodeBlockType, class ExecutableType>
+UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, JSScope* scope, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
{
- return getCodeBlock<UnlinkedProgramCodeBlock>(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<UnlinkedCodeBlockType>::codeType == SourceCodeKey::EvalType) {
+ if (scope->next() && !scope->isActivationObject())
+ return generateBytecode<UnlinkedCodeBlockType, ExecutableType>(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<UnlinkedEvalCodeBlock>(globalData, executable, source, strictness, debuggerMode, profilerMode, error);
-}
+ SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes<UnlinkedCodeBlockType>::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<FunctionBodyNode> body = parse<FunctionBodyNode>(&globalData, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error);
+ if (!addResult.isNewEntry && canCache) {
+ UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(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<UnlinkedCodeBlockType, ExecutableType>(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<BytecodeGenerator> 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<UnlinkedFunctionCodeBlock>(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<UnlinkedProgramCodeBlock>(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<UnlinkedEvalCodeBlock>(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<UnlinkedFunctionExecutable>* 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<UnlinkedFunctionExecutable*>(addResult.iterator->value.cell.get());
- RefPtr<ProgramNode> program = parse<ProgramNode>(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+ RefPtr<ProgramNode> program = parse<ProgramNode>(&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<ExprStatementNode*>(exprStatement)->expr();
ASSERT(funcExpr);
- ASSERT(funcExpr->isFuncExprNode());
+ RELEASE_ASSERT(funcExpr->isFuncExprNode());
FunctionBodyNode* body = static_cast<FuncExprNode*>(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<UnlinkedFunctionExecutable>(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<UnlinkedFunctionCodeBlock>(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 <wtf/CurrentTime.h>
#include <wtf/FixedArray.h>
#include <wtf/Forward.h>
#include <wtf/PassOwnPtr.h>
@@ -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 <typename KeyType, typename EntryType, int CacheSize> class CacheMap {
- typedef typename HashMap<KeyType, unsigned>::iterator iterator;
+class SourceCodeKey {
public:
- CacheMap()
- : m_randomGenerator((static_cast<uint32_t>(randomNumber() * std::numeric_limits<uint32_t>::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<SourceCodeKey> {
+ 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<JSCell> cell;
+ int64_t age;
+};
+
+class CodeCacheMap {
+public:
+ typedef HashMap<SourceCodeKey, SourceCodeValue, SourceCodeKeyHash, SourceCodeKeyHashTraits> 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<KeyType, unsigned> m_map;
- FixedArray<std::pair<KeyType, EntryType>, 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<size_t>(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 <script>, eval(), new Function, and JSEvaluateScript().
+class CodeCache : public RefCounted<CodeCache> {
public:
- static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); }
+ enum CodeCacheKind { GlobalCodeCache, NonGlobalCodeCache };
+ static PassRefPtr<CodeCache> create(CodeCacheKind kind) { return adoptRef(new CodeCache(kind)); }
- UnlinkedProgramCodeBlock* getProgramCodeBlock(JSGlobalData&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
- 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*);
+ UnlinkedProgramCodeBlock* getProgramCodeBlock(VM&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+ UnlinkedEvalCodeBlock* getEvalCodeBlock(VM&, JSScope*, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+ UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(VM&, const Identifier&, const SourceCode&, ParserError&);
~CodeCache();
- enum CodeType { EvalType, ProgramType, FunctionType };
- typedef std::pair<String, unsigned> CodeBlockKey;
- typedef std::pair<String, String> GlobalFunctionKey;
+ void clear()
+ {
+ m_sourceCode.clear();
+ }
private:
- CodeCache();
-
- UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+ CodeCache(CodeCacheKind);
- template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
- CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness);
- GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&);
+ template <class UnlinkedCodeBlockType, class ExecutableType>
+ UnlinkedCodeBlockType* getCodeBlock(VM&, JSScope*, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
- enum {
- kMaxCodeBlockEntries = 1024,
- kMaxGlobalFunctionEntries = 1024,
- kMaxFunctionCodeBlocks = 1024
- };
+ template <class UnlinkedCodeBlockType, class ExecutableType>
+ UnlinkedCodeBlockType* generateBytecode(VM&, JSScope*, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
- CacheMap<CodeBlockKey, Strong<UnlinkedCodeBlock>, kMaxCodeBlockEntries> m_cachedCodeBlocks;
- CacheMap<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable>, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions;
- CacheMap<UnlinkedFunctionCodeBlock*, Strong<UnlinkedFunctionCodeBlock>, kMaxFunctionCodeBlocks> m_cachedFunctionCode;
+ CodeCacheMap m_sourceCode;
};
}
-#endif
+#endif // CodeCache_h
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp b/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp
index e929d7a49..e19df1c64 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.cpp
@@ -23,15 +23,15 @@
namespace JSC {
-#define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
-#define INITIALIZE_KEYWORD(name) , name##Keyword(globalData, #name)
+#define INITIALIZE_PROPERTY_NAME(name) , name(vm, #name)
+#define INITIALIZE_KEYWORD(name) , name##Keyword(vm, #name)
-CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
+CommonIdentifiers::CommonIdentifiers(VM* vm)
: nullIdentifier()
, emptyIdentifier(Identifier::EmptyIdentifier)
- , underscoreProto(globalData, "__proto__")
- , thisIdentifier(globalData, "this")
- , useStrictIdentifier(globalData, "use strict")
+ , underscoreProto(vm, "__proto__")
+ , thisIdentifier(vm, "this")
+ , useStrictIdentifier(vm, "use strict")
JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(INITIALIZE_KEYWORD)
JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
{
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index ae3b45b8c..13cf037d5 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -27,40 +27,93 @@
// MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various
// ways without repeating the list.
#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+ macro(Array) \
+ macro(Boolean) \
+ macro(Date) \
+ macro(Error) \
+ macro(EvalError) \
+ macro(Function) \
+ macro(Infinity) \
+ macro(JSON) \
+ macro(Math) \
+ macro(NaN) \
+ macro(Number) \
+ macro(Object) \
+ macro(RangeError) \
+ macro(ReferenceError) \
+ macro(RegExp) \
+ macro(String) \
+ macro(SyntaxError) \
+ macro(TypeError) \
+ macro(URIError) \
+ macro(UTC) \
+ macro(__defineGetter__) \
+ macro(__defineSetter__) \
+ macro(__lookupGetter__) \
+ macro(__lookupSetter__) \
+ macro(anonymous) \
macro(apply) \
macro(arguments) \
- macro(Array) \
macro(bind) \
+ macro(bytecode) \
+ macro(bytecodeIndex) \
+ macro(bytecodes) \
+ macro(bytecodesID) \
macro(call) \
macro(callee) \
macro(caller) \
+ macro(compilationKind) \
+ macro(compilations) \
macro(compile) \
macro(configurable) \
macro(constructor) \
+ macro(count) \
+ macro(counters) \
+ macro(description) \
+ macro(descriptions) \
+ macro(displayName) \
+ macro(document) \
macro(enumerable) \
macro(eval) \
macro(exec) \
+ macro(executionCount) \
+ macro(exitKind) \
macro(fromCharCode) \
- macro(global) \
macro(get) \
+ macro(global) \
macro(hasOwnProperty) \
+ macro(hash) \
+ macro(header) \
+ macro(id) \
macro(ignoreCase) \
macro(index) \
+ macro(inferredName) \
macro(input) \
+ macro(instructionCount) \
macro(isArray) \
macro(isPrototypeOf) \
+ macro(isWatchpoint) \
+ macro(join) \
macro(lastIndex) \
macro(length) \
macro(message) \
macro(multiline) \
macro(name) \
macro(now) \
- macro(Object) \
+ macro(numInlinedCalls) \
+ macro(numInlinedGetByIds) \
+ macro(numInlinedPutByIds) \
+ macro(opcode) \
+ macro(origin) \
+ macro(osrExitSites) \
+ macro(osrExits) \
macro(parse) \
+ macro(profiledBytecodes) \
macro(propertyIsEnumerable) \
macro(prototype) \
macro(set) \
macro(source) \
+ macro(sourceCode) \
macro(stack) \
macro(test) \
macro(toExponential) \
@@ -70,12 +123,10 @@
macro(toLocaleString) \
macro(toPrecision) \
macro(toString) \
- macro(UTC) \
macro(value) \
macro(valueOf) \
- macro(writable) \
- macro(displayName) \
- macro(join)
+ macro(window) \
+ macro(writable)
#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
macro(null) \
@@ -130,8 +181,8 @@ namespace JSC {
class CommonIdentifiers {
WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED;
private:
- CommonIdentifiers(JSGlobalData*);
- friend class JSGlobalData;
+ CommonIdentifiers(VM*);
+ friend class VM;
public:
const Identifier nullIdentifier;
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
index 2f5159461..731b773f0 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -78,7 +78,7 @@ ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, JSStack* stack, CodeSpec
inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
{
if (!baseVal.isObject()) {
- exec->globalData().exception = createInvalidParamError(exec, "in", baseVal);
+ exec->vm().exception = createInvalidParameterError(exec, "in", baseVal);
return false;
}
@@ -92,7 +92,7 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
return baseObj->hasProperty(exec, jsCast<NameInstance*>(propName.asCell())->privateName());
Identifier property(exec, propName.toString(exec)->value(exec));
- if (exec->globalData().exception)
+ if (exec->vm().exception)
return false;
return baseObj->hasProperty(exec, property);
}
diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp
index 3de8d4841..a2d8a6b5f 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -25,11 +25,12 @@
#include "CallFrame.h"
#include "CodeProfiling.h"
+#include "Debugger.h"
+#include "Interpreter.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
-#include "Interpreter.h"
+#include "Operations.h"
#include "Parser.h"
-#include "Debugger.h"
#include <wtf/WTFThreadData.h>
#include <stdio.h>
@@ -38,7 +39,7 @@ namespace JSC {
bool checkSyntax(ExecState* exec, const SourceCode& source, JSValue* returnedException)
{
JSLockHolder lock(exec);
- ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
+ RELEASE_ASSERT(exec->vm().identifierTable == wtfThreadData().currentIdentifierTable());
ProgramExecutable* program = ProgramExecutable::create(exec, source);
JSObject* error = program->checkSyntax(exec);
@@ -50,22 +51,29 @@ bool checkSyntax(ExecState* exec, const SourceCode& source, JSValue* returnedExc
return true;
}
+
+bool checkSyntax(VM& vm, const SourceCode& source, ParserError& error)
+{
+ JSLockHolder lock(vm);
+ RELEASE_ASSERT(vm.identifierTable == wtfThreadData().currentIdentifierTable());
+ RefPtr<ProgramNode> programNode = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+ return programNode;
+}
JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, JSValue* returnedException)
{
JSLockHolder lock(exec);
- ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
- if (exec->globalData().isCollectorBusy())
- CRASH();
+ RELEASE_ASSERT(exec->vm().identifierTable == wtfThreadData().currentIdentifierTable());
+ RELEASE_ASSERT(!exec->vm().isCollectorBusy());
CodeProfiling profile(source);
ProgramExecutable* program = ProgramExecutable::create(exec, source);
if (!program) {
if (returnedException)
- *returnedException = exec->globalData().exception;
+ *returnedException = exec->vm().exception;
- exec->globalData().exception = JSValue();
+ exec->vm().exception = JSValue();
return jsUndefined();
}
@@ -82,7 +90,7 @@ JSValue evaluate(ExecState* exec, const SourceCode& source, JSValue thisValue, J
return jsUndefined();
}
- ASSERT(result);
+ RELEASE_ASSERT(result);
return result;
}
diff --git a/Source/JavaScriptCore/runtime/Completion.h b/Source/JavaScriptCore/runtime/Completion.h
index d150fcea2..78f8ac795 100644
--- a/Source/JavaScriptCore/runtime/Completion.h
+++ b/Source/JavaScriptCore/runtime/Completion.h
@@ -23,14 +23,17 @@
#ifndef Completion_h
#define Completion_h
-#include "JSValue.h"
+#include "JSCJSValue.h"
namespace JSC {
-
+
+ struct ParserError;
class ExecState;
class JSScope;
class SourceCode;
+ class VM;
+ JS_EXPORT_PRIVATE bool checkSyntax(VM&, const SourceCode&, ParserError&);
JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0);
JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0);
diff --git a/Source/JavaScriptCore/runtime/ConstructData.cpp b/Source/JavaScriptCore/runtime/ConstructData.cpp
index 5da2a911c..3dc46180c 100644
--- a/Source/JavaScriptCore/runtime/ConstructData.cpp
+++ b/Source/JavaScriptCore/runtime/ConstructData.cpp
@@ -30,6 +30,7 @@
#include "Interpreter.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/ConstructData.h b/Source/JavaScriptCore/runtime/ConstructData.h
index 6426b044e..10317a2f9 100644
--- a/Source/JavaScriptCore/runtime/ConstructData.h
+++ b/Source/JavaScriptCore/runtime/ConstructData.h
@@ -30,7 +30,7 @@
#define ConstructData_h
#include "CallData.h"
-#include "JSValue.h"
+#include "JSCJSValue.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index 9a162e9e7..b21a5d0c2 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -31,6 +31,7 @@
#include "JSString.h"
#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include <math.h>
#include <time.h>
#include <wtf/MathExtras.h>
@@ -80,9 +81,9 @@ DateConstructor::DateConstructor(JSGlobalObject* globalObject, Structure* struct
void DateConstructor::finishCreation(ExecState* exec, DatePrototype* datePrototype)
{
- Base::finishCreation(exec->globalData(), datePrototype->classInfo()->className);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
+ Base::finishCreation(exec->vm(), datePrototype->classInfo()->className);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
}
bool DateConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
@@ -124,13 +125,13 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg
args.at(5).toNumber(exec),
args.at(6).toNumber(exec)
};
- if (!isfinite(doubleArguments[0])
- || !isfinite(doubleArguments[1])
- || (numArgs >= 3 && !isfinite(doubleArguments[2]))
- || (numArgs >= 4 && !isfinite(doubleArguments[3]))
- || (numArgs >= 5 && !isfinite(doubleArguments[4]))
- || (numArgs >= 6 && !isfinite(doubleArguments[5]))
- || (numArgs >= 7 && !isfinite(doubleArguments[6])))
+ if (!std::isfinite(doubleArguments[0])
+ || !std::isfinite(doubleArguments[1])
+ || (numArgs >= 3 && !std::isfinite(doubleArguments[2]))
+ || (numArgs >= 4 && !std::isfinite(doubleArguments[3]))
+ || (numArgs >= 5 && !std::isfinite(doubleArguments[4]))
+ || (numArgs >= 6 && !std::isfinite(doubleArguments[5]))
+ || (numArgs >= 7 && !std::isfinite(doubleArguments[6])))
value = QNaN;
else {
GregorianDateTime t;
@@ -198,13 +199,13 @@ static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec)
exec->argument(6).toNumber(exec)
};
int n = exec->argumentCount();
- if (isnan(doubleArguments[0])
- || isnan(doubleArguments[1])
- || (n >= 3 && isnan(doubleArguments[2]))
- || (n >= 4 && isnan(doubleArguments[3]))
- || (n >= 5 && isnan(doubleArguments[4]))
- || (n >= 6 && isnan(doubleArguments[5]))
- || (n >= 7 && isnan(doubleArguments[6])))
+ if (std::isnan(doubleArguments[0])
+ || std::isnan(doubleArguments[1])
+ || (n >= 3 && std::isnan(doubleArguments[2]))
+ || (n >= 4 && std::isnan(doubleArguments[3]))
+ || (n >= 5 && std::isnan(doubleArguments[4]))
+ || (n >= 6 && std::isnan(doubleArguments[5]))
+ || (n >= 7 && std::isnan(doubleArguments[6])))
return JSValue::encode(jsNaN());
GregorianDateTime t;
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h
index f089e036c..5a6200e99 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.h
+++ b/Source/JavaScriptCore/runtime/DateConstructor.h
@@ -40,9 +40,9 @@ namespace JSC {
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/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp
index 47a19df47..db7b84634 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.cpp
+++ b/Source/JavaScriptCore/runtime/DateInstance.cpp
@@ -24,7 +24,7 @@
#include "JSDateMath.h"
#include "JSGlobalObject.h"
-
+#include "Operations.h"
#include <math.h>
#include <wtf/MathExtras.h>
@@ -35,22 +35,22 @@ namespace JSC {
const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(DateInstance)};
DateInstance::DateInstance(ExecState* exec, Structure* structure)
- : JSWrapperObject(exec->globalData(), structure)
+ : JSWrapperObject(exec->vm(), structure)
{
}
-void DateInstance::finishCreation(JSGlobalData& globalData)
+void DateInstance::finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
- setInternalValue(globalData, jsNaN());
+ setInternalValue(vm, jsNaN());
}
-void DateInstance::finishCreation(JSGlobalData& globalData, double time)
+void DateInstance::finishCreation(VM& vm, double time)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
- setInternalValue(globalData, jsNumber(timeClip(time)));
+ setInternalValue(vm, jsNumber(timeClip(time)));
}
void DateInstance::destroy(JSCell* cell)
@@ -61,11 +61,11 @@ void DateInstance::destroy(JSCell* cell)
const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
{
double milli = internalNumber();
- if (isnan(milli))
+ if (std::isnan(milli))
return 0;
if (!m_data)
- m_data = exec->globalData().dateInstanceCache.add(milli);
+ m_data = exec->vm().dateInstanceCache.add(milli);
if (m_data->m_gregorianDateTimeCachedForMS != milli) {
msToGregorianDateTime(exec, milli, false, m_data->m_cachedGregorianDateTime);
@@ -77,11 +77,11 @@ const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exe
const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(ExecState* exec) const
{
double milli = internalNumber();
- if (isnan(milli))
+ if (std::isnan(milli))
return 0;
if (!m_data)
- m_data = exec->globalData().dateInstanceCache.add(milli);
+ m_data = exec->vm().dateInstanceCache.add(milli);
if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
msToGregorianDateTime(exec, milli, true, m_data->m_cachedGregorianDateTimeUTC);
diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h
index 9742e6889..870777240 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.h
+++ b/Source/JavaScriptCore/runtime/DateInstance.h
@@ -28,8 +28,8 @@ namespace JSC {
class DateInstance : public JSWrapperObject {
protected:
JS_EXPORT_PRIVATE DateInstance(ExecState*, Structure*);
- void finishCreation(JSGlobalData&);
- JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, double);
+ void finishCreation(VM&);
+ JS_EXPORT_PRIVATE void finishCreation(VM&, double);
static void destroy(JSCell*);
@@ -39,14 +39,14 @@ namespace JSC {
static DateInstance* create(ExecState* exec, Structure* structure, double date)
{
DateInstance* instance = new (NotNull, allocateCell<DateInstance>(*exec->heap())) DateInstance(exec, structure);
- instance->finishCreation(exec->globalData(), date);
+ instance->finishCreation(exec->vm(), date);
return instance;
}
static DateInstance* create(ExecState* exec, Structure* structure)
{
DateInstance* instance = new (NotNull, allocateCell<DateInstance>(*exec->heap())) DateInstance(exec, structure);
- instance->finishCreation(exec->globalData());
+ instance->finishCreation(exec->vm());
return instance;
}
@@ -68,9 +68,9 @@ namespace JSC {
return calculateGregorianDateTimeUTC(exec);
}
- 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);
}
private:
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp
index 75da466fb..9cbaf7480 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp
@@ -33,6 +33,7 @@
#include "JSStringBuilder.h"
#include "Lookup.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#if !PLATFORM(MAC) && HAVE(LANGINFO_H)
#include <langinfo.h>
@@ -46,7 +47,6 @@
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
#include <wtf/StringExtras.h>
-#include <wtf/UnusedParam.h>
#if HAVE(SYS_PARAM_H)
#include <sys/param.h>
@@ -60,7 +60,7 @@
#include <sys/timeb.h>
#endif
-#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WX) && OS(DARWIN)) || (PLATFORM(QT) && OS(DARWIN))
+#if OS(DARWIN) && USE(CF)
#include <CoreFoundation/CoreFoundation.h>
#elif USE(ICU_UNICODE)
#include <unicode/udat.h>
@@ -124,9 +124,9 @@ namespace JSC {
enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
-#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WX) && OS(DARWIN)) || (PLATFORM(QT) && OS(DARWIN))
+#if OS(DARWIN) && USE(CF)
-// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
+// FIXME: Since this is superior to the strftime-based version, why limit this to OS(DARWIN)?
// Instead we should consider using this whenever USE(CF) is true.
static CFDateFormatterStyle styleFromArgString(const String& string, CFDateFormatterStyle defaultStyle)
@@ -245,7 +245,7 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L
length += GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, buffer.data() + length, buffer.size() - length);
}
} else
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
// Remove terminating null character.
if (length)
@@ -336,7 +336,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl
return formatLocaleDate(exec, *gregorianDateTime, format);
}
-#endif // !PLATFORM(MAC) && !PLATFORM(IOS)
+#endif // OS(DARWIN) && USE(CF)
static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format, bool asUTCVariant)
{
@@ -374,7 +374,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
if (maxArgs >= 4 && idx < numArgs) {
t->setHour(0);
double hours = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(hours);
+ ok = std::isfinite(hours);
milliseconds += hours * msPerHour;
}
@@ -382,7 +382,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
if (maxArgs >= 3 && idx < numArgs && ok) {
t->setMinute(0);
double minutes = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(minutes);
+ ok = std::isfinite(minutes);
milliseconds += minutes * msPerMinute;
}
@@ -390,7 +390,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
if (maxArgs >= 2 && idx < numArgs && ok) {
t->setSecond(0);
double seconds = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(seconds);
+ ok = std::isfinite(seconds);
milliseconds += seconds * msPerSecond;
}
@@ -400,7 +400,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
// milliseconds
if (idx < numArgs) {
double millis = exec->argument(idx).toIntegerPreserveNaN(exec);
- ok = isfinite(millis);
+ ok = std::isfinite(millis);
milliseconds += millis;
} else
milliseconds += *ms;
@@ -426,19 +426,19 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms
// years
if (maxArgs >= 3 && idx < numArgs) {
double years = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(years);
+ ok = std::isfinite(years);
t->setYear(toInt32(years));
}
// months
if (maxArgs >= 2 && idx < numArgs && ok) {
double months = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(months);
+ ok = std::isfinite(months);
t->setMonth(toInt32(months));
}
// days
if (idx < numArgs && ok) {
double days = exec->argument(idx++).toIntegerPreserveNaN(exec);
- ok = isfinite(days);
+ ok = std::isfinite(days);
t->setMonthDay(0);
*ms += days * msPerDay;
}
@@ -508,7 +508,7 @@ DatePrototype::DatePrototype(ExecState* exec, Structure* structure)
void DatePrototype::finishCreation(ExecState* exec, JSGlobalObject*)
{
- Base::finishCreation(exec->globalData());
+ Base::finishCreation(exec->vm());
ASSERT(inherits(&s_info));
// The constructor will be added later, after DateConstructor has been built.
@@ -545,7 +545,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
return throwVMTypeError(exec);
DateInstance* thisDateObj = asDateInstance(thisValue);
- if (!isfinite(thisDateObj->internalNumber()))
+ if (!std::isfinite(thisDateObj->internalNumber()))
return throwVMError(exec, createRangeError(exec, ASCIILiteral("Invalid Date")));
const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
@@ -833,7 +833,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
DateInstance* thisDateObj = asDateInstance(thisValue);
double milli = thisDateObj->internalNumber();
- if (isnan(milli))
+ if (std::isnan(milli))
return JSValue::encode(jsNaN());
double secs = floor(milli / msPerSecond);
@@ -849,7 +849,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
DateInstance* thisDateObj = asDateInstance(thisValue);
double milli = thisDateObj->internalNumber();
- if (isnan(milli))
+ if (std::isnan(milli))
return JSValue::encode(jsNaN());
double secs = floor(milli / msPerSecond);
@@ -881,7 +881,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
double milli = timeClip(exec->argument(0).toNumber(exec));
JSValue result = jsNumber(milli);
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -894,9 +894,9 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
DateInstance* thisDateObj = asDateInstance(thisValue);
double milli = thisDateObj->internalNumber();
- if (!exec->argumentCount() || isnan(milli)) {
+ if (!exec->argumentCount() || std::isnan(milli)) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -913,12 +913,12 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
gregorianDateTime.copyFrom(*other);
if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -931,7 +931,7 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
DateInstance* thisDateObj = asDateInstance(thisValue);
if (!exec->argumentCount()) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -939,7 +939,7 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
double ms = 0;
GregorianDateTime gregorianDateTime;
- if (numArgsToUse == 3 && isnan(milli))
+ if (numArgsToUse == 3 && std::isnan(milli))
msToGregorianDateTime(exec, 0, true, gregorianDateTime);
else {
ms = milli - floor(milli / msPerSecond) * msPerSecond;
@@ -953,12 +953,12 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -1055,7 +1055,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
DateInstance* thisDateObj = asDateInstance(thisValue);
if (!exec->argumentCount()) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -1063,7 +1063,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
double ms = 0;
GregorianDateTime gregorianDateTime;
- if (isnan(milli))
+ if (std::isnan(milli))
// Based on ECMA 262 B.2.5 (setYear)
// the time must be reset to +0 if it is NaN.
msToGregorianDateTime(exec, 0, true, gregorianDateTime);
@@ -1075,15 +1075,15 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
}
double year = exec->argument(0).toIntegerPreserveNaN(exec);
- if (!isfinite(year)) {
+ if (!std::isfinite(year)) {
JSValue result = jsNaN();
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
- thisDateObj->setInternalValue(exec->globalData(), result);
+ thisDateObj->setInternalValue(exec->vm(), result);
return JSValue::encode(result);
}
@@ -1110,7 +1110,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsNull());
- JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
+ JSValue toISOValue = object->get(exec, exec->vm().propertyNames->toISOString);
if (exec->hadException())
return JSValue::encode(jsNull());
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.h b/Source/JavaScriptCore/runtime/DatePrototype.h
index c4f6d6916..85f7d46d7 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.h
+++ b/Source/JavaScriptCore/runtime/DatePrototype.h
@@ -46,9 +46,9 @@ namespace JSC {
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/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index 68ae12d90..9cbe20b97 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -34,6 +34,7 @@
#include "JSObject.h"
#include "JSString.h"
#include "NativeErrorConstructor.h"
+#include "Operations.h"
#include "SourceCode.h"
#include <wtf/text/StringBuilder.h>
@@ -46,37 +47,37 @@ static const char* sourceURLPropertyName = "sourceURL";
JSObject* createError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->errorStructure(), message);
}
JSObject* createEvalError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->evalErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->evalErrorConstructor()->errorStructure(), message);
}
JSObject* createRangeError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->rangeErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->rangeErrorConstructor()->errorStructure(), message);
}
JSObject* createReferenceError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->referenceErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->referenceErrorConstructor()->errorStructure(), message);
}
JSObject* createSyntaxError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->syntaxErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->syntaxErrorConstructor()->errorStructure(), message);
}
JSObject* createTypeError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->typeErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->typeErrorConstructor()->errorStructure(), message);
}
JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject)
@@ -87,7 +88,7 @@ JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject)
JSObject* createURIError(JSGlobalObject* globalObject, const String& message)
{
ASSERT(!message.isEmpty());
- return ErrorInstance::create(globalObject->globalData(), globalObject->URIErrorConstructor()->errorStructure(), message);
+ return ErrorInstance::create(globalObject->vm(), globalObject->URIErrorConstructor()->errorStructure(), message);
}
JSObject* createError(ExecState* exec, const String& message)
@@ -132,15 +133,15 @@ JSObject* createURIError(ExecState* exec, const String& message)
JSObject* addErrorInfo(CallFrame* callFrame, JSObject* error, int line, const SourceCode& source)
{
- JSGlobalData* globalData = &callFrame->globalData();
+ VM* vm = &callFrame->vm();
const String& sourceURL = source.provider()->url();
if (line != -1)
- error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
+ error->putDirect(*vm, Identifier(vm, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
if (!sourceURL.isNull())
- error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
+ error->putDirect(*vm, Identifier(vm, sourceURLPropertyName), jsString(vm, sourceURL), ReadOnly | DontDelete);
- globalData->interpreter->addStackTraceIfNecessary(callFrame, error);
+ vm->interpreter->addStackTraceIfNecessary(callFrame, error);
return error;
}
@@ -154,16 +155,15 @@ bool hasErrorInfo(ExecState* exec, JSObject* error)
JSValue throwError(ExecState* exec, JSValue error)
{
- if (error.isObject())
- return throwError(exec, asObject(error));
- exec->globalData().exception = error;
+ Interpreter::addStackTraceIfNecessary(exec, error);
+ exec->vm().exception = error;
return error;
}
JSObject* throwError(ExecState* exec, JSObject* error)
{
Interpreter::addStackTraceIfNecessary(exec, error);
- exec->globalData().exception = error;
+ exec->vm().exception = error;
return error;
}
diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h
index 9c34a0574..36e425d7e 100644
--- a/Source/JavaScriptCore/runtime/Error.h
+++ b/Source/JavaScriptCore/runtime/Error.h
@@ -31,7 +31,7 @@
namespace JSC {
class ExecState;
- class JSGlobalData;
+ class VM;
class JSGlobalObject;
class JSObject;
class SourceCode;
@@ -89,7 +89,7 @@ namespace JSC {
static StrictModeTypeErrorFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const String& message)
{
StrictModeTypeErrorFunction* function = new (NotNull, allocateCell<StrictModeTypeErrorFunction>(*exec->heap())) StrictModeTypeErrorFunction(globalObject, structure, message);
- function->finishCreation(exec->globalData(), String());
+ function->finishCreation(exec->vm(), String());
return function;
}
@@ -119,9 +119,9 @@ namespace JSC {
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);
}
private:
diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
index f2578a497..b143f5a18 100644
--- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
@@ -24,6 +24,7 @@
#include "ErrorPrototype.h"
#include "JSGlobalObject.h"
#include "JSString.h"
+#include "Operations.h"
namespace JSC {
@@ -38,10 +39,10 @@ ErrorConstructor::ErrorConstructor(JSGlobalObject* globalObject, Structure* stru
void ErrorConstructor::finishCreation(ExecState* exec, ErrorPrototype* errorPrototype)
{
- Base::finishCreation(exec->globalData(), errorPrototype->classInfo()->className);
+ Base::finishCreation(exec->vm(), errorPrototype->classInfo()->className);
// ECMA 15.11.3.1 Error.prototype
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
}
// ECMA 15.9.3
diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.h b/Source/JavaScriptCore/runtime/ErrorConstructor.h
index 58399a9bc..b8e3b841b 100644
--- a/Source/JavaScriptCore/runtime/ErrorConstructor.h
+++ b/Source/JavaScriptCore/runtime/ErrorConstructor.h
@@ -41,9 +41,9 @@ namespace JSC {
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/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
index 9c0fe3e8b..e8f7ac162 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -22,6 +22,7 @@
#include "ErrorInstance.h"
#include "JSScope.h"
+#include "Operations.h"
namespace JSC {
@@ -29,8 +30,8 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorInstance);
const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ErrorInstance) };
-ErrorInstance::ErrorInstance(JSGlobalData& globalData, Structure* structure)
- : JSNonFinalObject(globalData, structure)
+ErrorInstance::ErrorInstance(VM& vm, Structure* structure)
+ : JSNonFinalObject(vm, structure)
, m_appendSourceToMessage(false)
{
}
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h
index 894676361..26a8b31ea 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.h
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.h
@@ -31,21 +31,21 @@ namespace JSC {
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(ErrorInstanceType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ErrorInstanceType, StructureFlags), &s_info);
}
- static ErrorInstance* create(JSGlobalData& globalData, Structure* structure, const String& message)
+ static ErrorInstance* create(VM& vm, Structure* structure, const String& message)
{
- ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(globalData.heap)) ErrorInstance(globalData, structure);
- instance->finishCreation(globalData, message);
+ ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(vm.heap)) ErrorInstance(vm, structure);
+ instance->finishCreation(vm, message);
return instance;
}
static ErrorInstance* create(ExecState* exec, Structure* structure, JSValue message)
{
- return create(exec->globalData(), structure, message.isUndefined() ? String() : message.toString(exec)->value(exec));
+ return create(exec->vm(), structure, message.isUndefined() ? String() : message.toString(exec)->value(exec));
}
bool appendSourceToMessage() { return m_appendSourceToMessage; }
@@ -53,14 +53,14 @@ namespace JSC {
void clearAppendSourceToMessage() { m_appendSourceToMessage = false; }
protected:
- explicit ErrorInstance(JSGlobalData&, Structure*);
+ explicit ErrorInstance(VM&, Structure*);
- void finishCreation(JSGlobalData& globalData, const String& message)
+ void finishCreation(VM& vm, const String& message)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
if (!message.isNull())
- putDirect(globalData, globalData.propertyNames->message, jsString(&globalData, message), DontEnum);
+ putDirect(vm, vm.propertyNames->message, jsString(&vm, message), DontEnum);
}
bool m_appendSourceToMessage;
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
index a30efdc31..bab3a7440 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -26,6 +26,7 @@
#include "JSString.h"
#include "JSStringBuilder.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include "StringRecursionChecker.h"
namespace JSC {
@@ -49,15 +50,15 @@ const ClassInfo ErrorPrototype::s_info = { "Error", &ErrorInstance::s_info, 0, E
*/
ErrorPrototype::ErrorPrototype(ExecState* exec, Structure* structure)
- : ErrorInstance(exec->globalData(), structure)
+ : ErrorInstance(exec->vm(), structure)
{
}
void ErrorPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
{
- Base::finishCreation(exec->globalData(), "");
+ Base::finishCreation(exec->vm(), "");
ASSERT(inherits(&s_info));
- putDirect(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, String(ASCIILiteral("Error"))), DontEnum);
+ putDirect(exec->vm(), exec->propertyNames().name, jsNontrivialString(exec, String(ASCIILiteral("Error"))), DontEnum);
}
bool ErrorPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.h b/Source/JavaScriptCore/runtime/ErrorPrototype.h
index e961946df..9401b2220 100644
--- a/Source/JavaScriptCore/runtime/ErrorPrototype.h
+++ b/Source/JavaScriptCore/runtime/ErrorPrototype.h
@@ -40,9 +40,9 @@ namespace JSC {
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(ErrorInstanceType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ErrorInstanceType, StructureFlags), &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index a4368a2bb..ccd7a02cb 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -37,36 +37,10 @@
#include "JSNotAnObject.h"
#include "Interpreter.h"
#include "Nodes.h"
+#include "Operations.h"
namespace JSC {
-ASSERT_HAS_TRIVIAL_DESTRUCTOR(InterruptedExecutionError);
-
-const ClassInfo InterruptedExecutionError::s_info = { "InterruptedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(InterruptedExecutionError) };
-
-JSValue InterruptedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
-{
- if (hint == PreferString)
- return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution exceeded timeout.")));
- return JSValue(QNaN);
-}
-
-JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
-{
- return InterruptedExecutionError::create(*globalData);
-}
-
-bool isInterruptedExecutionException(JSObject* object)
-{
- return object->inherits(&InterruptedExecutionError::s_info);
-}
-
-bool isInterruptedExecutionException(JSValue value)
-{
- return value.inherits(&InterruptedExecutionError::s_info);
-}
-
-
ASSERT_HAS_TRIVIAL_DESTRUCTOR(TerminatedExecutionError);
const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(TerminatedExecutionError) };
@@ -78,9 +52,9 @@ JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec,
return JSValue(QNaN);
}
-JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
+JSObject* createTerminatedExecutionException(VM* vm)
{
- return TerminatedExecutionError::create(*globalData);
+ return TerminatedExecutionError::create(*vm);
}
bool isTerminatedExecutionException(JSObject* object)
@@ -110,40 +84,59 @@ JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
return createReferenceError(exec, message);
}
-JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
+JSString* errorDescriptionForValue(ExecState* exec, JSValue v)
+{
+ VM& vm = exec->vm();
+ if (v.isNull())
+ return vm.smallStrings.nullString();
+ if (v.isUndefined())
+ return vm.smallStrings.undefinedString();
+ if (v.isInt32())
+ return jsString(&vm, vm.numericStrings.add(v.asInt32()));
+ if (v.isDouble())
+ return jsString(&vm, vm.numericStrings.add(v.asDouble()));
+ if (v.isTrue())
+ return vm.smallStrings.trueString();
+ if (v.isFalse())
+ return vm.smallStrings.falseString();
+ if (v.isString())
+ return jsCast<JSString*>(v.asCell());
+ if (v.isObject()) {
+ CallData callData;
+ JSObject* object = asObject(v);
+ if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
+ return vm.smallStrings.functionString();
+ }
+ return jsString(exec, asObject(v)->methodTable()->className(asObject(v)));
+}
+
+JSObject* createError(ExecState* exec, ErrorFactory errorFactory, JSValue value, const String& message)
{
- String errorMessage = makeString("'", value.toString(exec)->value(exec), "' is not a valid argument for '", op, "'");
- JSObject* exception = createTypeError(exec, errorMessage);
+ String errorMessage = makeString(errorDescriptionForValue(exec, value)->value(exec), " ", message);
+ JSObject* exception = errorFactory(exec, errorMessage);
ASSERT(exception->isErrorInstance());
static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
return exception;
}
+JSObject* createInvalidParameterError(ExecState* exec, const char* op, JSValue value)
+{
+ return createError(exec, createTypeError, value, makeString("is not a valid argument for '", op, "'"));
+}
+
JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
{
- String errorMessage = makeString("'", value.toString(exec)->value(exec), "' is not a constructor");
- JSObject* exception = createTypeError(exec, errorMessage);
- ASSERT(exception->isErrorInstance());
- static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
- return exception;
+ return createError(exec, createTypeError, value, "is not a constructor");
}
JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
{
- String errorMessage = makeString("'", value.toString(exec)->value(exec), "' is not a function");
- JSObject* exception = createTypeError(exec, errorMessage);
- ASSERT(exception->isErrorInstance());
- static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
- return exception;
+ return createError(exec, createTypeError, value, "is not a function");
}
JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
{
- String errorMessage = makeString("'", value.toString(exec)->value(exec), "' is not an object");
- JSObject* exception = createTypeError(exec, errorMessage);
- ASSERT(exception->isErrorInstance());
- static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
- return exception;
+ return createError(exec, createTypeError, value, "is not an object");
}
JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const String& propertyName)
@@ -167,4 +160,10 @@ JSObject* throwStackOverflowError(ExecState* exec)
return throwError(exec, createStackOverflowError(exec));
}
+JSObject* throwTerminatedExecutionException(ExecState* exec)
+{
+ Interpreter::ErrorHandlingMode mode(exec);
+ return throwError(exec, createTerminatedExecutionException(&exec->vm()));
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.h b/Source/JavaScriptCore/runtime/ExceptionHelpers.h
index d2daaa044..bfe1d66af 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -33,59 +33,32 @@
namespace JSC {
-JS_EXPORT_PRIVATE JSObject* createInterruptedExecutionException(JSGlobalData*);
-bool isInterruptedExecutionException(JSObject*);
-bool isInterruptedExecutionException(JSValue);
+typedef JSObject* (*ErrorFactory)(ExecState*, const String&);
-JSObject* createTerminatedExecutionException(JSGlobalData*);
+JSObject* createTerminatedExecutionException(VM*);
bool isTerminatedExecutionException(JSObject*);
JS_EXPORT_PRIVATE bool isTerminatedExecutionException(JSValue);
-
+JS_EXPORT_PRIVATE JSObject* createError(ExecState*, ErrorFactory, JSValue, const String&);
JS_EXPORT_PRIVATE JSObject* createStackOverflowError(ExecState*);
JSObject* createStackOverflowError(JSGlobalObject*);
JSObject* createOutOfMemoryError(JSGlobalObject*);
JSObject* createUndefinedVariableError(ExecState*, const Identifier&);
JSObject* createNotAnObjectError(ExecState*, JSValue);
-JSObject* createInvalidParamError(ExecState*, const char* op, JSValue);
+JSObject* createInvalidParameterError(ExecState*, const char* op, JSValue);
JSObject* createNotAConstructorError(ExecState*, JSValue);
JSObject* createNotAFunctionError(ExecState*, JSValue);
JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const String&);
+JSString* errorDescriptionForValue(ExecState*, JSValue);
JSObject* throwOutOfMemoryError(ExecState*);
JSObject* throwStackOverflowError(ExecState*);
+JSObject* throwTerminatedExecutionException(ExecState*);
-class InterruptedExecutionError : public JSNonFinalObject {
-private:
- InterruptedExecutionError(JSGlobalData& globalData)
- : JSNonFinalObject(globalData, globalData.interruptedExecutionErrorStructure.get())
- {
- }
-
- static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
-
-public:
- typedef JSNonFinalObject Base;
-
- static InterruptedExecutionError* create(JSGlobalData& globalData)
- {
- InterruptedExecutionError* error = new (NotNull, allocateCell<InterruptedExecutionError>(globalData.heap)) InterruptedExecutionError(globalData);
- error->finishCreation(globalData);
- return error;
- }
-
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
- }
-
- static const ClassInfo s_info;
-};
-
class TerminatedExecutionError : public JSNonFinalObject {
private:
- TerminatedExecutionError(JSGlobalData& globalData)
- : JSNonFinalObject(globalData, globalData.terminatedExecutionErrorStructure.get())
+ TerminatedExecutionError(VM& vm)
+ : JSNonFinalObject(vm, vm.terminatedExecutionErrorStructure.get())
{
}
@@ -94,16 +67,16 @@ private:
public:
typedef JSNonFinalObject Base;
- static TerminatedExecutionError* create(JSGlobalData& globalData)
+ static TerminatedExecutionError* create(VM& vm)
{
- TerminatedExecutionError* error = new (NotNull, allocateCell<TerminatedExecutionError>(globalData.heap)) TerminatedExecutionError(globalData);
- error->finishCreation(globalData);
+ TerminatedExecutionError* error = new (NotNull, allocateCell<TerminatedExecutionError>(vm.heap)) TerminatedExecutionError(vm);
+ error->finishCreation(vm);
return error;
}
- 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);
}
static JS_EXPORTDATA const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index ff4c2ff76..918537650 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -33,6 +33,7 @@
#include "ExecutionHarness.h"
#include "JIT.h"
#include "JITDriver.h"
+#include "Operations.h"
#include "Parser.h"
#include <wtf/Vector.h>
#include <wtf/text/StringBuilder.h>
@@ -67,6 +68,11 @@ Intrinsic ExecutableBase::intrinsic() const
return nativeExecutable->intrinsic();
return NoIntrinsic;
}
+#else
+Intrinsic ExecutableBase::intrinsic() const
+{
+ return NoIntrinsic;
+}
#endif
const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
@@ -88,14 +94,14 @@ Intrinsic NativeExecutable::intrinsic() const
#if ENABLE(JIT)
// Utility method used for jettisoning code blocks.
template<typename T>
-static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
+static void jettisonCodeBlock(VM& vm, OwnPtr<T>& codeBlock)
{
ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
ASSERT(codeBlock->alternative());
OwnPtr<T> codeBlockToJettison = codeBlock.release();
codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
codeBlockToJettison->unlinkIncomingCalls();
- globalData.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
+ vm.heap.jettisonDFGCodeBlock(static_pointer_cast<CodeBlock>(codeBlockToJettison.release()));
}
#endif
@@ -110,8 +116,9 @@ void ScriptExecutable::destroy(JSCell* cell)
const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
-EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
- : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
+EvalExecutable::EvalExecutable(ExecState* exec, PassRefPtr<CodeCache> codeCache, const SourceCode& source, bool inStrictContext)
+ : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
+ , m_codeCache(codeCache)
{
}
@@ -123,7 +130,7 @@ void EvalExecutable::destroy(JSCell* cell)
const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
- : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
+ : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
{
}
@@ -134,14 +141,15 @@ void ProgramExecutable::destroy(JSCell* cell)
const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
- : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, unlinkedExecutable->isInStrictContext())
- , m_unlinkedExecutable(globalData, this, unlinkedExecutable)
+FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
+ : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext())
+ , m_unlinkedExecutable(vm, this, unlinkedExecutable)
{
- ASSERT(!source.isNull());
+ RELEASE_ASSERT(!source.isNull());
ASSERT(source.length());
m_firstLine = firstLine;
m_lastLine = lastLine;
+ m_startColumn = startColumn;
}
void FunctionExecutable::destroy(JSCell* cell)
@@ -151,7 +159,7 @@ void FunctionExecutable::destroy(JSCell* cell)
JSObject* EvalExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ ASSERT(exec->vm().dynamicGlobalObject);
ASSERT(!!m_evalCodeBlock);
JSObject* error = 0;
if (m_evalCodeBlock->getJITType() != JITCode::topTierJIT())
@@ -177,7 +185,7 @@ inline const char* samplingDescription(JITCode::JITType jitType)
case JITCode::DFGJIT:
return "DFG Compilation (TOTAL)";
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return 0;
}
}
@@ -190,7 +198,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
UNUSED_PARAM(jitType);
UNUSED_PARAM(bytecodeIndex);
#endif
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
if (!!m_evalCodeBlock) {
@@ -199,19 +207,19 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
m_evalCodeBlock = newCodeBlock.release();
} else {
UNUSED_PARAM(scope);
- UNUSED_PARAM(globalData);
+ UNUSED_PARAM(vm);
UNUSED_PARAM(lexicalGlobalObject);
if (!lexicalGlobalObject->evalEnabled())
return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage()));
JSObject* exception = 0;
- UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(exec, this, &exception);
+ UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(m_codeCache.get(), exec, scope, this, &exception);
if (!unlinkedEvalCode)
return exception;
OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
- m_unlinkedEvalCodeBlock.set(*globalData, this, unlinkedEvalCode);
+ m_unlinkedEvalCodeBlock.set(*vm, this, unlinkedEvalCode);
m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
m_evalCodeBlock->copyPostParseDataFromAlternative();
}
@@ -231,9 +239,9 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
}
#if ENABLE(JIT)
-void EvalExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
+void EvalExecutable::jettisonOptimizedCode(VM& vm)
{
- jettisonCodeBlock(globalData, m_evalCodeBlock);
+ jettisonCodeBlock(vm, m_evalCodeBlock);
m_jitCodeForCall = m_evalCodeBlock->getJITCode();
ASSERT(!m_jitCodeForCallWithArityCheck);
}
@@ -256,7 +264,7 @@ void EvalExecutable::unlinkCalls()
#if ENABLE(JIT)
if (!m_jitCodeForCall)
return;
- ASSERT(m_evalCodeBlock);
+ RELEASE_ASSERT(m_evalCodeBlock);
m_evalCodeBlock->unlinkCalls();
#endif
}
@@ -271,9 +279,9 @@ void EvalExecutable::clearCode()
JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
{
ParserError error;
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
+ RefPtr<ProgramNode> programNode = parse<ProgramNode>(vm, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
if (programNode)
return 0;
ASSERT(error.m_type != ParserError::ErrorNone);
@@ -282,7 +290,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
ASSERT(!!m_programCodeBlock);
JSObject* error = 0;
if (m_programCodeBlock->getJITType() != JITCode::topTierJIT())
@@ -313,7 +321,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI
m_programCodeBlock = newCodeBlock.release();
} else {
JSGlobalObject* globalObject = scope->globalObject();
- m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), m_programCodeBlock.release()));
+ m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), source().startColumn(), m_programCodeBlock.release()));
m_programCodeBlock->copyPostParseDataFromAlternative();
}
@@ -332,9 +340,9 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI
}
#if ENABLE(JIT)
-void ProgramExecutable::jettisonOptimizedCode(JSGlobalData& globalData)
+void ProgramExecutable::jettisonOptimizedCode(VM& vm)
{
- jettisonCodeBlock(globalData, m_programCodeBlock);
+ jettisonCodeBlock(vm, m_programCodeBlock);
m_jitCodeForCall = m_programCodeBlock->getJITCode();
ASSERT(!m_jitCodeForCallWithArityCheck);
}
@@ -345,7 +353,7 @@ void ProgramExecutable::unlinkCalls()
#if ENABLE(JIT)
if (!m_jitCodeForCall)
return;
- ASSERT(m_programCodeBlock);
+ RELEASE_ASSERT(m_programCodeBlock);
m_programCodeBlock->unlinkCalls();
#endif
}
@@ -367,21 +375,21 @@ int ProgramExecutable::addGlobalVar(JSGlobalObject* globalObject, const Identifi
return index;
}
-JSObject* ProgramExecutable::initalizeGlobalProperties(JSGlobalData& globalData, CallFrame* callFrame, JSScope* scope)
+JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
{
- ASSERT(scope);
+ RELEASE_ASSERT(scope);
JSGlobalObject* globalObject = scope->globalObject();
- ASSERT(globalObject);
- ASSERT(&globalObject->globalData() == &globalData);
+ RELEASE_ASSERT(globalObject);
+ ASSERT(&globalObject->vm() == &vm);
JSObject* exception = 0;
UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
if (exception)
return exception;
- m_unlinkedProgramCodeBlock.set(globalData, this, unlinkedCode);
+ m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCode);
- BatchedTransitionOptimizer optimizer(globalData, globalObject);
+ BatchedTransitionOptimizer optimizer(vm, globalObject);
const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
@@ -393,12 +401,12 @@ JSObject* ProgramExecutable::initalizeGlobalProperties(JSGlobalData& globalData,
CallFrame* globalExec = globalObject->globalExec();
for (size_t i = 0; i < functionDeclarations.size(); ++i) {
- bool propertyDidExist = globalObject->removeDirect(globalData, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
+ bool propertyDidExist = globalObject->removeDirect(vm, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
- JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(globalData, m_source, lineNo(), 0), scope);
+ JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(vm, m_source, lineNo(), 0), scope);
int index = addGlobalVar(globalObject, functionDeclarations[i].first, IsVariable,
!propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
- globalObject->registerAt(index).set(globalData, globalObject, value);
+ globalObject->registerAt(index).set(vm, globalObject, value);
}
for (size_t i = 0; i < variableDeclarations.size(); ++i) {
@@ -436,21 +444,21 @@ FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKi
if (kind == CodeForCall)
result = m_codeBlockForCall.get();
else {
- ASSERT(kind == CodeForConstruct);
+ RELEASE_ASSERT(kind == CodeForConstruct);
result = m_codeBlockForConstruct.get();
}
if (!result)
return 0;
while (result->alternative())
result = static_cast<FunctionCodeBlock*>(result->alternative());
- ASSERT(result);
+ RELEASE_ASSERT(result);
ASSERT(JITCode::isBaselineCode(result->getJITType()));
return result;
}
JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
ASSERT(!!m_codeBlockForCall);
JSObject* error = 0;
if (m_codeBlockForCall->getJITType() != JITCode::topTierJIT())
@@ -461,7 +469,7 @@ JSObject* FunctionExecutable::compileOptimizedForCall(ExecState* exec, JSScope*
JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
ASSERT(!!m_codeBlockForConstruct);
JSObject* error = 0;
if (m_codeBlockForConstruct->getJITType() != JITCode::topTierJIT())
@@ -482,30 +490,29 @@ bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
}
#endif
-FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
-{
- return baselineCodeBlockFor(kind);
-}
-
PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
{
if (!!codeBlockFor(specializationKind))
return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
- JSGlobalData* globalData = scope->globalData();
+ VM* vm = scope->vm();
JSGlobalObject* globalObject = scope->globalObject();
ParserError error;
DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
- UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*globalData, m_source, specializationKind, debuggerMode, profilerMode, error);
- recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine());
+ UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*vm, scope, m_source, specializationKind, debuggerMode, profilerMode, error);
+ recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine(), startColumn());
if (!unlinkedCodeBlock) {
exception = error.toErrorObject(globalObject, m_source);
return nullptr;
}
- OwnPtr<FunctionCodeBlock> result = adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock, globalObject, source().provider(), source().startOffset()));
+ SourceProvider* provider = source().provider();
+ unsigned sourceOffset = source().startOffset();
+ unsigned startColumn = source().startColumn();
+
+ OwnPtr<FunctionCodeBlock> result = adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock, globalObject, provider, sourceOffset, startColumn));
result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
return result.release();
}
@@ -531,7 +538,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s
m_codeBlockForCall = newCodeBlock.release();
m_numParametersForCall = m_codeBlockForCall->numParameters();
- ASSERT(m_numParametersForCall);
+ RELEASE_ASSERT(m_numParametersForCall);
#if ENABLE(JIT)
if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, jitType, bytecodeIndex, CodeForCall))
@@ -567,7 +574,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
m_codeBlockForConstruct = newCodeBlock.release();
m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
- ASSERT(m_numParametersForConstruct);
+ RELEASE_ASSERT(m_numParametersForConstruct);
#if ENABLE(JIT)
if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, jitType, bytecodeIndex, CodeForConstruct))
@@ -584,16 +591,16 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
}
#if ENABLE(JIT)
-void FunctionExecutable::jettisonOptimizedCodeForCall(JSGlobalData& globalData)
+void FunctionExecutable::jettisonOptimizedCodeForCall(VM& vm)
{
- jettisonCodeBlock(globalData, m_codeBlockForCall);
+ jettisonCodeBlock(vm, m_codeBlockForCall);
m_jitCodeForCall = m_codeBlockForCall->getJITCode();
m_jitCodeForCallWithArityCheck = m_codeBlockForCall->getJITCodeWithArityCheck();
}
-void FunctionExecutable::jettisonOptimizedCodeForConstruct(JSGlobalData& globalData)
+void FunctionExecutable::jettisonOptimizedCodeForConstruct(VM& vm)
{
- jettisonCodeBlock(globalData, m_codeBlockForConstruct);
+ jettisonCodeBlock(vm, m_codeBlockForConstruct);
m_jitCodeForConstruct = m_codeBlockForConstruct->getJITCode();
m_jitCodeForConstructWithArityCheck = m_codeBlockForConstruct->getJITCodeWithArityCheck();
}
@@ -638,11 +645,11 @@ void FunctionExecutable::unlinkCalls()
{
#if ENABLE(JIT)
if (!!m_jitCodeForCall) {
- ASSERT(m_codeBlockForCall);
+ RELEASE_ASSERT(m_codeBlockForCall);
m_codeBlockForCall->unlinkCalls();
}
if (!!m_jitCodeForConstruct) {
- ASSERT(m_codeBlockForConstruct);
+ RELEASE_ASSERT(m_codeBlockForConstruct);
m_codeBlockForConstruct->unlinkCalls();
}
#endif
@@ -655,9 +662,10 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, E
return 0;
unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
+ unsigned startColumn = source.startColumn();
unsigned sourceLength = unlinkedFunction->sourceLength();
- SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine);
- return FunctionExecutable::create(exec->globalData(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount());
+ SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine, startColumn);
+ return FunctionExecutable::create(exec->vm(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount(), startColumn);
}
String FunctionExecutable::paramString() const
@@ -678,7 +686,7 @@ CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const
if (kind == CodeForCall)
return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_function)));
- ASSERT(kind == CodeForConstruct);
+ RELEASE_ASSERT(kind == CodeForConstruct);
return CodeBlockHash(static_cast<unsigned>(bitwise_cast<size_t>(m_constructor)));
}
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 83eb602c4..28e823ca4 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 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
@@ -32,10 +32,11 @@
#include "HandlerInfo.h"
#include "JSFunction.h"
#include "Interpreter.h"
+#include "JITCode.h"
#include "JSGlobalObject.h"
#include "LLIntCLoop.h"
-#include "Nodes.h"
#include "SamplingTool.h"
+#include "SourceCode.h"
#include "UnlinkedCodeBlock.h"
#include <wtf/PassOwnPtr.h>
@@ -67,16 +68,16 @@ namespace JSC {
static const int NUM_PARAMETERS_IS_HOST = 0;
static const int NUM_PARAMETERS_NOT_COMPILED = -1;
- ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
- : JSCell(globalData, structure)
+ ExecutableBase(VM& vm, Structure* structure, int numParameters)
+ : JSCell(vm, structure)
, m_numParametersForCall(numParameters)
, m_numParametersForConstruct(numParameters)
{
}
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
}
public:
@@ -101,7 +102,7 @@ namespace JSC {
return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
}
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
void clearCode();
@@ -176,16 +177,6 @@ namespace JSC {
return hasJITCodeForConstruct();
}
- // Intrinsics are only for calls, currently.
- Intrinsic intrinsic() const;
-
- Intrinsic intrinsicFor(CodeSpecializationKind kind) const
- {
- if (isCall(kind))
- return intrinsic();
- return NoIntrinsic;
- }
-
static ptrdiff_t offsetOfJITCodeFor(CodeSpecializationKind kind)
{
if (kind == CodeForCall)
@@ -211,6 +202,16 @@ namespace JSC {
}
#endif // ENABLE(JIT)
+ // Intrinsics are only for calls, currently.
+ Intrinsic intrinsic() const;
+
+ Intrinsic intrinsicFor(CodeSpecializationKind kind) const
+ {
+ if (isCall(kind))
+ return intrinsic();
+ return NoIntrinsic;
+ }
+
#if ENABLE(JIT) || ENABLE(LLINT_C_LOOP)
MacroAssemblerCodePtr hostCodeEntryFor(CodeSpecializationKind kind)
{
@@ -270,26 +271,26 @@ namespace JSC {
typedef ExecutableBase Base;
#if ENABLE(JIT)
- static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
+ static NativeExecutable* create(VM& vm, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
{
NativeExecutable* executable;
if (!callThunk) {
- executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
- executable->finishCreation(globalData, JITCode(), JITCode(), intrinsic);
+ executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
+ executable->finishCreation(vm, JITCode(), JITCode(), intrinsic);
} else {
- executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
- executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
+ executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
+ executable->finishCreation(vm, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
}
return executable;
}
#endif
#if ENABLE(LLINT_C_LOOP)
- static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+ static NativeExecutable* create(VM& vm, NativeFunction function, NativeFunction constructor)
{
- ASSERT(!globalData.canUseJIT());
- NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
- executable->finishCreation(globalData);
+ ASSERT(!vm.canUseJIT());
+ NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(vm.heap)) NativeExecutable(vm, function, constructor);
+ executable->finishCreation(vm);
return executable;
}
#endif
@@ -302,8 +303,24 @@ namespace JSC {
NativeFunction function() { return m_function; }
NativeFunction constructor() { return m_constructor; }
+
+ NativeFunction nativeFunctionFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return function();
+ ASSERT(kind == CodeForConstruct);
+ return constructor();
+ }
+
+ static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall)
+ return OBJECT_OFFSETOF(NativeExecutable, m_function);
+ ASSERT(kind == CodeForConstruct);
+ return OBJECT_OFFSETOF(NativeExecutable, m_constructor);
+ }
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); }
static const ClassInfo s_info;
@@ -311,9 +328,9 @@ namespace JSC {
protected:
#if ENABLE(JIT)
- void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
+ void finishCreation(VM& vm, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
m_jitCodeForCall = callThunk;
m_jitCodeForConstruct = constructThunk;
m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
@@ -323,8 +340,8 @@ namespace JSC {
#endif
private:
- NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
- : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
+ NativeExecutable(VM& vm, NativeFunction function, NativeFunction constructor)
+ : ExecutableBase(vm, vm.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
, m_function(function)
, m_constructor(constructor)
{
@@ -340,17 +357,19 @@ namespace JSC {
public:
typedef ExecutableBase Base;
- ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
- : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
+ ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
+ : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
, m_features(isInStrictContext ? StrictModeFeature : 0)
+ , m_neverInline(false)
{
}
ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
- : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
+ : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
, m_features(isInStrictContext ? StrictModeFeature : 0)
+ , m_neverInline(false)
{
}
@@ -365,11 +384,16 @@ namespace JSC {
const String& sourceURL() const { return m_source.provider()->url(); }
int lineNo() const { return m_firstLine; }
int lastLine() const { return m_lastLine; }
+ unsigned startColumn() const { return m_startColumn; }
bool usesEval() const { return m_features & EvalFeature; }
bool usesArguments() const { return m_features & ArgumentsFeature; }
bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
bool isStrictMode() const { return m_features & StrictModeFeature; }
+
+ void setNeverInline(bool value) { m_neverInline = value; }
+ bool neverInline() const { return m_neverInline; }
+ bool isInliningCandidate() const { return !neverInline(); }
void unlinkCalls();
@@ -377,31 +401,34 @@ namespace JSC {
static const ClassInfo s_info;
- void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+ void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine, unsigned startColumn)
{
m_features = features;
m_hasCapturedVariables = hasCapturedVariables;
m_firstLine = firstLine;
m_lastLine = lastLine;
+ m_startColumn = startColumn;
}
protected:
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
- globalData.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
+ Base::finishCreation(vm);
+ vm.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
#if ENABLE(CODEBLOCK_SAMPLING)
- if (SamplingTool* sampler = globalData.interpreter->sampler())
- sampler->notifyOfScope(globalData, this);
+ if (SamplingTool* sampler = vm.interpreter->sampler())
+ sampler->notifyOfScope(vm, this);
#endif
}
SourceCode m_source;
CodeFeatures m_features;
bool m_hasCapturedVariables;
+ bool m_neverInline;
int m_firstLine;
int m_lastLine;
+ unsigned m_startColumn;
};
class EvalExecutable : public ScriptExecutable {
@@ -413,7 +440,7 @@ namespace JSC {
JSObject* compile(ExecState* exec, JSScope* scope)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
JSObject* error = 0;
if (!m_evalCodeBlock)
error = compileInternal(exec, scope, JITCode::bottomTierJIT());
@@ -424,7 +451,7 @@ namespace JSC {
JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
#if ENABLE(JIT)
- void jettisonOptimizedCode(JSGlobalData&);
+ void jettisonOptimizedCode(VM&);
bool jitCompile(ExecState*);
#endif
@@ -434,10 +461,10 @@ namespace JSC {
return *m_evalCodeBlock;
}
- static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext)
+ static EvalExecutable* create(ExecState* exec, PassRefPtr<CodeCache> cache, const SourceCode& source, bool isInStrictContext)
{
- EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
- executable->finishCreation(exec->globalData());
+ EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, cache, source, isInStrictContext);
+ executable->finishCreation(exec->vm());
return executable;
}
@@ -447,9 +474,9 @@ namespace JSC {
return generatedJITCodeForCall();
}
#endif
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info);
}
static const ClassInfo s_info;
@@ -462,13 +489,14 @@ namespace JSC {
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
- EvalExecutable(ExecState*, const SourceCode&, bool);
+ EvalExecutable(ExecState*, PassRefPtr<CodeCache>, const SourceCode&, bool);
JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
OwnPtr<EvalCodeBlock> m_evalCodeBlock;
WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
+ RefPtr<CodeCache> m_codeCache;
};
class ProgramExecutable : public ScriptExecutable {
@@ -479,18 +507,18 @@ namespace JSC {
static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
{
ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
- executable->finishCreation(exec->globalData());
+ executable->finishCreation(exec->vm());
return executable;
}
- JSObject* initalizeGlobalProperties(JSGlobalData&, CallFrame*, JSScope*);
+ JSObject* initializeGlobalProperties(VM&, CallFrame*, JSScope*);
static void destroy(JSCell*);
JSObject* compile(ExecState* exec, JSScope* scope)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
JSObject* error = 0;
if (!m_programCodeBlock)
error = compileInternal(exec, scope, JITCode::bottomTierJIT());
@@ -501,7 +529,7 @@ namespace JSC {
JSObject* compileOptimized(ExecState*, JSScope*, unsigned bytecodeIndex);
#if ENABLE(JIT)
- void jettisonOptimizedCode(JSGlobalData&);
+ void jettisonOptimizedCode(VM&);
bool jitCompile(ExecState*);
#endif
@@ -520,9 +548,9 @@ namespace JSC {
}
#endif
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info);
}
static const ClassInfo s_info;
@@ -555,15 +583,20 @@ namespace JSC {
public:
typedef ScriptExecutable Base;
- static FunctionExecutable* create(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
+ static FunctionExecutable* create(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn)
{
- FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, source, unlinkedExecutable, firstLine, lastLine);
- executable->finishCreation(globalData);
+ FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(vm.heap)) FunctionExecutable(vm, source, unlinkedExecutable, firstLine, lastLine, startColumn);
+ executable->finishCreation(vm);
return executable;
}
static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
static void destroy(JSCell*);
+
+ UnlinkedFunctionExecutable* unlinkedExecutable()
+ {
+ return m_unlinkedExecutable.get();
+ }
// Returns either call or construct bytecode. This can be appropriate
// for answering questions that that don't vary between call and construct --
@@ -576,13 +609,11 @@ namespace JSC {
return *m_codeBlockForConstruct;
}
- FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind);
-
PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
JSObject* compileForCall(ExecState* exec, JSScope* scope)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
JSObject* error = 0;
if (!m_codeBlockForCall)
error = compileForCallInternal(exec, scope, JITCode::bottomTierJIT());
@@ -593,7 +624,7 @@ namespace JSC {
JSObject* compileOptimizedForCall(ExecState*, JSScope*, unsigned bytecodeIndex);
#if ENABLE(JIT)
- void jettisonOptimizedCodeForCall(JSGlobalData&);
+ void jettisonOptimizedCodeForCall(VM&);
bool jitCompileForCall(ExecState*);
#endif
@@ -610,7 +641,7 @@ namespace JSC {
JSObject* compileForConstruct(ExecState* exec, JSScope* scope)
{
- ASSERT(exec->globalData().dynamicGlobalObject);
+ RELEASE_ASSERT(exec->vm().dynamicGlobalObject);
JSObject* error = 0;
if (!m_codeBlockForConstruct)
error = compileForConstructInternal(exec, scope, JITCode::bottomTierJIT());
@@ -621,7 +652,7 @@ namespace JSC {
JSObject* compileOptimizedForConstruct(ExecState*, JSScope*, unsigned bytecodeIndex);
#if ENABLE(JIT)
- void jettisonOptimizedCodeForConstruct(JSGlobalData&);
+ void jettisonOptimizedCodeForConstruct(VM&);
bool jitCompileForConstruct(ExecState*);
#endif
@@ -661,13 +692,13 @@ namespace JSC {
}
#if ENABLE(JIT)
- void jettisonOptimizedCodeFor(JSGlobalData& globalData, CodeSpecializationKind kind)
+ void jettisonOptimizedCodeFor(VM& vm, CodeSpecializationKind kind)
{
if (kind == CodeForCall)
- jettisonOptimizedCodeForCall(globalData);
+ jettisonOptimizedCodeForCall(vm);
else {
ASSERT(kind == CodeForConstruct);
- jettisonOptimizedCodeForConstruct(globalData);
+ jettisonOptimizedCodeForConstruct(vm);
}
}
@@ -713,9 +744,9 @@ namespace JSC {
void clearCodeIfNotCompiling();
void clearUnlinkedCodeForRecompilationIfNotCompiling();
static void visitChildren(JSCell*, SlotVisitor&);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
}
static const ClassInfo s_info;
@@ -725,7 +756,7 @@ namespace JSC {
void clearCode();
private:
- FunctionExecutable(JSGlobalData&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine);
+ FunctionExecutable(VM&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine, unsigned startColumn);
JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
@@ -755,38 +786,6 @@ namespace JSC {
OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
};
- inline JSFunction::JSFunction(JSGlobalData& globalData, FunctionExecutable* executable, JSScope* scope)
- : Base(globalData, scope->globalObject()->functionStructure())
- , m_executable(globalData, this, executable)
- , m_scope(globalData, this, scope)
- , m_inheritorIDWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
- {
- }
-
- inline FunctionExecutable* JSFunction::jsExecutable() const
- {
- ASSERT(!isHostFunctionNonInline());
- return static_cast<FunctionExecutable*>(m_executable.get());
- }
-
- inline bool JSFunction::isHostFunction() const
- {
- ASSERT(m_executable);
- return m_executable->isHostFunction();
- }
-
- inline NativeFunction JSFunction::nativeFunction()
- {
- ASSERT(isHostFunction());
- return static_cast<NativeExecutable*>(m_executable.get())->function();
- }
-
- inline NativeFunction JSFunction::nativeConstructor()
- {
- ASSERT(isHostFunction());
- return static_cast<NativeExecutable*>(m_executable.get())->constructor();
- }
-
inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
{
JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
@@ -819,10 +818,12 @@ namespace JSC {
case FunctionExecutableType:
return jsCast<FunctionExecutable*>(this)->unlinkCalls();
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
}
+#include "JSFunctionInlines.h"
+
#endif
diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h
index b71b60217..ba52a1e51 100644
--- a/Source/JavaScriptCore/runtime/ExecutionHarness.h
+++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h
@@ -41,8 +41,10 @@ inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBloc
#if ENABLE(LLINT)
if (JITCode::isBaselineCode(jitType)) {
// Start off in the low level interpreter.
- LLInt::getEntrypoint(exec->globalData(), codeBlock.get(), jitCode);
+ LLInt::getEntrypoint(exec->vm(), codeBlock.get(), jitCode);
codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
+ if (exec->vm().m_perBytecodeProfiler)
+ exec->vm().m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get());
return true;
}
#endif // ENABLE(LLINT)
@@ -54,8 +56,10 @@ inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBloc
#if ENABLE(LLINT)
if (JITCode::isBaselineCode(jitType)) {
// Start off in the low level interpreter.
- LLInt::getFunctionEntrypoint(exec->globalData(), kind, jitCode, jitCodeWithArityCheck);
+ LLInt::getFunctionEntrypoint(exec->vm(), kind, jitCode, jitCodeWithArityCheck);
codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
+ if (exec->vm().m_perBytecodeProfiler)
+ exec->vm().m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get());
return true;
}
#else
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index bf74c0a97..3c4379b39 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -29,6 +29,7 @@
#include "JSString.h"
#include "Lexer.h"
#include "Nodes.h"
+#include "Operations.h"
#include "Parser.h"
#include <wtf/text/StringBuilder.h>
@@ -45,11 +46,11 @@ FunctionConstructor::FunctionConstructor(JSGlobalObject* globalObject, Structure
void FunctionConstructor::finishCreation(ExecState* exec, FunctionPrototype* functionPrototype)
{
- Base::finishCreation(exec->globalData(), functionPrototype->classInfo()->className);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+ Base::finishCreation(exec->vm(), functionPrototype->classInfo()->className);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
// Number 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);
}
static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec)
@@ -123,7 +124,7 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj
// ECMA 15.3.2 The Function Constructor
JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
{
- return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), String(), TextPosition::minimumPosition());
+ return constructFunction(exec, globalObject, args, exec->propertyNames().anonymous, String(), TextPosition::minimumPosition());
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h
index 99eafee80..3d211f633 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.h
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h
@@ -44,9 +44,9 @@ namespace JSC {
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);
}
private:
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp b/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp
new file mode 100644
index 000000000..1577ed57a
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/FunctionExecutableDump.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FunctionExecutableDump.h"
+
+namespace JSC {
+
+void FunctionExecutableDump::dump(PrintStream& out) const
+{
+ out.print(m_executable->inferredName().string(), "#", m_executable->hashFor(CodeForCall), "/", m_executable->hashFor(CodeForConstruct), ":[", RawPointer(m_executable), "]");
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/runtime/FunctionExecutableDump.h b/Source/JavaScriptCore/runtime/FunctionExecutableDump.h
new file mode 100644
index 000000000..732ec458f
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/FunctionExecutableDump.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FunctionExecutableDump_h
+#define FunctionExecutableDump_h
+
+#include "Executable.h"
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+class FunctionExecutableDump {
+public:
+ explicit FunctionExecutableDump(FunctionExecutable* executable)
+ : m_executable(executable)
+ {
+ }
+
+ void dump(PrintStream&) const;
+private:
+ FunctionExecutable* m_executable;
+};
+
+} // namespace JSC
+
+#endif // FunctionExecutableDump_h
+
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index 8e4390b1b..183298267 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -29,6 +29,7 @@
#include "JSStringBuilder.h"
#include "Interpreter.h"
#include "Lexer.h"
+#include "Operations.h"
namespace JSC {
@@ -48,23 +49,23 @@ FunctionPrototype::FunctionPrototype(JSGlobalObject* globalObject, Structure* st
void FunctionPrototype::finishCreation(ExecState* exec, const String& name)
{
- Base::finishCreation(exec->globalData(), name);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
+ Base::finishCreation(exec->vm(), name);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
}
void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, JSFunction** callFunction, JSFunction** applyFunction)
{
JSFunction* toStringFunction = JSFunction::create(exec, globalObject, 0, exec->propertyNames().toString.string(), functionProtoFuncToString);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().toString, toStringFunction, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().toString, toStringFunction, DontEnum);
*applyFunction = JSFunction::create(exec, globalObject, 2, exec->propertyNames().apply.string(), functionProtoFuncApply);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().apply, *applyFunction, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().apply, *applyFunction, DontEnum);
*callFunction = JSFunction::create(exec, globalObject, 1, exec->propertyNames().call.string(), functionProtoFuncCall);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().call, *callFunction, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().call, *callFunction, DontEnum);
JSFunction* bindFunction = JSFunction::create(exec, globalObject, 1, exec->propertyNames().bind.string(), functionProtoFuncBind);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().bind, bindFunction, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().bind, bindFunction, DontEnum);
}
static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
@@ -186,12 +187,12 @@ 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->vm(), globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), numBoundArgs);
if (!boundArgs)
return JSValue::encode(throwOutOfMemoryError(exec));
for (size_t i = 0; i < numBoundArgs; ++i)
- boundArgs->initializeIndex(exec->globalData(), i, exec->argument(i + 1));
+ boundArgs->initializeIndex(exec->vm(), i, exec->argument(i + 1));
// If the [[Class]] internal property of Target is "Function", then ...
// Else set the length own property of F to 0.
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.h b/Source/JavaScriptCore/runtime/FunctionPrototype.h
index 07f381306..0083fb9d2 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.h
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.h
@@ -38,9 +38,9 @@ namespace JSC {
void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
index 0c07b5e02..4898122b5 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp
@@ -31,16 +31,20 @@
#include "APIShims.h"
#include "Heap.h"
-#include "JSGlobalData.h"
+#include "VM.h"
#include "JSLock.h"
#include "JSObject.h"
#include <wtf/RetainPtr.h>
#include <wtf/WTFThreadData.h>
+#if PLATFORM(EFL)
+#include <wtf/MainThread.h>
+#endif
+
namespace JSC {
-#if USE(CF) || PLATFORM(QT)
+#if USE(CF) || PLATFORM(QT) || PLATFORM(EFL)
const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB
const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections.
@@ -50,19 +54,25 @@ const double hour = 60 * 60;
#if USE(CF)
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
- : GCActivityCallback(heap->globalData(), CFRunLoopGetCurrent())
+ : GCActivityCallback(heap->vm(), CFRunLoopGetCurrent())
, m_delay(s_decade)
{
}
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
- : GCActivityCallback(heap->globalData(), runLoop)
+ : GCActivityCallback(heap->vm(), runLoop)
, m_delay(s_decade)
{
}
#elif PLATFORM(QT)
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
- : GCActivityCallback(heap->globalData())
+ : GCActivityCallback(heap->vm())
+ , m_delay(hour)
+{
+}
+#elif PLATFORM(EFL)
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+ : GCActivityCallback(heap->vm(), WTF::isMainThread())
, m_delay(hour)
{
}
@@ -70,11 +80,11 @@ DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
void DefaultGCActivityCallback::doWork()
{
- Heap* heap = &m_globalData->heap;
+ Heap* heap = &m_vm->heap;
if (!isEnabled())
return;
- APIEntryShim shim(m_globalData);
+ APIEntryShim shim(m_vm);
#if !PLATFORM(IOS)
double startTime = WTF::monotonicallyIncreasingTime();
if (heap->isPagedOut(startTime + pagingTimeOut)) {
@@ -116,15 +126,40 @@ void DefaultGCActivityCallback::cancelTimer()
m_delay = hour;
m_timer.stop();
}
+#elif PLATFORM(EFL)
+void DefaultGCActivityCallback::scheduleTimer(double newDelay)
+{
+ if (newDelay * timerSlop > m_delay)
+ return;
+
+ stop();
+ m_delay = newDelay;
+
+ ASSERT(!m_timer);
+ m_timer = add(newDelay, this);
+}
+
+void DefaultGCActivityCallback::cancelTimer()
+{
+ m_delay = hour;
+ stop();
+}
#endif
void DefaultGCActivityCallback::didAllocate(size_t bytes)
{
+#if PLATFORM(EFL)
+ if (!isEnabled())
+ return;
+
+ ASSERT(WTF::isMainThread());
+#endif
+
// The first byte allocated in an allocation cycle will report 0 bytes to didAllocate.
// We pretend it's one byte so that we don't ignore this allocation entirely.
if (!bytes)
bytes = 1;
- Heap* heap = static_cast<Heap*>(&m_globalData->heap);
+ Heap* heap = static_cast<Heap*>(&m_vm->heap);
double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice);
double newDelay = heap->lastGCLength() / gcTimeSlice;
scheduleTimer(newDelay);
@@ -143,7 +178,7 @@ void DefaultGCActivityCallback::cancel()
#else
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
- : GCActivityCallback(heap->globalData())
+ : GCActivityCallback(heap->vm())
{
}
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.h b/Source/JavaScriptCore/runtime/GCActivityCallback.h
index 3522e6c8e..a7aec6a8d 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallback.h
+++ b/Source/JavaScriptCore/runtime/GCActivityCallback.h
@@ -52,14 +52,20 @@ public:
protected:
#if USE(CF)
- GCActivityCallback(JSGlobalData* globalData, CFRunLoopRef runLoop)
- : HeapTimer(globalData, runLoop)
+ GCActivityCallback(VM* vm, CFRunLoopRef runLoop)
+ : HeapTimer(vm, runLoop)
, m_enabled(true)
{
}
+#elif PLATFORM(EFL)
+ GCActivityCallback(VM* vm, bool flag)
+ : HeapTimer(vm)
+ , m_enabled(flag)
+ {
+ }
#else
- GCActivityCallback(JSGlobalData* globalData)
- : HeapTimer(globalData)
+ GCActivityCallback(VM* vm)
+ : HeapTimer(vm)
, m_enabled(true)
{
}
@@ -70,7 +76,7 @@ protected:
class DefaultGCActivityCallback : public GCActivityCallback {
public:
- static DefaultGCActivityCallback* create(Heap*);
+ static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
DefaultGCActivityCallback(Heap*);
@@ -84,7 +90,7 @@ public:
protected:
DefaultGCActivityCallback(Heap*, CFRunLoopRef);
#endif
-#if USE(CF) || PLATFORM(QT)
+#if USE(CF) || PLATFORM(QT) || PLATFORM(EFL)
protected:
void cancelTimer();
void scheduleTimer(double);
@@ -94,9 +100,9 @@ private:
#endif
};
-inline DefaultGCActivityCallback* DefaultGCActivityCallback::create(Heap* heap)
+inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
{
- return new DefaultGCActivityCallback(heap);
+ return adoptPtr(new DefaultGCActivityCallback(heap));
}
}
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
index 35b992567..d7c9d53c2 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp
@@ -20,29 +20,29 @@
#include "GCActivityCallback.h"
#include "Heap.h"
-#include "JSGlobalData.h"
+#include "VM.h"
#include <BlackBerryPlatformMemory.h>
namespace JSC {
DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
- : GCActivityCallback(heap->globalData())
+ : GCActivityCallback(heap->vm())
{
}
void DefaultGCActivityCallback::doWork()
{
- JSLock lock(SilenceAssertionsOnly);
- m_globalData->heap.collect(Heap::DoNotSweep);
+ JSLockHolder lock(m_vm);
+ m_vm->heap.collect(Heap::DoNotSweep);
}
-void DefaultGCActivityCallback::didAllocate(size_t bytesAllocated)
+void DefaultGCActivityCallback::didAllocate(size_t)
{
if (m_timer.started())
return;
// Try using ~5% CPU time.
- m_timer.start(m_globalData->heap.lastGCLength() * 20);
+ m_timer.start(m_vm->heap.lastGCLength() * 20);
}
void DefaultGCActivityCallback::willCollect()
diff --git a/Source/JavaScriptCore/runtime/GetterSetter.cpp b/Source/JavaScriptCore/runtime/GetterSetter.cpp
index 8ed582548..b4651141e 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.cpp
+++ b/Source/JavaScriptCore/runtime/GetterSetter.cpp
@@ -24,6 +24,7 @@
#include "GetterSetter.h"
#include "JSObject.h"
+#include "Operations.h"
#include <wtf/Assertions.h>
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h
index b8caf0198..f459e4432 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.h
+++ b/Source/JavaScriptCore/runtime/GetterSetter.h
@@ -39,7 +39,7 @@ namespace JSC {
private:
GetterSetter(ExecState* exec)
- : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get())
+ : JSCell(exec->vm(), exec->vm().getterSetterStructure.get())
{
}
@@ -49,19 +49,19 @@ namespace JSC {
static GetterSetter* create(ExecState* exec)
{
GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(*exec->heap())) GetterSetter(exec);
- getterSetter->finishCreation(exec->globalData());
+ getterSetter->finishCreation(exec->vm());
return getterSetter;
}
static void visitChildren(JSCell*, SlotVisitor&);
JSObject* getter() const { return m_getter.get(); }
- void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.setMayBeNull(globalData, this, getter); }
+ void setGetter(VM& vm, JSObject* getter) { m_getter.setMayBeNull(vm, this, getter); }
JSObject* setter() const { return m_setter.get(); }
- void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.setMayBeNull(globalData, this, setter); }
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+ void setSetter(VM& vm, JSObject* setter) { m_setter.setMayBeNull(vm, this, setter); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(globalData, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), &s_info);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index 583c12bb1..ad61b493a 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -25,6 +25,7 @@
#include "JSObject.h"
#include "JSScope.h"
#include "NumericStrings.h"
+#include "Operations.h"
#include <new>
#include <string.h>
#include <wtf/Assertions.h>
@@ -50,7 +51,7 @@ void deleteIdentifierTable(IdentifierTable* table)
struct IdentifierASCIIStringTranslator {
static unsigned hash(const LChar* c)
{
- return StringHasher::computeHashAndMaskTop8Bits<LChar>(c);
+ return StringHasher::computeHashAndMaskTop8Bits(c);
}
static bool equal(StringImpl* r, const LChar* s)
@@ -69,7 +70,7 @@ struct IdentifierASCIIStringTranslator {
struct IdentifierLCharFromUCharTranslator {
static unsigned hash(const CharBuffer<UChar>& buf)
{
- return StringHasher::computeHashAndMaskTop8Bits<UChar>(buf.s, buf.length);
+ return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
}
static bool equal(StringImpl* str, const CharBuffer<UChar>& buf)
@@ -87,19 +88,14 @@ struct IdentifierLCharFromUCharTranslator {
}
};
-PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
+PassRefPtr<StringImpl> Identifier::add(VM* vm, const char* c)
{
ASSERT(c);
ASSERT(c[0]);
if (!c[1])
- return add(globalData, globalData->smallStrings.singleCharacterStringRep(c[0]));
+ return add(vm, vm->smallStrings.singleCharacterStringRep(c[0]));
- IdentifierTable& identifierTable = *globalData->identifierTable;
- LiteralIdentifierTable& literalIdentifierTable = identifierTable.literalTable();
-
- const LiteralIdentifierTable::iterator& iter = literalIdentifierTable.find(c);
- if (iter != literalIdentifierTable.end())
- return iter->value;
+ IdentifierTable& identifierTable = *vm->identifierTable;
HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierASCIIStringTranslator>(reinterpret_cast<const LChar*>(c));
@@ -107,36 +103,34 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
// The boolean in the pair tells us if that is so.
RefPtr<StringImpl> addedString = addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
- literalIdentifierTable.add(c, addedString.get());
-
return addedString.release();
}
PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c)
{
- return add(&exec->globalData(), c);
+ return add(&exec->vm(), c);
}
-PassRefPtr<StringImpl> Identifier::add8(JSGlobalData* globalData, const UChar* s, int length)
+PassRefPtr<StringImpl> Identifier::add8(VM* vm, const UChar* s, int length)
{
if (length == 1) {
UChar c = s[0];
ASSERT(c <= 0xff);
if (canUseSingleCharacterString(c))
- return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+ return add(vm, vm->smallStrings.singleCharacterStringRep(c));
}
if (!length)
return StringImpl::empty();
CharBuffer<UChar> buf = { s, static_cast<unsigned>(length) };
- HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf);
+ HashSet<StringImpl*>::AddResult addResult = vm->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf);
// If the string is newly-translated, then we need to adopt it.
// The boolean in the pair tells us if that is so.
return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
}
-PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringImpl* r)
+PassRefPtr<StringImpl> Identifier::addSlowCase(VM* vm, StringImpl* r)
{
ASSERT(!r->isIdentifier());
// The empty & null strings are static singletons, and static strings are handled
@@ -146,68 +140,68 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI
if (r->length() == 1) {
UChar c = (*r)[0];
if (c <= maxSingleCharacterString)
- r = globalData->smallStrings.singleCharacterStringRep(c);
+ r = vm->smallStrings.singleCharacterStringRep(c);
if (r->isIdentifier())
return r;
}
- return *globalData->identifierTable->add(r).iterator;
+ return *vm->identifierTable->add(r).iterator;
}
PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r)
{
- return addSlowCase(&exec->globalData(), r);
+ return addSlowCase(&exec->vm(), r);
}
Identifier Identifier::from(ExecState* exec, unsigned value)
{
- return Identifier(exec, exec->globalData().numericStrings.add(value));
+ return Identifier(exec, exec->vm().numericStrings.add(value));
}
Identifier Identifier::from(ExecState* exec, int value)
{
- return Identifier(exec, exec->globalData().numericStrings.add(value));
+ return Identifier(exec, exec->vm().numericStrings.add(value));
}
Identifier Identifier::from(ExecState* exec, double value)
{
- return Identifier(exec, exec->globalData().numericStrings.add(value));
+ return Identifier(exec, exec->vm().numericStrings.add(value));
}
-Identifier Identifier::from(JSGlobalData* globalData, unsigned value)
+Identifier Identifier::from(VM* vm, unsigned value)
{
- return Identifier(globalData, globalData->numericStrings.add(value));
+ return Identifier(vm, vm->numericStrings.add(value));
}
-Identifier Identifier::from(JSGlobalData* globalData, int value)
+Identifier Identifier::from(VM* vm, int value)
{
- return Identifier(globalData, globalData->numericStrings.add(value));
+ return Identifier(vm, vm->numericStrings.add(value));
}
-Identifier Identifier::from(JSGlobalData* globalData, double value)
+Identifier Identifier::from(VM* vm, double value)
{
- return Identifier(globalData, globalData->numericStrings.add(value));
+ return Identifier(vm, vm->numericStrings.add(value));
}
#ifndef NDEBUG
-void Identifier::checkCurrentIdentifierTable(JSGlobalData* globalData)
+void Identifier::checkCurrentIdentifierTable(VM* vm)
{
// Check the identifier table accessible through the threadspecific matches the
- // globalData's identifier table.
- ASSERT_UNUSED(globalData, globalData->identifierTable == wtfThreadData().currentIdentifierTable());
+ // vm's identifier table.
+ ASSERT_UNUSED(vm, vm->identifierTable == wtfThreadData().currentIdentifierTable());
}
void Identifier::checkCurrentIdentifierTable(ExecState* exec)
{
- checkCurrentIdentifierTable(&exec->globalData());
+ checkCurrentIdentifierTable(&exec->vm());
}
#else
// These only exists so that our exports are the same for debug and release builds.
-// This would be an ASSERT_NOT_REACHED(), but we're in NDEBUG only code here!
-NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(JSGlobalData*) { CRASH(); }
+// This would be an RELEASE_ASSERT_NOT_REACHED(), but we're in NDEBUG only code here!
+NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(VM*) { CRASH(); }
NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); }
#endif
diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h
index dcb739ec3..75b68b6e1 100644
--- a/Source/JavaScriptCore/runtime/Identifier.h
+++ b/Source/JavaScriptCore/runtime/Identifier.h
@@ -21,7 +21,7 @@
#ifndef Identifier_h
#define Identifier_h
-#include "JSGlobalData.h"
+#include "VM.h"
#include <wtf/ThreadSpecific.h>
#include <wtf/WTFThreadData.h>
#include <wtf/text/CString.h>
@@ -42,15 +42,15 @@ namespace JSC {
template<unsigned charactersCount>
Identifier(ExecState* exec, const char (&characters)[charactersCount]) : m_string(add(exec, characters)) { }
template<unsigned charactersCount>
- Identifier(JSGlobalData* globalData, const char (&characters)[charactersCount]) : m_string(add(globalData, characters)) { }
+ Identifier(VM* vm, const char (&characters)[charactersCount]) : m_string(add(vm, characters)) { }
Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { }
Identifier(ExecState* exec, const String& s) : m_string(add(exec, s.impl())) { }
- Identifier(JSGlobalData* globalData, const LChar* s, int length) : m_string(add(globalData, s, length)) { }
- Identifier(JSGlobalData* globalData, const UChar* s, int length) : m_string(add(globalData, s, length)) { }
- Identifier(JSGlobalData* globalData, StringImpl* rep) : m_string(add(globalData, rep)) { }
- Identifier(JSGlobalData* globalData, const String& s) : m_string(add(globalData, s.impl())) { }
+ Identifier(VM* vm, const LChar* s, int length) : m_string(add(vm, s, length)) { }
+ Identifier(VM* vm, const UChar* s, int length) : m_string(add(vm, s, length)) { }
+ Identifier(VM* vm, StringImpl* rep) : m_string(add(vm, rep)) { }
+ Identifier(VM* vm, const String& s) : m_string(add(vm, s.impl())) { }
const String& string() const { return m_string; }
StringImpl* impl() const { return m_string.impl(); }
@@ -60,14 +60,14 @@ namespace JSC {
CString ascii() const { return m_string.ascii(); }
- static Identifier createLCharFromUChar(JSGlobalData* globalData, const UChar* s, int length) { return Identifier(globalData, add8(globalData, s, length)); }
+ static Identifier createLCharFromUChar(VM* vm, const UChar* s, int length) { return Identifier(vm, add8(vm, s, length)); }
JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, unsigned y);
JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, int y);
static Identifier from(ExecState* exec, double y);
- static Identifier from(JSGlobalData*, unsigned y);
- static Identifier from(JSGlobalData*, int y);
- static Identifier from(JSGlobalData*, double y);
+ static Identifier from(VM*, unsigned y);
+ static Identifier from(VM*, int y);
+ static Identifier from(VM*, double y);
bool isNull() const { return m_string.isNull(); }
bool isEmpty() const { return m_string.isEmpty(); }
@@ -87,7 +87,7 @@ namespace JSC {
static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
// Only to be used with string literals.
- static PassRefPtr<StringImpl> add(JSGlobalData*, const char*);
+ static PassRefPtr<StringImpl> add(VM*, const char*);
JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*);
private:
@@ -99,8 +99,8 @@ namespace JSC {
static bool equal(const Identifier& a, const Identifier& b) { return a.m_string.impl() == b.m_string.impl(); }
static bool equal(const Identifier& a, const LChar* b) { return equal(a.m_string.impl(), b); }
- template <typename T> static PassRefPtr<StringImpl> add(JSGlobalData*, const T*, int length);
- static PassRefPtr<StringImpl> add8(JSGlobalData*, const UChar*, int length);
+ template <typename T> static PassRefPtr<StringImpl> add(VM*, const T*, int length);
+ static PassRefPtr<StringImpl> add8(VM*, const UChar*, int length);
template <typename T> ALWAYS_INLINE static bool canUseSingleCharacterString(T);
static PassRefPtr<StringImpl> add(ExecState* exec, StringImpl* r)
@@ -112,21 +112,21 @@ namespace JSC {
return r;
return addSlowCase(exec, r);
}
- static PassRefPtr<StringImpl> add(JSGlobalData* globalData, StringImpl* r)
+ static PassRefPtr<StringImpl> add(VM* vm, StringImpl* r)
{
#ifndef NDEBUG
- checkCurrentIdentifierTable(globalData);
+ checkCurrentIdentifierTable(vm);
#endif
if (r->isIdentifier())
return r;
- return addSlowCase(globalData, r);
+ return addSlowCase(vm, r);
}
JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
- JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
+ JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(VM*, StringImpl* r);
JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(ExecState*);
- JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(JSGlobalData*);
+ JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(VM*);
};
template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(LChar)
@@ -150,7 +150,7 @@ namespace JSC {
struct IdentifierCharBufferTranslator {
static unsigned hash(const CharBuffer<T>& buf)
{
- return StringHasher::computeHashAndMaskTop8Bits<T>(buf.s, buf.length);
+ return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
}
static bool equal(StringImpl* str, const CharBuffer<T>& buf)
@@ -170,18 +170,18 @@ namespace JSC {
};
template <typename T>
- PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const T* s, int length)
+ PassRefPtr<StringImpl> Identifier::add(VM* vm, const T* s, int length)
{
if (length == 1) {
T c = s[0];
if (canUseSingleCharacterString(c))
- return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
+ return add(vm, vm->smallStrings.singleCharacterStringRep(c));
}
if (!length)
return StringImpl::empty();
CharBuffer<T> buf = { s, static_cast<unsigned>(length) };
- HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(buf);
+ HashSet<StringImpl*>::AddResult addResult = vm->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(buf);
// If the string is newly-translated, then we need to adopt it.
// The boolean in the pair tells us if that is so.
@@ -251,11 +251,17 @@ namespace JSC {
template<typename U, typename V>
HashSet<StringImpl*>::AddResult IdentifierTable::add(U value)
{
- HashSet<StringImpl*>::AddResult result = m_table.add<U, V>(value);
+ HashSet<StringImpl*>::AddResult result = m_table.add<V>(value);
(*result.iterator)->setIsIdentifier(true);
return result;
}
} // namespace JSC
+namespace WTF {
+
+template <> struct VectorTraits<JSC::Identifier> : SimpleClassVectorTraits { };
+
+} // namespace WTF
+
#endif // Identifier_h
diff --git a/Source/JavaScriptCore/runtime/IndexingHeader.h b/Source/JavaScriptCore/runtime/IndexingHeader.h
index caa18183a..145b61876 100644
--- a/Source/JavaScriptCore/runtime/IndexingHeader.h
+++ b/Source/JavaScriptCore/runtime/IndexingHeader.h
@@ -44,25 +44,25 @@ public:
static ptrdiff_t offsetOfIndexingHeader() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
- static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, m_publicLength); }
- static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, m_vectorLength); }
+ static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.publicLength); }
+ static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.vectorLength); }
IndexingHeader()
- : m_publicLength(0)
- , m_vectorLength(0)
{
+ u.lengths.publicLength = 0;
+ u.lengths.vectorLength = 0;
}
- uint32_t vectorLength() const { return m_vectorLength; }
+ uint32_t vectorLength() const { return u.lengths.vectorLength; }
void setVectorLength(uint32_t length)
{
- ASSERT(length <= maximumLength);
- m_vectorLength = length;
+ RELEASE_ASSERT(length <= maximumLength);
+ u.lengths.vectorLength = length;
}
- uint32_t publicLength() { return m_publicLength; }
- void setPublicLength(uint32_t auxWord) { m_publicLength = auxWord; }
+ uint32_t publicLength() { return u.lengths.publicLength; }
+ void setPublicLength(uint32_t auxWord) { u.lengths.publicLength = auxWord; }
static IndexingHeader* from(Butterfly* butterfly)
{
@@ -86,12 +86,12 @@ public:
PropertyStorage propertyStorage()
{
- return reinterpret_cast<PropertyStorage>(this);
+ return reinterpret_cast_ptr<PropertyStorage>(this);
}
ConstPropertyStorage propertyStorage() const
{
- return reinterpret_cast<ConstPropertyStorage>(this);
+ return reinterpret_cast_ptr<ConstPropertyStorage>(this);
}
ArrayStorage* arrayStorage()
@@ -111,9 +111,13 @@ public:
private:
friend class LLIntOffsetsExtractor;
-
- uint32_t m_publicLength; // The meaning of this field depends on the array type, but for all JSArrays we rely on this being the publicly visible length (array.length).
- uint32_t m_vectorLength; // The length of the indexed property storage. The actual size of the storage depends on this, and the type.
+
+ union {
+ struct {
+ uint32_t publicLength; // The meaning of this field depends on the array type, but for all JSArrays we rely on this being the publicly visible length (array.length).
+ uint32_t vectorLength; // The length of the indexed property storage. The actual size of the storage depends on this, and the type.
+ } lengths;
+ } u;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/IndexingType.cpp b/Source/JavaScriptCore/runtime/IndexingType.cpp
index dc2733ad1..040a7828a 100644
--- a/Source/JavaScriptCore/runtime/IndexingType.cpp
+++ b/Source/JavaScriptCore/runtime/IndexingType.cpp
@@ -71,9 +71,8 @@ IndexingType leastUpperBoundOfIndexingTypeAndValue(IndexingType indexingType, JS
return leastUpperBoundOfIndexingTypeAndType(indexingType, speculationFromValue(value));
}
-const char* indexingTypeToString(IndexingType indexingType)
+void dumpIndexingType(PrintStream& out, IndexingType indexingType)
{
- static char result[128];
const char* basicName;
switch (indexingType & AllArrayTypes) {
case NonArray:
@@ -120,11 +119,7 @@ const char* indexingTypeToString(IndexingType indexingType)
break;
}
- snprintf(
- result, sizeof(result), "%s%s", basicName,
- (indexingType & MayHaveIndexedAccessors) ? "|MayHaveIndexedAccessors" : "");
-
- return result;
+ out.printf("%s%s", basicName, (indexingType & MayHaveIndexedAccessors) ? "|MayHaveIndexedAccessors" : "");
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/IndexingType.h b/Source/JavaScriptCore/runtime/IndexingType.h
index ab253be1e..dc5684b5f 100644
--- a/Source/JavaScriptCore/runtime/IndexingType.h
+++ b/Source/JavaScriptCore/runtime/IndexingType.h
@@ -34,27 +34,27 @@ namespace JSC {
typedef uint8_t IndexingType;
// Flags for testing the presence of capabilities.
-static const IndexingType IsArray = 1;
+static const IndexingType IsArray = 0x01;
// 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 ContiguousShape = 26;
-static const IndexingType ArrayStorageShape = 28;
-static const IndexingType SlowPutArrayStorageShape = 30;
+static const IndexingType IndexingShapeMask = 0x1E;
+static const IndexingType NoIndexingShape = 0x00;
+static const IndexingType UndecidedShape = 0x02; // Only useful for arrays.
+static const IndexingType Int32Shape = 0x14;
+static const IndexingType DoubleShape = 0x16;
+static const IndexingType ContiguousShape = 0x1A;
+static const IndexingType ArrayStorageShape = 0x1C;
+static const IndexingType SlowPutArrayStorageShape = 0x1E;
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;
+static const IndexingType MayHaveIndexedAccessors = 0x20;
// List of acceptable array types.
-static const IndexingType NonArray = 0;
+static const IndexingType NonArray = 0x0;
static const IndexingType NonArrayWithInt32 = Int32Shape;
static const IndexingType NonArrayWithDouble = DoubleShape;
static const IndexingType NonArrayWithContiguous = ContiguousShape;
@@ -149,7 +149,8 @@ IndexingType leastUpperBoundOfIndexingTypes(IndexingType, IndexingType);
IndexingType leastUpperBoundOfIndexingTypeAndType(IndexingType, SpeculatedType);
IndexingType leastUpperBoundOfIndexingTypeAndValue(IndexingType, JSValue);
-const char* indexingTypeToString(IndexingType);
+void dumpIndexingType(PrintStream&, IndexingType);
+MAKE_PRINT_ADAPTOR(IndexingTypeDump, IndexingType, dumpIndexingType);
// Mask of all possible types.
static const IndexingType AllArrayTypes = 31;
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp
index afb5e6317..071babc46 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.cpp
+++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp
@@ -26,6 +26,7 @@
#include "FunctionPrototype.h"
#include "JSGlobalObject.h"
#include "JSString.h"
+#include "Operations.h"
namespace JSC {
@@ -34,26 +35,26 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(InternalFunction);
const ClassInfo InternalFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(InternalFunction) };
InternalFunction::InternalFunction(JSGlobalObject* globalObject, Structure* structure)
- : JSDestructibleObject(globalObject->globalData(), structure)
+ : JSDestructibleObject(globalObject->vm(), structure)
{
}
-void InternalFunction::finishCreation(JSGlobalData& globalData, const String& name)
+void InternalFunction::finishCreation(VM& vm, const String& name)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
ASSERT(methodTable()->getCallData != InternalFunction::s_info.methodTable.getCallData);
- putDirect(globalData, globalData.propertyNames->name, jsString(&globalData, name), DontDelete | ReadOnly | DontEnum);
+ putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum);
}
const String& InternalFunction::name(ExecState* exec)
{
- return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
+ return asString(getDirect(exec->vm(), exec->vm().propertyNames->name))->tryGetValue();
}
const String InternalFunction::displayName(ExecState* exec)
{
- JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
+ JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);
if (displayName && isJSString(displayName))
return asString(displayName)->tryGetValue();
@@ -63,7 +64,7 @@ const String InternalFunction::displayName(ExecState* exec)
CallType InternalFunction::getCallData(JSCell*, CallData&)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return CallTypeNone;
}
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h
index daeebc34d..e35f5f9f2 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.h
+++ b/Source/JavaScriptCore/runtime/InternalFunction.h
@@ -41,9 +41,9 @@ namespace JSC {
const String displayName(ExecState*);
const String calculatedDisplayName(ExecState*);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
}
protected:
@@ -51,7 +51,7 @@ namespace JSC {
JS_EXPORT_PRIVATE InternalFunction(JSGlobalObject*, Structure*);
- JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, const String& name);
+ JS_EXPORT_PRIVATE void finishCreation(VM&, const String& name);
static CallType getCallData(JSCell*, CallData&);
};
diff --git a/Source/JavaScriptCore/runtime/Intrinsic.h b/Source/JavaScriptCore/runtime/Intrinsic.h
index 73244e7c7..313826edb 100644
--- a/Source/JavaScriptCore/runtime/Intrinsic.h
+++ b/Source/JavaScriptCore/runtime/Intrinsic.h
@@ -47,6 +47,8 @@ enum Intrinsic {
LogIntrinsic,
RegExpExecIntrinsic,
RegExpTestIntrinsic,
+ StringPrototypeValueOfIntrinsic,
+ IMulIntrinsic
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
index 21d7b215c..f0910951b 100644
--- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
+++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h
@@ -23,8 +23,8 @@
#ifndef JSAPIValueWrapper_h
#define JSAPIValueWrapper_h
+#include "JSCJSValue.h"
#include "JSCell.h"
-#include "JSValue.h"
#include "CallFrame.h"
#include "Structure.h"
@@ -37,9 +37,9 @@ namespace JSC {
JSValue value() const { return m_value.get(); }
- 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(APIValueWrapperType, OverridesVisitChildren | OverridesGetPropertyNames), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(APIValueWrapperType, OverridesVisitChildren | OverridesGetPropertyNames), &s_info);
}
static JS_EXPORTDATA const ClassInfo s_info;
@@ -54,14 +54,14 @@ namespace JSC {
protected:
void finishCreation(ExecState* exec, JSValue value)
{
- Base::finishCreation(exec->globalData());
- m_value.set(exec->globalData(), this, value);
+ Base::finishCreation(exec->vm());
+ m_value.set(exec->vm(), this, value);
ASSERT(!value.isCell());
}
private:
JSAPIValueWrapper(ExecState* exec)
- : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
+ : JSCell(exec->vm(), exec->vm().apiWrapperStructure.get())
{
}
diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp
index 3b665962f..3a3bb50af 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.cpp
+++ b/Source/JavaScriptCore/runtime/JSActivation.cpp
@@ -32,6 +32,7 @@
#include "Arguments.h"
#include "Interpreter.h"
#include "JSFunction.h"
+#include "Operations.h"
using namespace std;
@@ -85,7 +86,7 @@ inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertyDesc
inline bool JSActivation::symbolTablePut(ExecState* exec, PropertyName propertyName, JSValue value, bool shouldThrow)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
@@ -101,7 +102,7 @@ inline bool JSActivation::symbolTablePut(ExecState* exec, PropertyName propertyN
if (isTornOff() && !isValid(entry))
return false;
- registerAt(entry.getIndex()).set(globalData, this, value);
+ registerAt(entry.getIndex()).set(vm, this, value);
return true;
}
@@ -124,7 +125,7 @@ void JSActivation::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec
JSObject::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
}
-inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
+inline bool JSActivation::symbolTablePutWithAttributes(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -137,7 +138,7 @@ inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData,
return false;
entry.setAttributes(attributes);
- registerAt(entry.getIndex()).set(globalData, this, value);
+ registerAt(entry.getIndex()).set(vm, this, value);
return true;
}
@@ -156,8 +157,8 @@ bool JSActivation::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyNam
if (thisObject->symbolTableGet(propertyName, slot))
return true;
- if (WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName)) {
- slot.setValue(location->get());
+ if (JSValue value = thisObject->getDirect(exec->vm(), propertyName)) {
+ slot.setValue(value);
return true;
}
@@ -200,7 +201,7 @@ void JSActivation::put(JSCell* cell, ExecState* exec, PropertyName propertyName,
// properties are non-standard extensions that other implementations do not
// expose in the activation object.
ASSERT(!thisObject->hasGetterSetterProperties());
- thisObject->putOwnDataProperty(exec->globalData(), propertyName, value, slot);
+ thisObject->putOwnDataProperty(exec->vm(), propertyName, value, slot);
}
// FIXME: Make this function honor ReadOnly (const) and DontEnum
@@ -209,7 +210,7 @@ void JSActivation::putDirectVirtual(JSObject* object, ExecState* exec, PropertyN
JSActivation* thisObject = jsCast<JSActivation*>(object);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
- if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
+ if (thisObject->symbolTablePutWithAttributes(exec->vm(), propertyName, value, attributes))
return;
// We don't call through to JSObject because __proto__ and getter/setter
@@ -244,7 +245,7 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, PropertyName
return arguments;
int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
- JSValue arguments = JSValue(Arguments::create(callFrame->globalData(), callFrame));
+ JSValue arguments = JSValue(Arguments::create(callFrame->vm(), callFrame));
callFrame->uncheckedR(argumentsRegister) = arguments;
callFrame->uncheckedR(realArgumentsRegister) = arguments;
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index b8f5621af..dfbc0c134 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -41,22 +41,22 @@ namespace JSC {
class JSActivation : public JSVariableObject {
private:
- JSActivation(JSGlobalData& globalData, CallFrame*, SharedSymbolTable*);
+ JSActivation(VM& vm, CallFrame*, SharedSymbolTable*);
public:
typedef JSVariableObject Base;
- static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, CodeBlock* codeBlock)
+ static JSActivation* create(VM& vm, CallFrame* callFrame, CodeBlock* codeBlock)
{
SharedSymbolTable* symbolTable = codeBlock->symbolTable();
JSActivation* activation = new (
NotNull,
allocateCell<JSActivation>(
- globalData.heap,
+ vm.heap,
allocationSize(symbolTable)
)
- ) JSActivation(globalData, callFrame, symbolTable);
- activation->finishCreation(globalData);
+ ) JSActivation(vm, callFrame, symbolTable);
+ activation->finishCreation(vm);
return activation;
}
@@ -75,11 +75,11 @@ namespace JSC {
static JSObject* toThisObject(JSCell*, ExecState*);
- void tearOff(JSGlobalData&);
+ void tearOff(VM&);
static const ClassInfo s_info;
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); }
WriteBarrierBase<Unknown>& registerAt(int) const;
bool isValidIndex(int) const;
@@ -96,7 +96,7 @@ namespace JSC {
bool symbolTableGet(PropertyName, PropertyDescriptor&);
bool symbolTableGet(PropertyName, PropertySlot&, bool& slotIsWriteable);
bool symbolTablePut(ExecState*, PropertyName, JSValue, bool shouldThrow);
- bool symbolTablePutWithAttributes(JSGlobalData&, PropertyName, JSValue, unsigned attributes);
+ bool symbolTablePutWithAttributes(VM&, PropertyName, JSValue, unsigned attributes);
static JSValue argumentsGetter(ExecState*, JSValue, PropertyName);
NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
@@ -110,9 +110,9 @@ namespace JSC {
extern int activationCount;
extern int allTheThingsCount;
- inline JSActivation::JSActivation(JSGlobalData& globalData, CallFrame* callFrame, SharedSymbolTable* symbolTable)
+ inline JSActivation::JSActivation(VM& vm, CallFrame* callFrame, SharedSymbolTable* symbolTable)
: Base(
- globalData,
+ vm,
callFrame->lexicalGlobalObject()->activationStructure(),
callFrame->registers(),
callFrame->scope(),
@@ -149,17 +149,17 @@ namespace JSC {
return storageOffset() - (symbolTable->captureStart() * sizeof(WriteBarrier<Unknown>));
}
- inline void JSActivation::tearOff(JSGlobalData& globalData)
+ inline void JSActivation::tearOff(VM& vm)
{
ASSERT(!isTornOff());
- WriteBarrierBase<Unknown>* dst = reinterpret_cast<WriteBarrierBase<Unknown>*>(
+ WriteBarrierBase<Unknown>* dst = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
WriteBarrierBase<Unknown>* src = m_registers;
int captureEnd = symbolTable()->captureEnd();
for (int i = symbolTable()->captureStart(); i < captureEnd; ++i)
- dst[i].set(globalData, this, src[i].get());
+ dst[i].set(vm, this, src[i].get());
m_registers = dst;
ASSERT(isTornOff());
@@ -167,7 +167,7 @@ namespace JSC {
inline bool JSActivation::isTornOff()
{
- return m_registers == reinterpret_cast<WriteBarrierBase<Unknown>*>(
+ return m_registers == reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
}
@@ -178,7 +178,7 @@ namespace JSC {
inline WriteBarrier<Unknown>* JSActivation::storage()
{
- return reinterpret_cast<WriteBarrier<Unknown>*>(
+ return reinterpret_cast_ptr<WriteBarrier<Unknown>*>(
reinterpret_cast<char*>(this) + storageOffset());
}
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index c742804f7..f97ccedcd 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -48,10 +48,10 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray);
const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSArray)};
-Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData& globalData, unsigned initialLength)
+Butterfly* createArrayButterflyInDictionaryIndexingMode(VM& vm, unsigned initialLength)
{
Butterfly* butterfly = Butterfly::create(
- globalData, 0, 0, true, IndexingHeader(), ArrayStorage::sizeFor(0));
+ vm, 0, 0, true, IndexingHeader(), ArrayStorage::sizeFor(0));
ArrayStorage* storage = butterfly->arrayStorage();
storage->setLength(initialLength);
storage->setVectorLength(0);
@@ -67,7 +67,7 @@ void JSArray::setLengthWritable(ExecState* exec, bool writable)
if (!isLengthWritable() || writable)
return;
- enterDictionaryIndexingMode(exec->globalData());
+ enterDictionaryIndexingMode(exec->vm());
SparseArrayValueMap* map = arrayStorage()->m_sparseMap.get();
ASSERT(map);
@@ -244,9 +244,9 @@ void JSArray::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, Pro
}
// This method makes room in the vector, but leaves the new space for count slots uncleared.
-bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, bool addToFront, unsigned count)
+bool JSArray::unshiftCountSlowCase(VM& vm, bool addToFront, unsigned count)
{
- ArrayStorage* storage = ensureArrayStorage(globalData);
+ ArrayStorage* storage = ensureArrayStorage(vm);
Butterfly* butterfly = storage->butterfly();
unsigned propertyCapacity = structure()->outOfLineCapacity();
unsigned propertySize = structure()->outOfLineSize();
@@ -286,7 +286,7 @@ bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, bool addToFront, un
newStorageCapacity = currentCapacity;
} else {
size_t newSize = Butterfly::totalSize(0, propertyCapacity, true, ArrayStorage::sizeFor(desiredCapacity));
- if (!globalData.heap.tryAllocateStorage(newSize, &newAllocBase))
+ if (!vm.heap.tryAllocateStorage(newSize, &newAllocBase))
return false;
newStorageCapacity = desiredCapacity;
}
@@ -349,8 +349,8 @@ bool JSArray::setLengthWithArrayStorage(ExecState* exec, unsigned newLength, boo
if (newLength < length) {
// Copy any keys we might be interested in into a vector.
- Vector<unsigned> keys;
- keys.reserveCapacity(min(map->size(), static_cast<size_t>(length - newLength)));
+ Vector<unsigned, 0, UnsafeVectorOverflow> keys;
+ keys.reserveInitialCapacity(min(map->size(), static_cast<size_t>(length - newLength)));
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
unsigned index = static_cast<unsigned>(it->key);
@@ -408,9 +408,9 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
if (newLength >= MIN_SPARSE_ARRAY_INDEX) {
return setLengthWithArrayStorage(
exec, newLength, throwException,
- convertContiguousToArrayStorage(exec->globalData()));
+ convertContiguousToArrayStorage(exec->vm()));
}
- createInitialUndecided(exec->globalData(), newLength);
+ createInitialUndecided(exec->vm(), newLength);
return true;
case ArrayWithUndecided:
@@ -424,10 +424,10 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
&& !isDenseEnoughForVector(newLength, countElements()))) {
return setLengthWithArrayStorage(
exec, newLength, throwException,
- ensureArrayStorage(exec->globalData()));
+ ensureArrayStorage(exec->vm()));
}
if (newLength > m_butterfly->publicLength()) {
- ensureLength(exec->globalData(), newLength);
+ ensureLength(exec->vm(), newLength);
return true;
}
if (structure()->indexingType() == ArrayWithDouble) {
@@ -469,7 +469,7 @@ JSValue JSArray::pop(ExecState* exec)
if (!length--)
return jsUndefined();
- ASSERT(length < m_butterfly->vectorLength());
+ RELEASE_ASSERT(length < m_butterfly->vectorLength());
JSValue value = m_butterfly->contiguous()[length].get();
if (value) {
m_butterfly->contiguous()[length].clear();
@@ -485,7 +485,7 @@ JSValue JSArray::pop(ExecState* exec)
if (!length--)
return jsUndefined();
- ASSERT(length < m_butterfly->vectorLength());
+ RELEASE_ASSERT(length < m_butterfly->vectorLength());
double value = m_butterfly->contiguousDouble()[length];
if (value == value) {
m_butterfly->contiguousDouble()[length] = QNaN;
@@ -513,7 +513,7 @@ JSValue JSArray::pop(ExecState* exec)
JSValue element = valueSlot.get();
valueSlot.clear();
- ASSERT(isLengthWritable());
+ RELEASE_ASSERT(isLengthWritable());
storage->setLength(index);
return element;
}
@@ -549,19 +549,19 @@ void JSArray::push(ExecState* exec, JSValue value)
{
switch (structure()->indexingType()) {
case ArrayClass: {
- createInitialUndecided(exec->globalData(), 0);
+ createInitialUndecided(exec->vm(), 0);
// Fall through.
}
case ArrayWithUndecided: {
- convertUndecidedForValue(exec->globalData(), value);
+ convertUndecidedForValue(exec->vm(), value);
push(exec, value);
return;
}
case ArrayWithInt32: {
if (!value.isInt32()) {
- convertInt32ForValue(exec->globalData(), value);
+ convertInt32ForValue(exec->vm(), value);
push(exec, value);
return;
}
@@ -589,7 +589,7 @@ void JSArray::push(ExecState* exec, JSValue value)
unsigned length = m_butterfly->publicLength();
ASSERT(length <= m_butterfly->vectorLength());
if (length < m_butterfly->vectorLength()) {
- m_butterfly->contiguous()[length].set(exec->globalData(), this, value);
+ m_butterfly->contiguous()[length].set(exec->vm(), this, value);
m_butterfly->setPublicLength(length + 1);
return;
}
@@ -607,13 +607,13 @@ void JSArray::push(ExecState* exec, JSValue value)
case ArrayWithDouble: {
if (!value.isNumber()) {
- convertDoubleToContiguous(exec->globalData());
+ convertDoubleToContiguous(exec->vm());
push(exec, value);
return;
}
double valueAsDouble = value.asNumber();
if (valueAsDouble != valueAsDouble) {
- convertDoubleToContiguous(exec->globalData());
+ convertDoubleToContiguous(exec->vm());
push(exec, value);
return;
}
@@ -653,7 +653,7 @@ void JSArray::push(ExecState* exec, JSValue value)
// Fast case - push within vector, always update m_length & m_numValuesInVector.
unsigned length = storage->length();
if (length < storage->vectorLength()) {
- storage->m_vector[length].set(exec->globalData(), this, value);
+ storage->m_vector[length].set(exec->vm(), this, value);
storage->setLength(length + 1);
++storage->m_numValuesInVector;
return;
@@ -674,14 +674,14 @@ void JSArray::push(ExecState* exec, JSValue value)
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
bool JSArray::shiftCountWithArrayStorage(unsigned startIndex, unsigned count, ArrayStorage* storage)
{
unsigned oldLength = storage->length();
- ASSERT(count <= oldLength);
+ RELEASE_ASSERT(count <= oldLength);
// If the array contains holes or is otherwise in an abnormal state,
// use the generic algorithm in ArrayPrototype.
@@ -736,7 +736,7 @@ bool JSArray::shiftCountWithArrayStorage(unsigned startIndex, unsigned count, Ar
bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex, unsigned count)
{
- ASSERT(count > 0);
+ RELEASE_ASSERT(count > 0);
switch (structure()->indexingType()) {
case ArrayClass:
@@ -749,12 +749,12 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex
case ArrayWithInt32:
case ArrayWithContiguous: {
unsigned oldLength = m_butterfly->publicLength();
- ASSERT(count <= oldLength);
+ RELEASE_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()));
+ return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->vm()));
unsigned end = oldLength - count;
for (unsigned i = startIndex; i < end; ++i) {
@@ -768,7 +768,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, ensureArrayStorage(exec->vm()));
}
// 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
@@ -784,12 +784,12 @@ bool JSArray::shiftCountWithAnyIndexingType(ExecState* exec, unsigned startIndex
case ArrayWithDouble: {
unsigned oldLength = m_butterfly->publicLength();
- ASSERT(count <= oldLength);
+ RELEASE_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()));
+ return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->vm()));
unsigned end = oldLength - count;
for (unsigned i = startIndex; i < end; ++i) {
@@ -803,7 +803,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, ensureArrayStorage(exec->vm()));
}
// 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
@@ -832,7 +832,7 @@ bool JSArray::unshiftCountWithArrayStorage(ExecState* exec, unsigned startIndex,
{
unsigned length = storage->length();
- ASSERT(startIndex <= length);
+ RELEASE_ASSERT(startIndex <= length);
// If the array contains holes or is otherwise in an abnormal state,
// use the generic algorithm in ArrayPrototype.
@@ -850,7 +850,7 @@ bool JSArray::unshiftCountWithArrayStorage(ExecState* exec, unsigned startIndex,
storage->setVectorLength(vectorLength + count);
} else if (!moveFront && vectorLength - length >= count)
storage = storage->butterfly()->arrayStorage();
- else if (unshiftCountSlowCase(exec->globalData(), moveFront, count))
+ else if (unshiftCountSlowCase(exec->vm(), moveFront, count))
storage = arrayStorage();
else {
throwOutOfMemoryError(exec);
@@ -886,14 +886,14 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd
// 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, ensureArrayStorage(exec->vm()));
- ensureLength(exec->globalData(), oldLength + count);
+ ensureLength(exec->vm(), 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, ensureArrayStorage(exec->vm()));
m_butterfly->contiguous()[i + count].setWithoutWriteBarrier(v);
}
@@ -911,14 +911,14 @@ bool JSArray::unshiftCountWithAnyIndexingType(ExecState* exec, unsigned startInd
// 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, ensureArrayStorage(exec->vm()));
- ensureLength(exec->globalData(), oldLength + count);
+ ensureLength(exec->vm(), 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()));
+ return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->vm()));
m_butterfly->contiguousDouble()[i + count] = v;
}
@@ -979,7 +979,7 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy
lengthNotIncludingUndefined,
newRelevantLength);
- WriteBarrier<Unknown>* data = indexingData<indexingType>();
+ ContiguousJSValues data = indexingData<indexingType>();
if (indexingType == ArrayWithArrayStorage && arrayStorage()->m_sparseMap.get()) {
throwOutOfMemoryError(exec);
@@ -1026,8 +1026,8 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy
compare = compareNumbersForQSort;
break;
}
-
- qsort(data, newRelevantLength, sizeof(WriteBarrier<Unknown>), compare);
+ ASSERT(data.length() >= newRelevantLength);
+ qsort(data.data(), newRelevantLength, sizeof(WriteBarrier<Unknown>), compare);
return;
}
@@ -1061,20 +1061,47 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
}
}
-template<IndexingType indexingType>
-void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevantLength)
+template <IndexingType> struct ContiguousTypeAccessor {
+ typedef WriteBarrier<Unknown> Type;
+ static JSValue getAsValue(ContiguousData<Type> data, size_t i) { return data[i].get(); }
+ static void setWithValue(VM& vm, JSArray* thisValue, ContiguousData<Type> data, size_t i, JSValue value)
+ {
+ data[i].set(vm, thisValue, value);
+ }
+ static void replaceDataReference(ContiguousData<Type>* outData, ContiguousJSValues inData)
+ {
+ *outData = inData;
+ }
+};
+
+template <> struct ContiguousTypeAccessor<ArrayWithDouble> {
+ typedef double Type;
+ static JSValue getAsValue(ContiguousData<Type> data, size_t i) { ASSERT(data[i] == data[i]); return JSValue(JSValue::EncodeAsDouble, data[i]); }
+ static void setWithValue(VM&, JSArray*, ContiguousData<Type> data, size_t i, JSValue value)
+ {
+ data[i] = value.asNumber();
+ }
+ static NO_RETURN_DUE_TO_CRASH void replaceDataReference(ContiguousData<Type>*, ContiguousJSValues)
+ {
+ RELEASE_ASSERT_WITH_MESSAGE(0, "Inconsistent indexing types during compact array sort.");
+ }
+};
+
+
+template<IndexingType indexingType, typename StorageType>
+void JSArray::sortCompactedVector(ExecState* exec, ContiguousData<StorageType> data, unsigned relevantLength)
{
if (!relevantLength)
return;
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// Converting JavaScript values to strings can be expensive, so we do it once up front and sort based on that.
// This is a considerable improvement over doing it twice per comparison, though it requires a large temporary
// buffer. Besides, this protects us from crashing if some objects have custom toString methods that return
// random or otherwise changing results, effectively making compare function inconsistent.
- Vector<ValueStringPair> values(relevantLength);
+ Vector<ValueStringPair, 0, UnsafeVectorOverflow> values(relevantLength);
if (!values.begin()) {
throwOutOfMemoryError(exec);
return;
@@ -1083,31 +1110,14 @@ 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;
+
+ for (size_t i = 0; i < relevantLength; i++) {
+ JSValue value = ContiguousTypeAccessor<indexingType>::getAsValue(data, i);
+ ASSERT(indexingType != ArrayWithInt32 || value.isInt32());
+ ASSERT(!value.isUndefined());
+ values[i].first = value;
+ if (indexingType != ArrayWithDouble && indexingType != ArrayWithInt32)
isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive();
- }
- break;
}
// FIXME: The following loop continues to call toString on subsequent values even after
@@ -1141,13 +1151,13 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan
case ArrayWithInt32:
case ArrayWithDouble:
case ArrayWithContiguous:
- ensureLength(globalData, relevantLength);
+ ensureLength(vm, relevantLength);
break;
case ArrayWithArrayStorage:
if (arrayStorage()->vectorLength() < relevantLength) {
- increaseVectorLength(exec->globalData(), relevantLength);
- begin = arrayStorage()->m_vector;
+ increaseVectorLength(exec->vm(), relevantLength);
+ ContiguousTypeAccessor<indexingType>::replaceDataReference(&data, arrayStorage()->vector());
}
if (arrayStorage()->length() < relevantLength)
arrayStorage()->setLength(relevantLength);
@@ -1157,12 +1167,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++)
+ ContiguousTypeAccessor<indexingType>::setWithValue(vm, this, data, i, values[i].first);
Heap::heap(this)->popTempSortVector(&values);
}
@@ -1217,13 +1223,12 @@ void JSArray::sort(ExecState* exec)
ArrayStorage* storage = m_butterfly->arrayStorage();
ASSERT(!storage->m_sparseMap);
- sortCompactedVector<ArrayWithArrayStorage>(
- exec, storage->m_vector, lengthNotIncludingUndefined);
+ sortCompactedVector<ArrayWithArrayStorage>(exec, storage->vector(), lengthNotIncludingUndefined);
return;
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
@@ -1242,7 +1247,7 @@ struct AVLTreeAbstractorForArrayCompare {
typedef JSValue key;
typedef int32_t size;
- Vector<AVLTreeNodeForArrayCompare> m_nodes;
+ Vector<AVLTreeNodeForArrayCompare, 0, UnsafeVectorOverflow> m_nodes;
ExecState* m_exec;
JSValue m_compareFunction;
CallType m_compareCallType;
@@ -1382,13 +1387,13 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call
// Copy the values back into m_storage.
AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;
iter.start_iter_least(tree);
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
for (unsigned i = 0; i < elementsToExtractThreshold; ++i) {
ASSERT(i < butterfly()->vectorLength());
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(vm, this, tree.abstractor().m_nodes[*iter].value);
++iter;
}
// Put undefined values back in.
@@ -1444,7 +1449,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
return;
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
@@ -1467,7 +1472,7 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
case ArrayWithInt32:
case ArrayWithContiguous: {
vectorEnd = m_butterfly->publicLength();
- vector = m_butterfly->contiguous();
+ vector = m_butterfly->contiguous().data();
break;
}
@@ -1528,7 +1533,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le
case ArrayWithInt32:
case ArrayWithContiguous: {
- vector = m_butterfly->contiguous();
+ vector = m_butterfly->contiguous().data();
vectorEnd = m_butterfly->publicLength();
break;
}
@@ -1635,12 +1640,12 @@ void JSArray::compactForSorting(unsigned& numDefined, unsigned& newRelevantLengt
newRelevantLength = numDefined + numUndefined;
if (hasArrayStorage(indexingType))
- ASSERT(!arrayStorage()->m_sparseMap);
+ RELEASE_ASSERT(!arrayStorage()->m_sparseMap);
switch (indexingType) {
case ArrayWithInt32:
case ArrayWithDouble:
- ASSERT(numDefined == newRelevantLength);
+ RELEASE_ASSERT(numDefined == newRelevantLength);
break;
default:
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index cef3b53ad..af81d2e3f 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -39,19 +39,19 @@ public:
typedef JSNonFinalObject Base;
protected:
- explicit JSArray(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly)
- : JSNonFinalObject(globalData, structure, butterfly)
+ explicit JSArray(VM& vm, Structure* structure, Butterfly* butterfly)
+ : JSNonFinalObject(vm, structure, butterfly)
{
}
public:
- static JSArray* create(JSGlobalData&, Structure*, unsigned initialLength = 0);
+ static JSArray* create(VM&, Structure*, unsigned initialLength = 0);
// tryCreateUninitialized is used for fast construction of arrays whose size and
// contents are known at time of creation. Clients of this interface must:
// - null-check the result (indicating out of memory, or otherwise unable to allocate vector).
// - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength.
- static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
+ static JSArray* tryCreateUninitialized(VM&, Structure*, unsigned initialLength);
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
@@ -84,7 +84,7 @@ public:
bool shiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
{
- return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData()));
+ return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->vm()));
}
bool shiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
{
@@ -106,7 +106,7 @@ public:
bool unshiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
{
- return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData()));
+ return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->vm()));
}
bool unshiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
{
@@ -129,9 +129,9 @@ public:
void fillArgList(ExecState*, MarkedArgumentBuffer&);
void copyToArguments(ExecState*, CallFrame*, uint32_t length);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
{
- return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, indexingType);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, indexingType);
}
protected:
@@ -156,13 +156,13 @@ private:
bool unshiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
bool unshiftCountWithArrayStorage(ExecState*, unsigned startIndex, unsigned count, ArrayStorage*);
- bool unshiftCountSlowCase(JSGlobalData&, bool, unsigned);
+ bool unshiftCountSlowCase(VM&, bool, unsigned);
template<IndexingType indexingType>
void sortNumericVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
- template<IndexingType indexingType>
- void sortCompactedVector(ExecState*, void* begin, unsigned relevantLength);
+ template<IndexingType indexingType, typename StorageType>
+ void sortCompactedVector(ExecState*, ContiguousData<StorageType>, unsigned relevantLength);
template<IndexingType indexingType>
void sortVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
@@ -174,21 +174,21 @@ private:
void compactForSorting(unsigned& numDefined, unsigned& newRelevantLength);
};
-inline Butterfly* createContiguousArrayButterfly(JSGlobalData& globalData, unsigned length, unsigned& vectorLength)
+inline Butterfly* createContiguousArrayButterfly(VM& vm, unsigned length, unsigned& vectorLength)
{
IndexingHeader header;
vectorLength = std::max(length, BASE_VECTOR_LEN);
header.setVectorLength(vectorLength);
header.setPublicLength(length);
Butterfly* result = Butterfly::create(
- globalData, 0, 0, true, header, vectorLength * sizeof(EncodedJSValue));
+ vm, 0, 0, true, header, vectorLength * sizeof(EncodedJSValue));
return result;
}
-inline Butterfly* createArrayButterfly(JSGlobalData& globalData, unsigned initialLength)
+inline Butterfly* createArrayButterfly(VM& vm, unsigned initialLength)
{
Butterfly* butterfly = Butterfly::create(
- globalData, 0, 0, true, baseIndexingHeaderForArray(initialLength), ArrayStorage::sizeFor(BASE_VECTOR_LEN));
+ vm, 0, 0, true, baseIndexingHeaderForArray(initialLength), ArrayStorage::sizeFor(BASE_VECTOR_LEN));
ArrayStorage* storage = butterfly->arrayStorage();
storage->m_indexBias = 0;
storage->m_sparseMap.clear();
@@ -196,9 +196,9 @@ inline Butterfly* createArrayButterfly(JSGlobalData& globalData, unsigned initia
return butterfly;
}
-Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData&, unsigned initialLength);
+Butterfly* createArrayButterflyInDictionaryIndexingMode(VM&, unsigned initialLength);
-inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+inline JSArray* JSArray::create(VM& vm, Structure* structure, unsigned initialLength)
{
Butterfly* butterfly;
if (LIKELY(!hasArrayStorage(structure->indexingType()))) {
@@ -208,7 +208,7 @@ inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure,
|| hasDouble(structure->indexingType())
|| hasContiguous(structure->indexingType()));
unsigned vectorLength;
- butterfly = createContiguousArrayButterfly(globalData, initialLength, vectorLength);
+ butterfly = createContiguousArrayButterfly(vm, initialLength, vectorLength);
ASSERT(initialLength < MIN_SPARSE_ARRAY_INDEX);
if (hasDouble(structure->indexingType())) {
for (unsigned i = 0; i < vectorLength; ++i)
@@ -218,14 +218,14 @@ inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure,
ASSERT(
structure->indexingType() == ArrayWithSlowPutArrayStorage
|| structure->indexingType() == ArrayWithArrayStorage);
- butterfly = createArrayButterfly(globalData, initialLength);
+ butterfly = createArrayButterfly(vm, initialLength);
}
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
- array->finishCreation(globalData);
+ JSArray* array = new (NotNull, allocateCell<JSArray>(vm.heap)) JSArray(vm, structure, butterfly);
+ array->finishCreation(vm);
return array;
}
-inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+inline JSArray* JSArray::tryCreateUninitialized(VM& vm, Structure* structure, unsigned initialLength)
{
unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
@@ -240,7 +240,7 @@ inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Struct
|| hasContiguous(structure->indexingType()));
void* temp;
- if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, vectorLength * sizeof(EncodedJSValue)), &temp))
+ if (!vm.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, vectorLength * sizeof(EncodedJSValue)), &temp))
return 0;
butterfly = Butterfly::fromBase(temp, 0, 0);
butterfly->setVectorLength(vectorLength);
@@ -251,7 +251,7 @@ inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Struct
}
} else {
void* temp;
- if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(vectorLength)), &temp))
+ if (!vm.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(vectorLength)), &temp))
return 0;
butterfly = Butterfly::fromBase(temp, 0, 0);
*butterfly->indexingHeader() = indexingHeaderForArray(initialLength, vectorLength);
@@ -261,8 +261,8 @@ inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Struct
storage->m_numValuesInVector = initialLength;
}
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
- array->finishCreation(globalData);
+ JSArray* array = new (NotNull, allocateCell<JSArray>(vm.heap)) JSArray(vm, structure, butterfly);
+ array->finishCreation(vm);
return array;
}
@@ -284,34 +284,32 @@ inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); }
inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const ArgList& values)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
unsigned length = values.size();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+ JSArray* array = JSArray::tryCreateUninitialized(vm, arrayStructure, length);
// FIXME: we should probably throw an out of memory error here, but
// when making this change we should check that all clients of this
// function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
+ RELEASE_ASSERT(array);
for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values.at(i));
+ array->initializeIndex(vm, i, values.at(i));
return array;
}
inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
{
- JSGlobalData& globalData = exec->globalData();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+ VM& vm = exec->vm();
+ JSArray* array = JSArray::tryCreateUninitialized(vm, arrayStructure, length);
// FIXME: we should probably throw an out of memory error here, but
// when making this change we should check that all clients of this
// function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
+ RELEASE_ASSERT(array);
for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values[i]);
+ array->initializeIndex(vm, i, values[i]);
return array;
}
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
index bb1af9d20..fb255d954 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
@@ -28,6 +28,7 @@
#include "GetterSetter.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
namespace JSC {
@@ -78,8 +79,7 @@ JSBoundFunction* JSBoundFunction::create(ExecState* exec, JSGlobalObject* global
ConstructData constructData;
ConstructType constructType = JSC::getConstructData(targetFunction, constructData);
bool canConstruct = constructType != ConstructTypeNone;
-
- NativeExecutable* executable = exec->globalData().getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor);
+ NativeExecutable* executable = exec->vm().getHostFunction(boundFunctionCall, canConstruct ? boundFunctionConstruct : callHostFunctionAsConstructor);
JSBoundFunction* function = new (NotNull, allocateCell<JSBoundFunction>(*exec->heap())) JSBoundFunction(exec, globalObject, globalObject->boundFunctionStructure(), targetFunction, boundThis, boundArgs);
function->finishCreation(exec, executable, length, name);
@@ -98,9 +98,9 @@ bool JSBoundFunction::customHasInstance(JSObject* object, ExecState* exec, JSVal
JSBoundFunction::JSBoundFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSObject* targetFunction, JSValue boundThis, JSValue boundArgs)
: Base(exec, globalObject, structure)
- , m_targetFunction(exec->globalData(), this, targetFunction)
- , m_boundThis(exec->globalData(), this, boundThis)
- , m_boundArgs(exec->globalData(), this, boundArgs)
+ , m_targetFunction(exec->vm(), this, targetFunction)
+ , m_boundThis(exec->vm(), this, boundThis)
+ , m_boundArgs(exec->vm(), this, boundArgs)
{
}
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h
index 886021940..3378d4048 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.h
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.h
@@ -47,10 +47,10 @@ public:
JSValue boundThis() { return m_boundThis.get(); }
JSValue boundArgs() { return m_boundArgs.get(); }
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
ASSERT(globalObject);
- return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSCJSValue.cpp
index d9253730f..627e9e077 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSCJSValue.cpp
@@ -21,15 +21,16 @@
*/
#include "config.h"
-#include "JSValue.h"
+#include "JSCJSValue.h"
#include "BooleanConstructor.h"
#include "BooleanPrototype.h"
#include "Error.h"
#include "ExceptionHelpers.h"
#include "GetterSetter.h"
-#include "JSGlobalObject.h"
+#include "JSCJSValueInlines.h"
#include "JSFunction.h"
+#include "JSGlobalObject.h"
#include "JSNotAnObject.h"
#include "NumberObject.h"
#include <wtf/MathExtras.h>
@@ -45,7 +46,7 @@ double JSValue::toInteger(ExecState* exec) const
if (isInt32())
return asInt32();
double d = toNumber(exec);
- return isnan(d) ? 0.0 : trunc(d);
+ return std::isnan(d) ? 0.0 : trunc(d);
}
double JSValue::toIntegerPreserveNaN(ExecState* exec) const
@@ -111,7 +112,7 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const
// ECMA 8.7.2
void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
unsigned index = propertyName.asIndex();
if (index != PropertyName::NotAnIndex) {
@@ -136,7 +137,7 @@ void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
for (; ; obj = asObject(prototype)) {
unsigned attributes;
JSCell* specificValue;
- PropertyOffset offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+ PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes, specificValue);
if (offset != invalidOffset) {
if (attributes & ReadOnly) {
if (slot.isStrictMode())
@@ -144,7 +145,7 @@ void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
return;
}
- JSValue gs = obj->getDirectOffset(offset);
+ JSValue gs = obj->getDirect(offset);
if (gs.isGetterSetter()) {
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
@@ -193,51 +194,53 @@ void JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSVa
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
}
-char* JSValue::description() const
+void JSValue::dump(PrintStream& out) const
{
- static const size_t size = 256;
- static char description[size];
-
if (!*this)
- snprintf(description, size, "<JSValue()>");
+ out.print("<JSValue()>");
else if (isInt32())
- snprintf(description, size, "Int32: %d", asInt32());
+ out.printf("Int32: %d", asInt32());
else if (isDouble()) {
#if USE(JSVALUE64)
- snprintf(description, size, "Double: %lld, %lf", (long long)reinterpretDoubleToInt64(asDouble()), asDouble());
+ out.printf("Double: %lld, %lf", (long long)reinterpretDoubleToInt64(asDouble()), asDouble());
#else
union {
double asDouble;
uint32_t asTwoInt32s[2];
} u;
u.asDouble = asDouble();
- snprintf(description, size, "Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
+ out.printf("Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
#endif
} else if (isCell()) {
- if (asCell()->inherits(&Structure::s_info)) {
+ if (asCell()->inherits(&JSString::s_info)) {
+ JSString* string = jsCast<JSString*>(asCell());
+ out.print("String: ");
+ if (string->isRope())
+ out.print("(rope) ");
+ out.print(string->tryGetValue());
+ } else if (asCell()->inherits(&Structure::s_info)) {
Structure* structure = jsCast<Structure*>(asCell());
- snprintf(
- description, size, "Structure: %p: %s, %s",
- structure, structure->classInfo()->className,
- indexingTypeToString(structure->indexingTypeIncludingHistory()));
+ out.print(
+ "Structure: ", RawPointer(structure), ": ", structure->classInfo()->className,
+ ", ", IndexingTypeDump(structure->indexingTypeIncludingHistory()));
} else {
- snprintf(
- description, size, "Cell: %p -> %p (%p: %s, %s)",
- asCell(), isObject() ? asObject(*this)->butterfly() : 0, asCell()->structure(), asCell()->structure()->classInfo()->className,
- indexingTypeToString(asCell()->structure()->indexingTypeIncludingHistory()));
+ out.print("Cell: ", RawPointer(asCell()));
+ if (isObject() && asObject(*this)->butterfly())
+ out.print("->", RawPointer(asObject(*this)->butterfly()));
+ out.print(
+ " (", RawPointer(asCell()->structure()), ": ", asCell()->structure()->classInfo()->className,
+ ", ", IndexingTypeDump(asCell()->structure()->indexingTypeIncludingHistory()), ")");
}
} else if (isTrue())
- snprintf(description, size, "True");
+ out.print("True");
else if (isFalse())
- snprintf(description, size, "False");
+ out.print("False");
else if (isNull())
- snprintf(description, size, "Null");
+ out.print("Null");
else if (isUndefined())
- snprintf(description, size, "Undefined");
+ out.print("Undefined");
else
- snprintf(description, size, "INVALID");
-
- return description;
+ out.print("INVALID");
}
// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
@@ -292,20 +295,20 @@ bool JSValue::isValidCallee()
JSString* JSValue::toStringSlowCase(ExecState* exec) const
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
ASSERT(!isString());
if (isInt32())
- return jsString(&globalData, globalData.numericStrings.add(asInt32()));
+ return jsString(&vm, vm.numericStrings.add(asInt32()));
if (isDouble())
- return jsString(&globalData, globalData.numericStrings.add(asDouble()));
+ return jsString(&vm, vm.numericStrings.add(asDouble()));
if (isTrue())
- return globalData.smallStrings.trueString(&globalData);
+ return vm.smallStrings.trueString();
if (isFalse())
- return globalData.smallStrings.falseString(&globalData);
+ return vm.smallStrings.falseString();
if (isNull())
- return globalData.smallStrings.nullString(&globalData);
+ return vm.smallStrings.nullString();
if (isUndefined())
- return globalData.smallStrings.undefinedString(&globalData);
+ return vm.smallStrings.undefinedString();
ASSERT(isCell());
JSValue value = asCell()->toPrimitive(exec, PreferString);
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSCJSValue.h
index f6447d0bd..abb4b8109 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSCJSValue.h
@@ -20,18 +20,19 @@
*
*/
-#ifndef JSValue_h
-#define JSValue_h
+#ifndef JSCJSValue_h
+#define JSCJSValue_h
#include <math.h>
#include <stddef.h> // for size_t
#include <stdint.h>
-#include <wtf/AlwaysInline.h>
#include <wtf/Assertions.h>
+#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/HashTraits.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/TriState.h>
namespace JSC {
@@ -41,7 +42,7 @@ namespace JSC {
class ExecState;
class JSCell;
-class JSGlobalData;
+class VM;
class JSGlobalObject;
class JSObject;
class JSString;
@@ -213,6 +214,7 @@ public:
bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
bool toBoolean(ExecState*) const;
+ TriState pureToBoolean() const;
// toNumber conversion is expected to be side effect free if an exception has
// been set in the ExecState already.
@@ -245,12 +247,12 @@ public:
JSObject* toThisObject(ExecState*) const;
- static bool equal(ExecState* exec, JSValue v1, JSValue v2);
- static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2);
- static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
- static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2);
- static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2);
- static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2);
+ static bool equal(ExecState*, JSValue v1, JSValue v2);
+ static bool equalSlowCase(ExecState*, JSValue v1, JSValue v2);
+ static bool equalSlowCaseInline(ExecState*, JSValue v1, JSValue v2);
+ static bool strictEqual(ExecState*, JSValue v1, JSValue v2);
+ static bool strictEqualSlowCase(ExecState*, JSValue v1, JSValue v2);
+ static bool strictEqualSlowCaseInline(ExecState*, JSValue v1, JSValue v2);
bool isCell() const;
JSCell* asCell() const;
@@ -258,7 +260,7 @@ public:
JSValue structureOrUndefined() const;
- JS_EXPORT_PRIVATE char* description() const;
+ JS_EXPORT_PRIVATE void dump(PrintStream&) const;
JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
@@ -494,4 +496,4 @@ inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) !=
} // namespace JSC
-#endif // JSValue_h
+#endif // JSCJSValue_h
diff --git a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
new file mode 100644
index 000000000..e22fe244f
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSValueInlines_h
+#define JSValueInlines_h
+
+#include "InternalFunction.h"
+#include "JSCJSValue.h"
+#include "JSCellInlines.h"
+#include "JSFunction.h"
+
+namespace JSC {
+
+ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
+{
+ if (isInt32())
+ return asInt32();
+ return JSC::toInt32(toNumber(exec));
+}
+
+inline uint32_t JSValue::toUInt32(ExecState* exec) const
+{
+ // See comment on JSC::toUInt32, above.
+ return toInt32(exec);
+}
+
+inline bool JSValue::isUInt32() const
+{
+ return isInt32() && asInt32() >= 0;
+}
+
+inline uint32_t JSValue::asUInt32() const
+{
+ ASSERT(isUInt32());
+ return asInt32();
+}
+
+inline double JSValue::asNumber() const
+{
+ ASSERT(isNumber());
+ return isInt32() ? asInt32() : asDouble();
+}
+
+inline JSValue jsNaN()
+{
+ return JSValue(QNaN);
+}
+
+inline JSValue::JSValue(char i)
+{
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(unsigned char i)
+{
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(short i)
+{
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(unsigned short i)
+{
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(unsigned i)
+{
+ if (static_cast<int32_t>(i) < 0) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(long i)
+{
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(unsigned long i)
+{
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<uint32_t>(i));
+}
+
+inline JSValue::JSValue(long long i)
+{
+ if (static_cast<int32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(i));
+}
+
+inline JSValue::JSValue(unsigned long long i)
+{
+ if (static_cast<uint32_t>(i) != i) {
+ *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+ return;
+ }
+ *this = JSValue(static_cast<uint32_t>(i));
+}
+
+inline JSValue::JSValue(double d)
+{
+ const int32_t asInt32 = static_cast<int32_t>(d);
+ if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
+ *this = JSValue(EncodeAsDouble, d);
+ return;
+ }
+ *this = JSValue(static_cast<int32_t>(d));
+}
+
+inline EncodedJSValue JSValue::encode(JSValue value)
+{
+ return value.u.asInt64;
+}
+
+inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
+{
+ JSValue v;
+ v.u.asInt64 = encodedJSValue;
+ return v;
+}
+
+#if USE(JSVALUE32_64)
+inline JSValue::JSValue()
+{
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = 0;
+}
+
+inline JSValue::JSValue(JSNullTag)
+{
+ u.asBits.tag = NullTag;
+ u.asBits.payload = 0;
+}
+
+inline JSValue::JSValue(JSUndefinedTag)
+{
+ u.asBits.tag = UndefinedTag;
+ u.asBits.payload = 0;
+}
+
+inline JSValue::JSValue(JSTrueTag)
+{
+ u.asBits.tag = BooleanTag;
+ u.asBits.payload = 1;
+}
+
+inline JSValue::JSValue(JSFalseTag)
+{
+ u.asBits.tag = BooleanTag;
+ u.asBits.payload = 0;
+}
+
+inline JSValue::JSValue(HashTableDeletedValueTag)
+{
+ u.asBits.tag = DeletedValueTag;
+ u.asBits.payload = 0;
+}
+
+inline JSValue::JSValue(JSCell* ptr)
+{
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(ptr);
+}
+
+inline JSValue::JSValue(const JSCell* ptr)
+{
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
+ u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
+}
+
+inline JSValue::operator bool() const
+{
+ ASSERT(tag() != DeletedValueTag);
+ return tag() != EmptyValueTag;
+}
+
+inline bool JSValue::operator==(const JSValue& other) const
+{
+ return u.asInt64 == other.u.asInt64;
+}
+
+inline bool JSValue::operator!=(const JSValue& other) const
+{
+ return u.asInt64 != other.u.asInt64;
+}
+
+inline bool JSValue::isEmpty() const
+{
+ return tag() == EmptyValueTag;
+}
+
+inline bool JSValue::isUndefined() const
+{
+ return tag() == UndefinedTag;
+}
+
+inline bool JSValue::isNull() const
+{
+ return tag() == NullTag;
+}
+
+inline bool JSValue::isUndefinedOrNull() const
+{
+ return isUndefined() || isNull();
+}
+
+inline bool JSValue::isCell() const
+{
+ return tag() == CellTag;
+}
+
+inline bool JSValue::isInt32() const
+{
+ return tag() == Int32Tag;
+}
+
+inline bool JSValue::isDouble() const
+{
+ return tag() < LowestTag;
+}
+
+inline bool JSValue::isTrue() const
+{
+ return tag() == BooleanTag && payload();
+}
+
+inline bool JSValue::isFalse() const
+{
+ return tag() == BooleanTag && !payload();
+}
+
+inline uint32_t JSValue::tag() const
+{
+ return u.asBits.tag;
+}
+
+inline int32_t JSValue::payload() const
+{
+ return u.asBits.payload;
+}
+
+inline int32_t JSValue::asInt32() const
+{
+ ASSERT(isInt32());
+ return u.asBits.payload;
+}
+
+inline double JSValue::asDouble() const
+{
+ ASSERT(isDouble());
+ return u.asDouble;
+}
+
+ALWAYS_INLINE JSCell* JSValue::asCell() const
+{
+ ASSERT(isCell());
+ return reinterpret_cast<JSCell*>(u.asBits.payload);
+}
+
+ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+{
+ u.asDouble = d;
+}
+
+inline JSValue::JSValue(int i)
+{
+ u.asBits.tag = Int32Tag;
+ u.asBits.payload = i;
+}
+
+#if ENABLE(LLINT_C_LOOP)
+inline JSValue::JSValue(int32_t tag, int32_t payload)
+{
+ u.asBits.tag = tag;
+ u.asBits.payload = payload;
+}
+#endif
+
+inline bool JSValue::isNumber() const
+{
+ return isInt32() || isDouble();
+}
+
+inline bool JSValue::isBoolean() const
+{
+ return isTrue() || isFalse();
+}
+
+inline bool JSValue::asBoolean() const
+{
+ ASSERT(isBoolean());
+ return payload();
+}
+
+#else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
+
+// 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
+inline JSValue::JSValue()
+{
+ u.asInt64 = ValueEmpty;
+}
+
+// 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
+inline JSValue::JSValue(HashTableDeletedValueTag)
+{
+ u.asInt64 = ValueDeleted;
+}
+
+inline JSValue::JSValue(JSCell* ptr)
+{
+ u.asInt64 = reinterpret_cast<uintptr_t>(ptr);
+}
+
+inline JSValue::JSValue(const JSCell* ptr)
+{
+ u.asInt64 = reinterpret_cast<uintptr_t>(const_cast<JSCell*>(ptr));
+}
+
+inline JSValue::operator bool() const
+{
+ return u.asInt64;
+}
+
+inline bool JSValue::operator==(const JSValue& other) const
+{
+ return u.asInt64 == other.u.asInt64;
+}
+
+inline bool JSValue::operator!=(const JSValue& other) const
+{
+ return u.asInt64 != other.u.asInt64;
+}
+
+inline bool JSValue::isEmpty() const
+{
+ return u.asInt64 == ValueEmpty;
+}
+
+inline bool JSValue::isUndefined() const
+{
+ return asValue() == JSValue(JSUndefined);
+}
+
+inline bool JSValue::isNull() const
+{
+ return asValue() == JSValue(JSNull);
+}
+
+inline bool JSValue::isTrue() const
+{
+ return asValue() == JSValue(JSTrue);
+}
+
+inline bool JSValue::isFalse() const
+{
+ return asValue() == JSValue(JSFalse);
+}
+
+inline bool JSValue::asBoolean() const
+{
+ ASSERT(isBoolean());
+ return asValue() == JSValue(JSTrue);
+}
+
+inline int32_t JSValue::asInt32() const
+{
+ ASSERT(isInt32());
+ return static_cast<int32_t>(u.asInt64);
+}
+
+inline bool JSValue::isDouble() const
+{
+ return isNumber() && !isInt32();
+}
+
+inline JSValue::JSValue(JSNullTag)
+{
+ u.asInt64 = ValueNull;
+}
+
+inline JSValue::JSValue(JSUndefinedTag)
+{
+ u.asInt64 = ValueUndefined;
+}
+
+inline JSValue::JSValue(JSTrueTag)
+{
+ u.asInt64 = ValueTrue;
+}
+
+inline JSValue::JSValue(JSFalseTag)
+{
+ u.asInt64 = ValueFalse;
+}
+
+inline bool JSValue::isUndefinedOrNull() const
+{
+ // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
+ return (u.asInt64 & ~TagBitUndefined) == ValueNull;
+}
+
+inline bool JSValue::isBoolean() const
+{
+ return (u.asInt64 & ~1) == ValueFalse;
+}
+
+inline bool JSValue::isCell() const
+{
+ return !(u.asInt64 & TagMask);
+}
+
+inline bool JSValue::isInt32() const
+{
+ return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
+}
+
+inline int64_t reinterpretDoubleToInt64(double value)
+{
+ return bitwise_cast<int64_t>(value);
+}
+inline double reinterpretInt64ToDouble(int64_t value)
+{
+ return bitwise_cast<double>(value);
+}
+
+ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+{
+ u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
+}
+
+inline JSValue::JSValue(int i)
+{
+ u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
+}
+
+inline double JSValue::asDouble() const
+{
+ ASSERT(isDouble());
+ return reinterpretInt64ToDouble(u.asInt64 - DoubleEncodeOffset);
+}
+
+inline bool JSValue::isNumber() const
+{
+ return u.asInt64 & TagTypeNumber;
+}
+
+ALWAYS_INLINE JSCell* JSValue::asCell() const
+{
+ ASSERT(isCell());
+ return u.ptr;
+}
+
+#endif // USE(JSVALUE64)
+
+inline bool JSValue::isString() const
+{
+ return isCell() && asCell()->isString();
+}
+
+inline bool JSValue::isPrimitive() const
+{
+ return !isCell() || asCell()->isString();
+}
+
+inline bool JSValue::isGetterSetter() const
+{
+ return isCell() && asCell()->isGetterSetter();
+}
+
+inline bool JSValue::isObject() const
+{
+ return isCell() && asCell()->isObject();
+}
+
+inline bool JSValue::getString(ExecState* exec, String& s) const
+{
+ return isCell() && asCell()->getString(exec, s);
+}
+
+inline String JSValue::getString(ExecState* exec) const
+{
+ return isCell() ? asCell()->getString(exec) : String();
+}
+
+template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
+{
+ return jsValue().getString(exec);
+}
+
+inline JSObject* JSValue::getObject() const
+{
+ return isCell() ? asCell()->getObject() : 0;
+}
+
+ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
+{
+ if (isInt32()) {
+ int32_t i = asInt32();
+ v = static_cast<uint32_t>(i);
+ return i >= 0;
+ }
+ if (isDouble()) {
+ double d = asDouble();
+ v = static_cast<uint32_t>(d);
+ return v == d;
+ }
+ return false;
+}
+
+inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+{
+ return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
+}
+
+inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
+{
+ if (isInt32()) {
+ number = asInt32();
+ value = *this;
+ return true;
+ }
+ if (isDouble()) {
+ number = asDouble();
+ value = *this;
+ return true;
+ }
+ if (isCell())
+ return asCell()->getPrimitiveNumber(exec, number, value);
+ if (isTrue()) {
+ number = 1.0;
+ value = *this;
+ return true;
+ }
+ if (isFalse() || isNull()) {
+ number = 0.0;
+ value = *this;
+ return true;
+ }
+ ASSERT(isUndefined());
+ number = QNaN;
+ value = *this;
+ return true;
+}
+
+ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
+{
+ if (isInt32())
+ return asInt32();
+ if (isDouble())
+ return asDouble();
+ return toNumberSlowCase(exec);
+}
+
+inline JSObject* JSValue::toObject(ExecState* exec) const
+{
+ return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
+}
+
+inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
+{
+ return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
+}
+
+inline bool JSValue::isFunction() const
+{
+ return isCell() && (asCell()->inherits(&JSFunction::s_info) || asCell()->inherits(&InternalFunction::s_info));
+}
+
+// this method is here to be after the inline declaration of JSCell::inherits
+inline bool JSValue::inherits(const ClassInfo* classInfo) const
+{
+ return isCell() && asCell()->inherits(classInfo);
+}
+
+inline JSObject* JSValue::toThisObject(ExecState* exec) const
+{
+ return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec);
+}
+
+inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const
+{
+ PropertySlot slot(asValue());
+ return get(exec, propertyName, slot);
+}
+
+inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(!isCell())) {
+ JSObject* prototype = synthesizePrototype(exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = asCell();
+ while (true) {
+ if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ JSValue prototype = asObject(cell)->prototype();
+ if (!prototype.isObject())
+ return jsUndefined();
+ cell = asObject(prototype);
+ }
+}
+
+inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
+{
+ PropertySlot slot(asValue());
+ return get(exec, propertyName, slot);
+}
+
+inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
+{
+ if (UNLIKELY(!isCell())) {
+ JSObject* prototype = synthesizePrototype(exec);
+ if (!prototype->getPropertySlot(exec, propertyName, slot))
+ return jsUndefined();
+ return slot.getValue(exec, propertyName);
+ }
+ JSCell* cell = const_cast<JSCell*>(asCell());
+ while (true) {
+ if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot))
+ return slot.getValue(exec, propertyName);
+ JSValue prototype = asObject(cell)->prototype();
+ if (!prototype.isObject())
+ return jsUndefined();
+ cell = prototype.asCell();
+ }
+}
+
+inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+ if (UNLIKELY(!isCell())) {
+ putToPrimitive(exec, propertyName, value, slot);
+ return;
+ }
+ asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
+}
+
+inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
+{
+ if (UNLIKELY(!isCell())) {
+ putToPrimitiveByIndex(exec, propertyName, value, shouldThrow);
+ return;
+ }
+ asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
+}
+
+inline JSValue JSValue::structureOrUndefined() const
+{
+ if (isCell())
+ return JSValue(asCell()->structure());
+ return jsUndefined();
+}
+
+// ECMA 11.9.3
+inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
+{
+ if (v1.isInt32() && v2.isInt32())
+ return v1 == v2;
+
+ return equalSlowCase(exec, v1, v2);
+}
+
+ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
+{
+ do {
+ if (v1.isNumber() && v2.isNumber())
+ return v1.asNumber() == v2.asNumber();
+
+ bool s1 = v1.isString();
+ bool s2 = v2.isString();
+ if (s1 && s2)
+ return asString(v1)->value(exec) == asString(v2)->value(exec);
+
+ if (v1.isUndefinedOrNull()) {
+ if (v2.isUndefinedOrNull())
+ return true;
+ if (!v2.isCell())
+ return false;
+ return v2.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
+ }
+
+ if (v2.isUndefinedOrNull()) {
+ if (!v1.isCell())
+ return false;
+ return v1.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
+ }
+
+ if (v1.isObject()) {
+ if (v2.isObject())
+ return v1 == v2;
+ JSValue p1 = v1.toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v1 = p1;
+ if (v1.isInt32() && v2.isInt32())
+ return v1 == v2;
+ continue;
+ }
+
+ if (v2.isObject()) {
+ JSValue p2 = v2.toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v2 = p2;
+ if (v1.isInt32() && v2.isInt32())
+ return v1 == v2;
+ continue;
+ }
+
+ if (s1 || s2) {
+ double d1 = v1.toNumber(exec);
+ double d2 = v2.toNumber(exec);
+ return d1 == d2;
+ }
+
+ if (v1.isBoolean()) {
+ if (v2.isNumber())
+ return static_cast<double>(v1.asBoolean()) == v2.asNumber();
+ } else if (v2.isBoolean()) {
+ if (v1.isNumber())
+ return v1.asNumber() == static_cast<double>(v2.asBoolean());
+ }
+
+ return v1 == v2;
+ } while (true);
+}
+
+// ECMA 11.9.3
+ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
+{
+ ASSERT(v1.isCell() && v2.isCell());
+
+ if (v1.asCell()->isString() && v2.asCell()->isString())
+ return asString(v1)->value(exec) == asString(v2)->value(exec);
+
+ return v1 == v2;
+}
+
+inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
+{
+ if (v1.isInt32() && v2.isInt32())
+ return v1 == v2;
+
+ if (v1.isNumber() && v2.isNumber())
+ return v1.asNumber() == v2.asNumber();
+
+ if (!v1.isCell() || !v2.isCell())
+ return v1 == v2;
+
+ return strictEqualSlowCaseInline(exec, v1, v2);
+}
+
+inline TriState JSValue::pureToBoolean() const
+{
+ if (isInt32())
+ return asInt32() ? TrueTriState : FalseTriState;
+ if (isDouble())
+ return isNotZeroAndOrdered(asDouble()) ? TrueTriState : FalseTriState; // false for NaN
+ if (isCell())
+ return asCell()->pureToBoolean();
+ return isTrue() ? TrueTriState : FalseTriState;
+}
+
+} // namespace JSC
+
+#endif // JSValueInlines_h
+
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index f6f4d716d..07b333193 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -27,6 +27,7 @@
#include "JSString.h"
#include "JSObject.h"
#include "NumberObject.h"
+#include "Operations.h"
#include <wtf/MathExtras.h>
namespace JSC {
@@ -65,13 +66,19 @@ const JSObject* JSCell::getObject() const
return isObject() ? static_cast<const JSObject*>(this) : 0;
}
-CallType JSCell::getCallData(JSCell*, CallData&)
+CallType JSCell::getCallData(JSCell*, CallData& callData)
{
+ callData.js.functionExecutable = 0;
+ callData.js.scope = 0;
+ callData.native.function = 0;
return CallTypeNone;
}
-ConstructType JSCell::getConstructData(JSCell*, ConstructData&)
+ConstructType JSCell::getConstructData(JSCell*, ConstructData& constructData)
{
+ constructData.js.functionExecutable = 0;
+ constructData.js.scope = 0;
+ constructData.native.function = 0;
return ConstructTypeNone;
}
@@ -173,23 +180,23 @@ void slowValidateCell(JSCell* cell)
JSValue JSCell::defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return jsUndefined();
}
void JSCell::getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
void JSCell::getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
String JSCell::className(const JSObject*)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return String();
}
@@ -200,29 +207,29 @@ const char* JSCell::className()
void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
bool JSCell::customHasInstance(JSObject*, ExecState*, JSValue)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
void JSCell::putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
bool JSCell::defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
bool JSCell::getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index b28fedd8d..76acb1e55 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -24,11 +24,9 @@
#define JSCell_h
#include "CallData.h"
-#include "CallFrame.h"
#include "ConstructData.h"
#include "Heap.h"
#include "JSLock.h"
-#include "JSValueInlines.h"
#include "SlotVisitor.h"
#include "TypedArrayDescriptor.h"
#include "WriteBarrier.h"
@@ -38,6 +36,7 @@
namespace JSC {
class CopyVisitor;
+class ExecState;
class JSDestructibleObject;
class JSGlobalObject;
class LLIntOffsetsExtractor;
@@ -66,7 +65,7 @@ public:
JSCell(CreatingEarlyCellTag);
protected:
- JSCell(JSGlobalData&, Structure*);
+ JSCell(VM&, Structure*);
JS_EXPORT_PRIVATE static void destroy(JSCell*);
public:
@@ -79,7 +78,7 @@ public:
bool isAPIValueWrapper() const;
Structure* structure() const;
- void setStructure(JSGlobalData&, Structure*);
+ void setStructure(VM&, Structure*);
void clearStructure() { m_structure.clear(); }
const char* className();
@@ -97,6 +96,7 @@ public:
JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
bool toBoolean(ExecState*) const;
+ TriState pureToBoolean() const;
JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
@@ -106,6 +106,7 @@ public:
// Object operations, with the toObject operation included.
const ClassInfo* classInfo() const;
const MethodTable* methodTable() const;
+ const MethodTable* methodTableForDestruction() const;
static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
@@ -141,8 +142,8 @@ public:
static const TypedArrayType TypedArrayStorageType = TypedArrayNone;
protected:
- void finishCreation(JSGlobalData&);
- void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag);
+ void finishCreation(VM&);
+ void finishCreation(VM&, Structure*, CreatingEarlyCellTag);
// Base implementation; for non-object classes implements getPropertySlot.
static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
@@ -150,12 +151,12 @@ protected:
// Dummy implementations of override-able static functions for classes to put in their MethodTable
static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
- static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static NO_RETURN_DUE_TO_ASSERT void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static String className(const JSObject*);
JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
- static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+ static NO_RETURN_DUE_TO_CRASH void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
@@ -165,174 +166,6 @@ private:
WriteBarrier<Structure> m_structure;
};
-inline JSCell::JSCell(CreatingEarlyCellTag)
-{
-}
-
-inline void JSCell::finishCreation(JSGlobalData& globalData)
-{
-#if ENABLE(GC_VALIDATION)
- ASSERT(globalData.isInitializingObject());
- globalData.setInitializingObjectClass(0);
-#else
- UNUSED_PARAM(globalData);
-#endif
- ASSERT(m_structure);
-}
-
-inline Structure* JSCell::structure() const
-{
- return m_structure.get();
-}
-
-inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- MARK_LOG_PARENT(visitor, cell);
-
- visitor.append(&cell->m_structure);
-}
-
-// --- JSValue inlines ----------------------------
-
-inline bool JSValue::isString() const
-{
- return isCell() && asCell()->isString();
-}
-
-inline bool JSValue::isPrimitive() const
-{
- return !isCell() || asCell()->isString();
-}
-
-inline bool JSValue::isGetterSetter() const
-{
- return isCell() && asCell()->isGetterSetter();
-}
-
-inline bool JSValue::isObject() const
-{
- return isCell() && asCell()->isObject();
-}
-
-inline bool JSValue::getString(ExecState* exec, String& s) const
-{
- return isCell() && asCell()->getString(exec, s);
-}
-
-inline String JSValue::getString(ExecState* exec) const
-{
- return isCell() ? asCell()->getString(exec) : String();
-}
-
-template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
-{
- return jsValue().getString(exec);
-}
-
-inline JSObject* JSValue::getObject() const
-{
- return isCell() ? asCell()->getObject() : 0;
-}
-
-ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
-{
- if (isInt32()) {
- int32_t i = asInt32();
- v = static_cast<uint32_t>(i);
- return i >= 0;
- }
- if (isDouble()) {
- double d = asDouble();
- v = static_cast<uint32_t>(d);
- return v == d;
- }
- return false;
-}
-
-inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
-{
- return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
-}
-
-inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
-{
- if (isInt32()) {
- number = asInt32();
- value = *this;
- return true;
- }
- if (isDouble()) {
- number = asDouble();
- value = *this;
- return true;
- }
- if (isCell())
- return asCell()->getPrimitiveNumber(exec, number, value);
- if (isTrue()) {
- number = 1.0;
- value = *this;
- return true;
- }
- if (isFalse() || isNull()) {
- number = 0.0;
- value = *this;
- return true;
- }
- ASSERT(isUndefined());
- number = QNaN;
- value = *this;
- return true;
-}
-
-ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
-{
- if (isInt32())
- return asInt32();
- if (isDouble())
- return asDouble();
- return toNumberSlowCase(exec);
-}
-
-inline JSObject* JSValue::toObject(ExecState* exec) const
-{
- return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
-}
-
-inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
-{
- return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
-}
-
-template<typename T>
-void* allocateCell(Heap& heap, size_t size)
-{
- ASSERT(size >= sizeof(T));
-#if ENABLE(GC_VALIDATION)
- ASSERT(!heap.globalData()->isInitializingObject());
- heap.globalData()->setInitializingObjectClass(&T::s_info);
-#endif
- JSCell* result = 0;
- if (T::needsDestruction && T::hasImmortalStructure)
- result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
- else if (T::needsDestruction && !T::hasImmortalStructure)
- result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
- else
- result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
- result->clearStructure();
- return result;
-}
-
-template<typename T>
-void* allocateCell(Heap& heap)
-{
- return allocateCell<T>(heap, sizeof(T));
-}
-
-inline bool isZapped(const JSCell* cell)
-{
- return cell->isZapped();
-}
-
template<typename To, typename From>
inline To jsCast(From* from)
{
diff --git a/Source/JavaScriptCore/runtime/JSCellInlines.h b/Source/JavaScriptCore/runtime/JSCellInlines.h
new file mode 100644
index 000000000..5312cae35
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSCellInlines.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCellInlines_h
+#define JSCellInlines_h
+
+#include "CallFrame.h"
+#include "Handle.h"
+#include "JSCell.h"
+#include "JSObject.h"
+#include "JSString.h"
+#include "Structure.h"
+
+namespace JSC {
+
+inline JSCell::JSCell(CreatingEarlyCellTag)
+{
+}
+
+inline JSCell::JSCell(VM& vm, Structure* structure)
+ : m_structure(vm, this, structure)
+{
+}
+
+inline void JSCell::finishCreation(VM& vm)
+{
+#if ENABLE(GC_VALIDATION)
+ ASSERT(vm.isInitializingObject());
+ vm.setInitializingObjectClass(0);
+#else
+ UNUSED_PARAM(vm);
+#endif
+ ASSERT(m_structure);
+}
+
+inline void JSCell::finishCreation(VM& vm, Structure* structure, CreatingEarlyCellTag)
+{
+#if ENABLE(GC_VALIDATION)
+ ASSERT(vm.isInitializingObject());
+ vm.setInitializingObjectClass(0);
+ if (structure)
+#endif
+ m_structure.setEarlyValue(vm, this, structure);
+ // Very first set of allocations won't have a real structure.
+ ASSERT(m_structure || !vm.structureStructure);
+}
+
+inline Structure* JSCell::structure() const
+{
+ return m_structure.get();
+}
+
+inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ MARK_LOG_PARENT(visitor, cell);
+
+ visitor.append(&cell->m_structure);
+}
+
+template<typename T>
+void* allocateCell(Heap& heap, size_t size)
+{
+ ASSERT(size >= sizeof(T));
+#if ENABLE(GC_VALIDATION)
+ ASSERT(!heap.vm()->isInitializingObject());
+ heap.vm()->setInitializingObjectClass(&T::s_info);
+#endif
+ JSCell* result = 0;
+ if (T::needsDestruction && T::hasImmortalStructure)
+ result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
+ else if (T::needsDestruction)
+ result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
+ else
+ result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
+ result->clearStructure();
+ return result;
+}
+
+template<typename T>
+void* allocateCell(Heap& heap)
+{
+ return allocateCell<T>(heap, sizeof(T));
+}
+
+inline bool isZapped(const JSCell* cell)
+{
+ return cell->isZapped();
+}
+
+inline bool JSCell::isObject() const
+{
+ return m_structure->isObject();
+}
+
+inline bool JSCell::isString() const
+{
+ return m_structure->typeInfo().type() == StringType;
+}
+
+inline bool JSCell::isGetterSetter() const
+{
+ return m_structure->typeInfo().type() == GetterSetterType;
+}
+
+inline bool JSCell::isProxy() const
+{
+ return structure()->typeInfo().type() == ProxyType;
+}
+
+inline bool JSCell::isAPIValueWrapper() const
+{
+ return m_structure->typeInfo().type() == APIValueWrapperType;
+}
+
+inline void JSCell::setStructure(VM& vm, Structure* structure)
+{
+ ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
+ ASSERT(structure->classInfo() == m_structure->classInfo());
+ ASSERT(!m_structure
+ || m_structure->transitionWatchpointSetHasBeenInvalidated()
+ || m_structure.get() == structure);
+ m_structure.set(vm, this, structure);
+}
+
+inline const MethodTable* JSCell::methodTableForDestruction() const
+{
+ return &classInfo()->methodTable;
+}
+
+inline const MethodTable* JSCell::methodTable() const
+{
+ if (Structure* rootStructure = m_structure->structure())
+ RELEASE_ASSERT(rootStructure == rootStructure->structure());
+
+ return &classInfo()->methodTable;
+}
+
+inline bool JSCell::inherits(const ClassInfo* info) const
+{
+ return classInfo()->isSubClassOf(info);
+}
+
+ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ if (!structure()->typeInfo().overridesGetOwnPropertySlot())
+ return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
+ return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot);
+}
+
+// Fast call to get a property where we may not yet have converted the string to an
+// identifier. The first time we perform a property access with a given string, try
+// performing the property map lookup without forming an identifier. We detect this
+// case by checking whether the hash has yet been set for this string.
+ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name)
+{
+ if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) {
+ PropertyOffset offset = name.impl()->hasHash()
+ ? structure()->get(exec->vm(), Identifier(exec, name))
+ : structure()->get(exec->vm(), name);
+ if (offset != invalidOffset)
+ return asObject(this)->locationForOffset(offset)->get();
+ }
+ return JSValue();
+}
+
+inline bool JSCell::toBoolean(ExecState* exec) const
+{
+ if (isString())
+ return static_cast<const JSString*>(this)->toBoolean();
+ return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
+}
+
+inline TriState JSCell::pureToBoolean() const
+{
+ if (isString())
+ return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
+ return MixedTriState;
+}
+
+} // namespace JSC
+
+#endif // JSCellInlines_h
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index cd3948fcf..b69573670 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
* Copyright (C) 2007-2009 Torch Mobile, Inc.
* Copyright (C) 2010 &yet, LLC. (nate@andyet.net)
@@ -74,6 +74,7 @@
#include "JSObject.h"
#include "JSScope.h"
+#include "Operations.h"
#include <algorithm>
#include <limits.h>
@@ -126,14 +127,14 @@ static inline int msToWeekDay(double ms)
return wd;
}
-// Get the DST offset for the time passed in.
+// Get the combined UTC + DST offset for the time passed in.
//
// NOTE: The implementation relies on the fact that no time zones have
// more than one daylight savings offset change per month.
// If this function is called with NaN it returns NaN.
-static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
+static LocalTimeOffset localTimeOffset(ExecState* exec, double ms)
{
- DSTOffsetCache& cache = exec->globalData().dstOffsetCache;
+ LocalTimeOffsetCache& cache = exec->vm().localTimeOffsetCache;
double start = cache.start;
double end = cache.end;
@@ -145,7 +146,7 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
double newEnd = end + cache.increment;
if (ms <= newEnd) {
- double endOffset = calculateDSTOffset(newEnd, utcOffset);
+ LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd);
if (cache.offset == endOffset) {
// If the offset at the end of the new interval still matches
// the offset in the cache, we grow the cached time interval
@@ -153,34 +154,33 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
cache.end = newEnd;
cache.increment = msPerMonth;
return endOffset;
+ }
+ LocalTimeOffset offset = calculateLocalTimeOffset(ms);
+ if (offset == endOffset) {
+ // The offset at the given time is equal to the offset at the
+ // new end of the interval, so that means that we've just skipped
+ // the point in time where the DST offset change occurred. Updated
+ // the interval to reflect this and reset the increment.
+ cache.start = ms;
+ cache.end = newEnd;
+ cache.increment = msPerMonth;
} else {
- double offset = calculateDSTOffset(ms, utcOffset);
- if (offset == endOffset) {
- // The offset at the given time is equal to the offset at the
- // new end of the interval, so that means that we've just skipped
- // the point in time where the DST offset change occurred. Updated
- // the interval to reflect this and reset the increment.
- cache.start = ms;
- cache.end = newEnd;
- cache.increment = msPerMonth;
- } else {
- // The interval contains a DST offset change and the given time is
- // before it. Adjust the increment to avoid a linear search for
- // the offset change point and change the end of the interval.
- cache.increment /= 3;
- cache.end = ms;
- }
- // Update the offset in the cache and return it.
- cache.offset = offset;
- return offset;
+ // The interval contains a DST offset change and the given time is
+ // before it. Adjust the increment to avoid a linear search for
+ // the offset change point and change the end of the interval.
+ cache.increment /= 3;
+ cache.end = ms;
}
+ // Update the offset in the cache and return it.
+ cache.offset = offset;
+ return offset;
}
}
// Compute the DST offset for the time and shrink the cache interval
// to only contain the time. This allows fast repeated DST offset
// computations for the same time.
- double offset = calculateDSTOffset(ms, utcOffset);
+ LocalTimeOffset offset = calculateLocalTimeOffset(ms);
cache.offset = offset;
cache.start = ms;
cache.end = ms;
@@ -188,30 +188,14 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset)
return offset;
}
-/*
- * Get the difference in milliseconds between this time zone and UTC (GMT)
- * NOT including DST.
- */
-double getUTCOffset(ExecState* exec)
-{
- double utcOffset = exec->globalData().cachedUTCOffset;
- if (!isnan(utcOffset))
- return utcOffset;
- exec->globalData().cachedUTCOffset = calculateUTCOffset();
- return exec->globalData().cachedUTCOffset;
-}
-
double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
{
double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay());
double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds);
double result = (day * WTF::msPerDay) + ms;
- if (!inputIsUTC) { // convert to UTC
- double utcOffset = getUTCOffset(exec);
- result -= utcOffset;
- result -= getDSTOffset(exec, result, utcOffset);
- }
+ if (!inputIsUTC)
+ result -= localTimeOffset(exec, result).offset;
return result;
}
@@ -219,12 +203,10 @@ double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double
// input is UTC
void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm)
{
- double dstOff = 0.0;
- double utcOff = 0.0;
+ LocalTimeOffset localTime;
if (!outputIsUTC) {
- utcOff = getUTCOffset(exec);
- dstOff = getDSTOffset(exec, ms, utcOff);
- ms += dstOff + utcOff;
+ localTime = localTimeOffset(exec, ms);
+ ms += localTime.offset;
}
const int year = msToYear(ms);
@@ -236,8 +218,8 @@ void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, Gregori
tm.setMonthDay(dayInMonthFromDayInYear(tm.yearDay(), isLeapYear(year)));
tm.setMonth(monthFromDayInYear(tm.yearDay(), isLeapYear(year)));
tm.setYear(year);
- tm.setIsDST(dstOff != 0.0);
- tm.setUtcOffset(static_cast<long>((dstOff + utcOff) / WTF::msPerSecond));
+ tm.setIsDST(localTime.isDST);
+ tm.setUtcOffset(localTime.offset / WTF::msPerSecond);
}
double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
@@ -246,27 +228,25 @@ double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateSt
bool haveTZ;
int offset;
double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
- if (isnan(ms))
+ if (std::isnan(ms))
return QNaN;
// fall back to local timezone
- if (!haveTZ) {
- double utcOffset = getUTCOffset(exec);
- double dstOffset = getDSTOffset(exec, ms, utcOffset);
- offset = static_cast<int>((utcOffset + dstOffset) / WTF::msPerMinute);
- }
+ if (!haveTZ)
+ offset = localTimeOffset(exec, ms).offset / WTF::msPerMinute;
+
return ms - (offset * WTF::msPerMinute);
}
double parseDate(ExecState* exec, const String& date)
{
- if (date == exec->globalData().cachedDateString)
- return exec->globalData().cachedDateStringValue;
+ if (date == exec->vm().cachedDateString)
+ return exec->vm().cachedDateStringValue;
double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data());
- if (isnan(value))
+ if (std::isnan(value))
value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data());
- exec->globalData().cachedDateString = date;
- exec->globalData().cachedDateStringValue = value;
+ exec->vm().cachedDateString = date;
+ exec->vm().cachedDateStringValue = value;
return value;
}
diff --git a/Source/JavaScriptCore/runtime/JSDestructibleObject.h b/Source/JavaScriptCore/runtime/JSDestructibleObject.h
index efbe2b4f6..27dc06da5 100644
--- a/Source/JavaScriptCore/runtime/JSDestructibleObject.h
+++ b/Source/JavaScriptCore/runtime/JSDestructibleObject.h
@@ -3,4 +3,43 @@
#include "JSObject.h"
+namespace JSC {
+
+struct ClassInfo;
+
+class JSDestructibleObject : public JSNonFinalObject {
+public:
+ typedef JSNonFinalObject Base;
+
+ static const bool needsDestruction = true;
+
+ const ClassInfo* classInfo() const { return m_classInfo; }
+
+ static ptrdiff_t classInfoOffset() { return OBJECT_OFFSETOF(JSDestructibleObject, m_classInfo); }
+
+protected:
+ JSDestructibleObject(VM& vm, Structure* structure, Butterfly* butterfly = 0)
+ : JSNonFinalObject(vm, structure, butterfly)
+ , m_classInfo(structure->classInfo())
+ {
+ ASSERT(m_classInfo);
+ }
+
+private:
+ const ClassInfo* m_classInfo;
+};
+
+inline const ClassInfo* JSCell::classInfo() const
+{
+ if (MarkedBlock::blockFor(this)->destructorType() == MarkedBlock::Normal)
+ return static_cast<const JSDestructibleObject*>(this)->classInfo();
+#if ENABLE(GC_VALIDATION)
+ return m_structure.unvalidatedGet()->classInfo();
+#else
+ return m_structure->classInfo();
+#endif
+}
+
+} // namespace JSC
+
#endif
diff --git a/Source/JavaScriptCore/runtime/JSExportMacros.h b/Source/JavaScriptCore/runtime/JSExportMacros.h
index 19e2c286f..77e4b0a33 100644
--- a/Source/JavaScriptCore/runtime/JSExportMacros.h
+++ b/Source/JavaScriptCore/runtime/JSExportMacros.h
@@ -48,7 +48,7 @@
#else // !USE(EXPORT_MACROS)
-#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
+#if OS(WINDOWS) && !COMPILER(GCC)
#if defined(BUILDING_JavaScriptCore) || defined(STATICALLY_LINKED_WITH_JavaScriptCore)
#define JS_EXPORTDATA __declspec(dllexport)
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 0a98e7c13..3b89f6d7a 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -35,7 +35,9 @@
#include "JSGlobalObject.h"
#include "JSNotAnObject.h"
#include "Interpreter.h"
+#include "ObjectConstructor.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include "Parser.h"
#include "PropertyNameArray.h"
@@ -61,12 +63,12 @@ JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, in
#if !ENABLE(JIT)
UNUSED_PARAM(intrinsic);
#else
- if (intrinsic != NoIntrinsic && exec->globalData().canUseJIT()) {
+ if (intrinsic != NoIntrinsic && exec->vm().canUseJIT()) {
ASSERT(nativeConstructor == callHostFunctionAsConstructor);
- executable = exec->globalData().getHostFunction(nativeFunction, intrinsic);
+ executable = exec->vm().getHostFunction(nativeFunction, intrinsic);
} else
#endif
- executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor);
+ executable = exec->vm().getHostFunction(nativeFunction, nativeConstructor);
JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure());
// Can't do this during initialization because getHostFunction might do a GC allocation.
@@ -80,49 +82,49 @@ void JSFunction::destroy(JSCell* cell)
}
JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
- : Base(exec->globalData(), structure)
+ : Base(exec->vm(), structure)
, m_executable()
- , m_scope(exec->globalData(), this, globalObject)
+ , m_scope(exec->vm(), this, globalObject)
// We initialize blind so that changes to the prototype after function creation but before
// the optimizer kicks in don't disable optimizations. Once the optimizer kicks in, the
// watchpoint will start watching and any changes will both force deoptimization and disable
// future attempts to optimize. This is necessary because we are guaranteed that the
- // inheritorID is changed exactly once prior to optimizations kicking in. We could be
+ // allocation profile is changed exactly once prior to optimizations kicking in. We could be
// smarter and count the number of times the prototype is clobbered and only optimize if it
// was clobbered exactly once, but that seems like overkill. In almost all cases it will be
// clobbered once, and if it's clobbered more than once, that will probably only occur
// before we started optimizing, anyway.
- , m_inheritorIDWatchpoint(InitializedBlind)
+ , m_allocationProfileWatchpoint(InitializedBlind)
{
}
void JSFunction::finishCreation(ExecState* exec, NativeExecutable* executable, int length, const String& name)
{
- Base::finishCreation(exec->globalData());
+ Base::finishCreation(exec->vm());
ASSERT(inherits(&s_info));
- m_executable.set(exec->globalData(), this, executable);
- putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name), DontDelete | ReadOnly | DontEnum);
- putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
+ m_executable.set(exec->vm(), this, executable);
+ putDirect(exec->vm(), exec->vm().propertyNames->name, jsString(exec, name), DontDelete | ReadOnly | DontEnum);
+ putDirect(exec->vm(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
}
-Structure* JSFunction::cacheInheritorID(ExecState* exec)
+ObjectAllocationProfile* JSFunction::createAllocationProfile(ExecState* exec, size_t inlineCapacity)
{
- JSValue prototype = get(exec, exec->globalData().propertyNames->prototype);
- if (prototype.isObject())
- m_cachedInheritorID.set(exec->globalData(), this, asObject(prototype)->inheritorID(exec->globalData()));
- else
- m_cachedInheritorID.set(exec->globalData(), this, globalObject()->emptyObjectStructure());
- return m_cachedInheritorID.get();
+ VM& vm = exec->vm();
+ JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
+ if (!prototype)
+ prototype = globalObject()->objectPrototype();
+ m_allocationProfile.initialize(globalObject()->vm(), this, prototype, inlineCapacity);
+ return &m_allocationProfile;
}
String JSFunction::name(ExecState* exec)
{
- return get(exec, exec->globalData().propertyNames->name).toWTFString(exec);
+ return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
}
String JSFunction::displayName(ExecState* exec)
{
- JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
+ JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);
if (displayName && isJSString(displayName))
return asString(displayName)->tryGetValue();
@@ -161,6 +163,7 @@ void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitor.append(&thisObject->m_scope);
visitor.append(&thisObject->m_executable);
+ thisObject->m_allocationProfile.visitAggregate(visitor);
}
CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
@@ -218,16 +221,17 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName
return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
if (propertyName == exec->propertyNames().prototype) {
- WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName);
-
- if (!location) {
- JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure());
- prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum);
- thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
- location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype);
+ VM& vm = exec->vm();
+ PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName);
+ if (!isValidOffset(offset)) {
+ JSObject* prototype = constructEmptyObject(exec);
+ prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
+ thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
+ offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype);
+ ASSERT(isValidOffset(offset));
}
- slot.setValue(thisObject, location->get(), thisObject->offsetForLocation(location));
+ slot.setValue(thisObject, thisObject->getDirect(offset), offset);
}
if (propertyName == exec->propertyNames().arguments) {
@@ -352,9 +356,9 @@ void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, J
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot;
thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
- thisObject->m_cachedInheritorID.clear();
- thisObject->m_inheritorIDWatchpoint.notifyWrite();
- // Don't allow this to be cached, since a [[Put]] must clear m_cachedInheritorID.
+ thisObject->m_allocationProfile.clear();
+ thisObject->m_allocationProfileWatchpoint.notifyWrite();
+ // Don't allow this to be cached, since a [[Put]] must clear m_allocationProfile.
PutPropertySlot dontCache;
Base::put(thisObject, exec, propertyName, value, dontCache);
return;
@@ -378,7 +382,7 @@ bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName prop
{
JSFunction* thisObject = jsCast<JSFunction*>(cell);
// For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
- if (!thisObject->isHostFunction() && !exec->globalData().isInDefineOwnProperty()
+ if (!thisObject->isHostFunction() && !exec->vm().isInDefineOwnProperty()
&& (propertyName == exec->propertyNames().arguments
|| propertyName == exec->propertyNames().length
|| propertyName == exec->propertyNames().name
@@ -399,8 +403,8 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot;
thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
- thisObject->m_cachedInheritorID.clear();
- thisObject->m_inheritorIDWatchpoint.notifyWrite();
+ thisObject->m_allocationProfile.clear();
+ thisObject->m_allocationProfileWatchpoint.notifyWrite();
return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
@@ -466,7 +470,6 @@ ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& construc
constructData.js.scope = thisObject->scope();
return ConstructTypeJS;
}
-
String getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
{
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index 322ee58e3..da50f9581 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -27,6 +27,7 @@
#include "InternalFunction.h"
#include "JSDestructibleObject.h"
#include "JSScope.h"
+#include "ObjectAllocationProfile.h"
#include "Watchpoint.h"
namespace JSC {
@@ -52,7 +53,7 @@ namespace JSC {
friend class JIT;
friend class DFG::SpeculativeJIT;
friend class DFG::JITCompiler;
- friend class JSGlobalData;
+ friend class VM;
public:
typedef JSDestructibleObject Base;
@@ -61,10 +62,10 @@ namespace JSC {
static JSFunction* create(ExecState* exec, FunctionExecutable* executable, JSScope* scope)
{
- JSGlobalData& globalData = exec->globalData();
- JSFunction* function = new (NotNull, allocateCell<JSFunction>(globalData.heap)) JSFunction(globalData, executable, scope);
+ VM& vm = exec->vm();
+ JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
ASSERT(function->structure()->globalObject());
- function->finishCreation(globalData);
+ function->finishCreation(vm);
return function;
}
@@ -88,10 +89,10 @@ namespace JSC {
{
return m_scope.get();
}
- void setScope(JSGlobalData& globalData, JSScope* scope)
+ void setScope(VM& vm, JSScope* scope)
{
ASSERT(!isHostFunctionNonInline());
- m_scope.set(globalData, this, scope);
+ m_scope.set(vm, this, scope);
}
ExecutableBase* executable() const { return m_executable.get(); }
@@ -104,10 +105,10 @@ namespace JSC {
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)
{
ASSERT(globalObject);
- return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info);
}
NativeFunction nativeFunction();
@@ -116,53 +117,53 @@ namespace JSC {
static ConstructType getConstructData(JSCell*, ConstructData&);
static CallType getCallData(JSCell*, CallData&);
- static inline size_t offsetOfScopeChain()
+ static inline ptrdiff_t offsetOfScopeChain()
{
return OBJECT_OFFSETOF(JSFunction, m_scope);
}
- static inline size_t offsetOfExecutable()
+ static inline ptrdiff_t offsetOfExecutable()
{
return OBJECT_OFFSETOF(JSFunction, m_executable);
}
- Structure* cachedInheritorID(ExecState* exec)
+ static inline ptrdiff_t offsetOfAllocationProfile()
{
- if (UNLIKELY(!m_cachedInheritorID))
- return cacheInheritorID(exec);
- return m_cachedInheritorID.get();
+ return OBJECT_OFFSETOF(JSFunction, m_allocationProfile);
}
- Structure* tryGetKnownInheritorID()
+ ObjectAllocationProfile* allocationProfile(ExecState* exec, unsigned inlineCapacity)
{
- if (!m_cachedInheritorID)
+ if (UNLIKELY(m_allocationProfile.isNull()))
+ return createAllocationProfile(exec, inlineCapacity);
+ return &m_allocationProfile;
+ }
+
+ ObjectAllocationProfile* tryGetAllocationProfile()
+ {
+ if (m_allocationProfile.isNull())
return 0;
- if (m_inheritorIDWatchpoint.hasBeenInvalidated())
+ if (m_allocationProfileWatchpoint.hasBeenInvalidated())
return 0;
- return m_cachedInheritorID.get();
+ return &m_allocationProfile;
}
- void addInheritorIDWatchpoint(Watchpoint* watchpoint)
- {
- ASSERT(tryGetKnownInheritorID());
- m_inheritorIDWatchpoint.add(watchpoint);
- }
-
- static size_t offsetOfCachedInheritorID()
+ void addAllocationProfileWatchpoint(Watchpoint* watchpoint)
{
- return OBJECT_OFFSETOF(JSFunction, m_cachedInheritorID);
+ ASSERT(tryGetAllocationProfile());
+ m_allocationProfileWatchpoint.add(watchpoint);
}
protected:
const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*);
- JSFunction(JSGlobalData&, FunctionExecutable*, JSScope*);
+ JSFunction(VM&, FunctionExecutable*, JSScope*);
void finishCreation(ExecState*, NativeExecutable*, int length, const String& name);
using Base::finishCreation;
- Structure* cacheInheritorID(ExecState*);
+ ObjectAllocationProfile* createAllocationProfile(ExecState*, size_t inlineCapacity);
static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
@@ -187,15 +188,10 @@ namespace JSC {
WriteBarrier<ExecutableBase> m_executable;
WriteBarrier<JSScope> m_scope;
- WriteBarrier<Structure> m_cachedInheritorID;
- InlineWatchpointSet m_inheritorIDWatchpoint;
+ ObjectAllocationProfile m_allocationProfile;
+ InlineWatchpointSet m_allocationProfileWatchpoint;
};
- inline bool JSValue::isFunction() const
- {
- return isCell() && (asCell()->inherits(&JSFunction::s_info) || asCell()->inherits(&InternalFunction::s_info));
- }
-
} // namespace JSC
#endif // JSFunction_h
diff --git a/Source/JavaScriptCore/runtime/JSFunctionInlines.h b/Source/JavaScriptCore/runtime/JSFunctionInlines.h
new file mode 100644
index 000000000..4f89acd7b
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSFunctionInlines.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSFunctionInlines_h
+#define JSFunctionInlines_h
+
+#include "Executable.h"
+#include "JSFunction.h"
+
+namespace JSC {
+
+inline JSFunction::JSFunction(VM& vm, FunctionExecutable* executable, JSScope* scope)
+ : Base(vm, scope->globalObject()->functionStructure())
+ , m_executable(vm, this, executable)
+ , m_scope(vm, this, scope)
+ , m_allocationProfileWatchpoint(InitializedBlind) // See comment in JSFunction.cpp concerning the reason for using InitializedBlind as opposed to InitializedWatching.
+{
+}
+
+inline FunctionExecutable* JSFunction::jsExecutable() const
+{
+ ASSERT(!isHostFunctionNonInline());
+ return static_cast<FunctionExecutable*>(m_executable.get());
+}
+
+inline bool JSFunction::isHostFunction() const
+{
+ ASSERT(m_executable);
+ return m_executable->isHostFunction();
+}
+
+inline NativeFunction JSFunction::nativeFunction()
+{
+ ASSERT(isHostFunction());
+ return static_cast<NativeExecutable*>(m_executable.get())->function();
+}
+
+inline NativeFunction JSFunction::nativeConstructor()
+{
+ ASSERT(isHostFunction());
+ return static_cast<NativeExecutable*>(m_executable.get())->constructor();
+}
+
+} // namespace JSC
+
+#endif // JSFunctionInlines_h
+
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 6f20f0e93..2fb5d34be 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -47,6 +47,7 @@
#include "FunctionPrototype.h"
#include "GetterSetter.h"
#include "Interpreter.h"
+#include "JSAPIWrapperObject.h"
#include "JSActivation.h"
#include "JSBoundFunction.h"
#include "JSCallbackConstructor.h"
@@ -58,6 +59,7 @@
#include "JSNameScope.h"
#include "JSONObject.h"
#include "JSWithScope.h"
+#include "LegacyProfiler.h"
#include "Lookup.h"
#include "MathObject.h"
#include "NameConstructor.h"
@@ -67,9 +69,11 @@
#include "NativeErrorPrototype.h"
#include "NumberConstructor.h"
#include "NumberPrototype.h"
+#include "ObjCCallbackFunction.h"
#include "ObjectConstructor.h"
#include "ObjectPrototype.h"
-#include "Profiler.h"
+#include "Operations.h"
+#include "ParserError.h"
#include "RegExpConstructor.h"
#include "RegExpMatchesArray.h"
#include "RegExpObject.h"
@@ -101,14 +105,8 @@ const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &all
@end
*/
-// Default number of ticks before a timeout check should be done.
-static const int initialTickCountThreshold = 255;
-
-// Preferred number of milliseconds between each timeout check
-static const int preferredScriptCheckTimeInterval = 1000;
-
-JSGlobalObject::JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
- : Base(globalData, structure, 0)
+JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
+ : Base(vm, structure, 0)
, m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(InitializedWatching)))
, m_havingABadTimeWatchpoint(adoptRef(new WatchpointSet(InitializedWatching)))
, m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
@@ -122,7 +120,7 @@ JSGlobalObject::~JSGlobalObject()
if (m_debugger)
m_debugger->detach(this);
- if (Profiler* profiler = globalData().enabledProfiler())
+ if (LegacyProfiler* profiler = vm().enabledProfiler())
profiler->stopProfiling(this);
}
@@ -131,16 +129,16 @@ void JSGlobalObject::destroy(JSCell* cell)
static_cast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
}
-void JSGlobalObject::setGlobalThis(JSGlobalData& globalData, JSObject* globalThis)
+void JSGlobalObject::setGlobalThis(VM& vm, JSObject* globalThis)
{
- m_globalThis.set(globalData, this, globalThis);
+ m_globalThis.set(vm, this, globalThis);
}
void JSGlobalObject::init(JSObject* thisValue)
{
- ASSERT(globalData().apiLock().currentThreadIsHoldingLock());
+ ASSERT(vm().apiLock().currentThreadIsHoldingLock());
- setGlobalThis(globalData(), thisValue);
+ setGlobalThis(vm(), thisValue);
JSGlobalObject::globalExec()->init(0, 0, this, CallFrame::noCaller(), 0, 0);
m_debugger = 0;
@@ -163,14 +161,14 @@ void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, Propert
JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
- if (symbolTablePutWithAttributes(thisObject, exec->globalData(), propertyName, value, attributes))
+ if (symbolTablePutWithAttributes(thisObject, exec->vm(), propertyName, value, attributes))
return;
- JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName);
+ JSValue valueBefore = thisObject->getDirect(exec->vm(), propertyName);
PutPropertySlot slot;
Base::put(thisObject, exec, propertyName, value, slot);
if (!valueBefore) {
- JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName);
+ JSValue valueAfter = thisObject->getDirect(exec->vm(), propertyName);
if (valueAfter)
JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes);
}
@@ -199,128 +197,131 @@ void JSGlobalObject::reset(JSValue prototype)
{
ExecState* exec = JSGlobalObject::globalExec();
- m_functionPrototype.set(exec->globalData(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->globalData(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
- m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
- m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
- m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
- m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
+ m_functionPrototype.set(exec->vm(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->vm(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
+ m_functionStructure.set(exec->vm(), this, JSFunction::createStructure(exec->vm(), this, m_functionPrototype.get()));
+ m_boundFunctionStructure.set(exec->vm(), this, JSBoundFunction::createStructure(exec->vm(), this, m_functionPrototype.get()));
+ m_namedFunctionStructure.set(exec->vm(), this, Structure::addPropertyTransition(exec->vm(), m_functionStructure.get(), exec->vm().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
+ m_internalFunctionStructure.set(exec->vm(), this, InternalFunction::createStructure(exec->vm(), this, m_functionPrototype.get()));
JSFunction* callFunction = 0;
JSFunction* applyFunction = 0;
m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
- m_callFunction.set(exec->globalData(), this, callFunction);
- m_applyFunction.set(exec->globalData(), this, applyFunction);
- m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull())));
+ m_callFunction.set(exec->vm(), this, callFunction);
+ m_applyFunction.set(exec->vm(), this, applyFunction);
+ m_objectPrototype.set(exec->vm(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->vm(), this, jsNull())));
GetterSetter* protoAccessor = GetterSetter::create(exec);
- protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, String(), globalFuncProtoGetter));
- protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, String(), globalFuncProtoSetter));
+ protoAccessor->setGetter(exec->vm(), JSFunction::create(exec, this, 0, String(), globalFuncProtoGetter));
+ protoAccessor->setSetter(exec->vm(), JSFunction::create(exec, this, 0, String(), globalFuncProtoSetter));
m_objectPrototype->putDirectAccessor(exec, exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum);
- m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
-
- m_nameScopeStructure.set(exec->globalData(), this, JSNameScope::createStructure(exec->globalData(), this, jsNull()));
- m_activationStructure.set(exec->globalData(), this, JSActivation::createStructure(exec->globalData(), this, jsNull()));
- m_strictEvalActivationStructure.set(exec->globalData(), this, StrictEvalActivation::createStructure(exec->globalData(), this, jsNull()));
- m_withScopeStructure.set(exec->globalData(), this, JSWithScope::createStructure(exec->globalData(), this, jsNull()));
-
- m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
- m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull()));
-
- m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
- m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), this, m_objectPrototype.get()));
- m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get()));
- m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
+ m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->vm(), m_objectPrototype.get());
+
+ m_nameScopeStructure.set(exec->vm(), this, JSNameScope::createStructure(exec->vm(), this, jsNull()));
+ m_activationStructure.set(exec->vm(), this, JSActivation::createStructure(exec->vm(), this, jsNull()));
+ m_strictEvalActivationStructure.set(exec->vm(), this, StrictEvalActivation::createStructure(exec->vm(), this, jsNull()));
+ m_withScopeStructure.set(exec->vm(), this, JSWithScope::createStructure(exec->vm(), this, jsNull()));
+
+ m_nullPrototypeObjectStructure.set(exec->vm(), this, JSFinalObject::createStructure(vm(), this, jsNull(), JSFinalObject::defaultInlineCapacity()));
+
+ m_callbackFunctionStructure.set(exec->vm(), this, JSCallbackFunction::createStructure(exec->vm(), this, m_functionPrototype.get()));
+ m_argumentsStructure.set(exec->vm(), this, Arguments::createStructure(exec->vm(), this, m_objectPrototype.get()));
+ m_callbackConstructorStructure.set(exec->vm(), this, JSCallbackConstructor::createStructure(exec->vm(), this, m_objectPrototype.get()));
+ m_callbackObjectStructure.set(exec->vm(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->vm(), this, m_objectPrototype.get()));
+#if JSC_OBJC_API_ENABLED
+ m_objcCallbackFunctionStructure.set(exec->vm(), this, ObjCCallbackFunction::createStructure(exec->vm(), this, m_functionPrototype.get()));
+ m_objcWrapperObjectStructure.set(exec->vm(), this, JSCallbackObject<JSAPIWrapperObject>::createStructure(exec->vm(), this, m_objectPrototype.get()));
+#endif
- m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
+ m_arrayPrototype.set(exec->vm(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->vm(), 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));
+ m_originalArrayStructureForIndexingShape[UndecidedShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithUndecided));
+ m_originalArrayStructureForIndexingShape[Int32Shape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithInt32));
+ m_originalArrayStructureForIndexingShape[DoubleShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithDouble));
+ m_originalArrayStructureForIndexingShape[ContiguousShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithContiguous));
+ m_originalArrayStructureForIndexingShape[ArrayStorageShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithArrayStorage));
+ m_originalArrayStructureForIndexingShape[SlowPutArrayStorageShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage));
for (unsigned i = 0; i < NumberOfIndexingShapes; ++i)
m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i];
- m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get()));
+ m_regExpMatchesArrayStructure.set(exec->vm(), this, RegExpMatchesArray::createStructure(exec->vm(), this, m_arrayPrototype.get()));
- m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
- m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), this, m_stringPrototype.get()));
+ m_stringPrototype.set(exec->vm(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->vm(), this, m_objectPrototype.get())));
+ m_stringObjectStructure.set(exec->vm(), this, StringObject::createStructure(exec->vm(), this, m_stringPrototype.get()));
- m_booleanPrototype.set(exec->globalData(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
- m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), this, m_booleanPrototype.get()));
+ m_booleanPrototype.set(exec->vm(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->vm(), this, m_objectPrototype.get())));
+ m_booleanObjectStructure.set(exec->vm(), this, BooleanObject::createStructure(exec->vm(), this, m_booleanPrototype.get()));
- m_numberPrototype.set(exec->globalData(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
- m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), this, m_numberPrototype.get()));
+ m_numberPrototype.set(exec->vm(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->vm(), this, m_objectPrototype.get())));
+ m_numberObjectStructure.set(exec->vm(), this, NumberObject::createStructure(exec->vm(), this, m_numberPrototype.get()));
- m_datePrototype.set(exec->globalData(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
- m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), this, m_datePrototype.get()));
+ m_datePrototype.set(exec->vm(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->vm(), this, m_objectPrototype.get())));
+ m_dateStructure.set(exec->vm(), this, DateInstance::createStructure(exec->vm(), this, m_datePrototype.get()));
- RegExp* emptyRegex = RegExp::create(exec->globalData(), "", NoFlags);
+ RegExp* emptyRegex = RegExp::create(exec->vm(), "", NoFlags);
- m_regExpPrototype.set(exec->globalData(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()), emptyRegex));
- m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), this, m_regExpPrototype.get()));
+ m_regExpPrototype.set(exec->vm(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()), emptyRegex));
+ m_regExpStructure.set(exec->vm(), this, RegExpObject::createStructure(exec->vm(), this, m_regExpPrototype.get()));
- m_errorPrototype.set(exec->globalData(), this, ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
- m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), this, m_errorPrototype.get()));
+ m_errorPrototype.set(exec->vm(), this, ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->vm(), this, m_objectPrototype.get())));
+ m_errorStructure.set(exec->vm(), this, ErrorInstance::createStructure(exec->vm(), this, m_errorPrototype.get()));
// Constructors
- JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_objectPrototype.get());
- JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_functionPrototype.get());
- JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_arrayPrototype.get());
- JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_stringPrototype.get());
- JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_booleanPrototype.get());
- JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_numberPrototype.get());
- JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_datePrototype.get());
-
- m_regExpConstructor.set(exec->globalData(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_regExpPrototype.get()));
-
- m_errorConstructor.set(exec->globalData(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_errorPrototype.get()));
-
- Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), this, m_errorPrototype.get());
- Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get());
- m_evalErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("EvalError")));
- m_rangeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("RangeError")));
- m_referenceErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("ReferenceError")));
- m_syntaxErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("SyntaxError")));
- m_typeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("TypeError")));
- m_URIErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("URIError")));
-
- m_objectPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
- m_functionPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
- m_arrayPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
- m_booleanPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
- m_stringPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
- m_numberPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
- m_datePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
- m_regExpPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
- m_errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
-
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().Object, objectConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().Array, arrayConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
-
- m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval.string(), globalFuncEval));
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum);
-
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum);
+ JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_objectPrototype.get());
+ JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_functionPrototype.get());
+ JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_arrayPrototype.get());
+ JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_stringPrototype.get());
+ JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_booleanPrototype.get());
+ JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_numberPrototype.get());
+ JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_datePrototype.get());
+
+ m_regExpConstructor.set(exec->vm(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_regExpPrototype.get()));
+
+ m_errorConstructor.set(exec->vm(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_errorPrototype.get()));
+
+ Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->vm(), this, m_errorPrototype.get());
+ Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->vm(), this, m_functionPrototype.get());
+ m_evalErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("EvalError")));
+ m_rangeErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("RangeError")));
+ m_referenceErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("ReferenceError")));
+ m_syntaxErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("SyntaxError")));
+ m_typeErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("TypeError")));
+ m_URIErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("URIError")));
+
+ m_objectPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, objectConstructor, DontEnum);
+ m_functionPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, functionConstructor, DontEnum);
+ m_arrayPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
+ m_booleanPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
+ m_stringPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, stringConstructor, DontEnum);
+ m_numberPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, numberConstructor, DontEnum);
+ m_datePrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, dateConstructor, DontEnum);
+ m_regExpPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
+ m_errorPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
+
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Object, objectConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Function, functionConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Array, arrayConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Boolean, booleanConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().String, stringConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Number, numberConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Date, dateConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().RegExp, m_regExpConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Error, m_errorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().EvalError, m_evalErrorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().RangeError, m_rangeErrorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().ReferenceError, m_referenceErrorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().SyntaxError, m_syntaxErrorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().TypeError, m_typeErrorConstructor.get(), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().URIError, m_URIErrorConstructor.get(), DontEnum);
+
+ m_evalFunction.set(exec->vm(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval.string(), globalFuncEval));
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum);
+
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().JSON, JSONObject::create(exec, this, JSONObject::createStructure(exec->vm(), this, m_objectPrototype.get())), DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().Math, MathObject::create(exec, this, MathObject::createStructure(exec->vm(), this, m_objectPrototype.get())), DontEnum);
GlobalPropertyInfo staticGlobals[] = {
- GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
- GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly)
+ GlobalPropertyInfo(exec->propertyNames().NaN, jsNaN(), DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(exec->propertyNames().Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(exec->propertyNames().undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly)
};
addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
@@ -330,15 +331,15 @@ void JSGlobalObject::reset(JSValue prototype)
m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
if (m_experimentsEnabled) {
- NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()));
- m_privateNameStructure.set(exec->globalData(), this, NameInstance::createStructure(exec->globalData(), this, privateNamePrototype));
+ NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->vm(), this, m_objectPrototype.get()));
+ m_privateNameStructure.set(exec->vm(), this, NameInstance::createStructure(exec->vm(), this, privateNamePrototype));
- JSCell* privateNameConstructor = NameConstructor::create(exec, this, NameConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), privateNamePrototype);
- privateNamePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, privateNameConstructor, DontEnum);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Name"), privateNameConstructor, DontEnum);
+ JSCell* privateNameConstructor = NameConstructor::create(exec, this, NameConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), privateNamePrototype);
+ privateNamePrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, privateNameConstructor, DontEnum);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "Name"), privateNameConstructor, DontEnum);
}
- resetPrototype(exec->globalData(), prototype);
+ resetPrototype(exec->vm(), prototype);
}
// Private namespace for helpers for JSGlobalObject::haveABadTime()
@@ -404,9 +405,9 @@ void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell)
} // end private namespace for helpers for JSGlobalObject::haveABadTime()
-void JSGlobalObject::haveABadTime(JSGlobalData& globalData)
+void JSGlobalObject::haveABadTime(VM& vm)
{
- ASSERT(&globalData == &this->globalData());
+ ASSERT(&vm == &this->vm());
if (isHavingABadTime())
return;
@@ -420,18 +421,18 @@ 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_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage));
// Make sure that all objects that have indexed storage switch to the slow kind of
// indexed storage.
MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC.
ObjectsWithBrokenIndexingFinder finder(foundObjects, this);
- globalData.heap.objectSpace().forEachLiveCell(finder);
+ vm.heap.objectSpace().forEachLiveCell(finder);
while (!foundObjects.isEmpty()) {
JSObject* object = asObject(foundObjects.last());
foundObjects.removeLast();
ASSERT(hasBrokenIndexing(object));
- object->switchToSlowPutArrayStorage(globalData);
+ object->switchToSlowPutArrayStorage(vm);
}
}
@@ -447,20 +448,20 @@ void JSGlobalObject::createThrowTypeError(ExecState* exec)
{
JSFunction* thrower = JSFunction::create(exec, this, 0, String(), globalFuncThrowTypeError);
GetterSetter* getterSetter = GetterSetter::create(exec);
- getterSetter->setGetter(exec->globalData(), thrower);
- getterSetter->setSetter(exec->globalData(), thrower);
- m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter);
+ getterSetter->setGetter(exec->vm(), thrower);
+ getterSetter->setSetter(exec->vm(), thrower);
+ m_throwTypeErrorGetterSetter.set(exec->vm(), this, getterSetter);
}
// Set prototype, and also insert the object prototype at the end of the chain.
-void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
+void JSGlobalObject::resetPrototype(VM& vm, JSValue prototype)
{
- setPrototype(globalData, prototype);
+ setPrototype(vm, prototype);
JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this);
JSObject* objectPrototype = m_objectPrototype.get();
if (oldLastInPrototypeChain != objectPrototype)
- oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
+ oldLastInPrototypeChain->setPrototype(vm, objectPrototype);
}
void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -510,8 +511,11 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitor.append(&thisObject->m_callbackConstructorStructure);
visitor.append(&thisObject->m_callbackFunctionStructure);
visitor.append(&thisObject->m_callbackObjectStructure);
+#if JSC_OBJC_API_ENABLED
+ visitor.append(&thisObject->m_objcCallbackFunctionStructure);
+ visitor.append(&thisObject->m_objcWrapperObjectStructure);
+#endif
visitor.append(&thisObject->m_dateStructure);
- visitor.append(&thisObject->m_emptyObjectStructure);
visitor.append(&thisObject->m_nullPrototypeObjectStructure);
visitor.append(&thisObject->m_errorStructure);
visitor.append(&thisObject->m_functionStructure);
@@ -546,7 +550,7 @@ void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
int index = symbolTable()->size();
SymbolTableEntry newEntry(index, global.attributes);
symbolTable()->add(global.identifier.impl(), newEntry);
- registerAt(index).set(globalData(), this, global.value);
+ registerAt(index).set(vm(), this, global.value);
}
}
@@ -571,28 +575,29 @@ void JSGlobalObject::clearRareData(JSCell* cell)
jsCast<JSGlobalObject*>(cell)->m_rareData.clear();
}
-DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
- : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject)
+DynamicGlobalObjectScope::DynamicGlobalObjectScope(VM& vm, JSGlobalObject* dynamicGlobalObject)
+ : m_dynamicGlobalObjectSlot(vm.dynamicGlobalObject)
, m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
{
if (!m_dynamicGlobalObjectSlot) {
#if ENABLE(ASSEMBLER)
if (ExecutableAllocator::underMemoryPressure())
- globalData.heap.deleteAllCompiledCode();
+ vm.heap.deleteAllCompiledCode();
#endif
m_dynamicGlobalObjectSlot = dynamicGlobalObject;
// Reset the date cache between JS invocations to force the VM
// to observe time zone changes.
- globalData.resetDateCache();
+ vm.resetDateCache();
}
+ // Clear the exception stack between entries
+ vm.clearExceptionStack();
}
void slowValidateCell(JSGlobalObject* globalObject)
{
- if (!globalObject->isGlobalObject())
- CRASH();
+ RELEASE_ASSERT(globalObject->isGlobalObject());
ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
}
@@ -602,7 +607,7 @@ UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* call
JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
- UnlinkedProgramCodeBlock* unlinkedCode = globalData().codeCache()->getProgramCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+ UnlinkedProgramCodeBlock* unlinkedCode = vm().codeCache()->getProgramCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
if (hasDebugger())
debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
@@ -615,13 +620,13 @@ UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* call
return unlinkedCode;
}
-UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, EvalExecutable* executable, JSObject** exception)
+UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CodeCache* cache, CallFrame* callFrame, JSScope* scope, EvalExecutable* executable, JSObject** exception)
{
ParserError error;
JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
- UnlinkedEvalCodeBlock* unlinkedCode = globalData().codeCache()->getEvalCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+ UnlinkedEvalCodeBlock* unlinkedCode = cache->getEvalCodeBlock(vm(), scope, executable, executable->source(), strictness, debuggerMode, profilerMode, error);
if (hasDebugger())
debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
@@ -634,20 +639,4 @@ UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame,
return unlinkedCode;
}
-UnlinkedFunctionExecutable* JSGlobalObject::createFunctionExecutableFromGlobalCode(CallFrame* callFrame, const Identifier& name, const SourceCode& code, JSObject** exception)
-{
- ParserError error;
- UnlinkedFunctionExecutable* executable = globalData().codeCache()->getFunctionExecutableFromGlobalCode(globalData(), name, code, error);
- if (hasDebugger())
- debugger()->sourceParsed(callFrame, code.provider(), error.m_line, error.m_message);
-
- if (error.m_type != ParserError::ErrorNone) {
- *exception = error.toErrorObject(this, code);
- return 0;
- }
-
- return executable;
-}
-
-
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index e6edd0be7..a2c99fccb 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -24,564 +24,524 @@
#include "ArrayAllocationProfile.h"
#include "JSArray.h"
-#include "JSGlobalData.h"
+#include "JSClassRef.h"
+#include "VM.h"
#include "JSSegmentedVariableObject.h"
#include "JSWeakObjectMapRefInternal.h"
#include "NumberPrototype.h"
#include "SpecialPointer.h"
#include "StringPrototype.h"
#include "StructureChain.h"
+#include "StructureRareDataInlines.h"
#include "Watchpoint.h"
+#include <JavaScriptCore/JSBase.h>
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/RandomNumber.h>
+struct OpaqueJSClass;
+struct OpaqueJSClassContextData;
+
namespace JSC {
- class ArrayPrototype;
- class BooleanPrototype;
- class DatePrototype;
- class Debugger;
- class ErrorConstructor;
- class ErrorPrototype;
- class EvalCodeBlock;
- class EvalExecutable;
- class FunctionCodeBlock;
- class FunctionExecutable;
- class FunctionPrototype;
- class GetterSetter;
- class GlobalCodeBlock;
- class JSStack;
- class LLIntOffsetsExtractor;
- class NativeErrorConstructor;
- class ProgramCodeBlock;
- class ProgramExecutable;
- class RegExpConstructor;
- class RegExpPrototype;
- class SourceCode;
- struct ActivationStackNode;
- struct HashTable;
-
- typedef Vector<ExecState*, 16> ExecStateStack;
+class ArrayPrototype;
+class BooleanPrototype;
+class DatePrototype;
+class Debugger;
+class ErrorConstructor;
+class ErrorPrototype;
+class EvalCodeBlock;
+class EvalExecutable;
+class FunctionCodeBlock;
+class FunctionExecutable;
+class FunctionPrototype;
+class GetterSetter;
+class GlobalCodeBlock;
+class JSStack;
+class LLIntOffsetsExtractor;
+class NativeErrorConstructor;
+class ProgramCodeBlock;
+class ProgramExecutable;
+class RegExpConstructor;
+class RegExpPrototype;
+class SourceCode;
+struct ActivationStackNode;
+struct HashTable;
+
+typedef Vector<ExecState*, 16> ExecStateStack;
- struct GlobalObjectMethodTable {
- typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);
- AllowsAccessFromFunctionPtr allowsAccessFrom;
-
- typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*);
- SupportsProfilingFunctionPtr supportsProfiling;
-
- typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);
- SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo;
-
- typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*);
- ShouldInterruptScriptFunctionPtr shouldInterruptScript;
-
- typedef bool (*JavaScriptExperimentsEnabledFunctionPtr)(const JSGlobalObject*);
- JavaScriptExperimentsEnabledFunctionPtr javaScriptExperimentsEnabled;
- };
-
- class JSGlobalObject : public JSSegmentedVariableObject {
- private:
- typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
-
- struct JSGlobalObjectRareData {
- JSGlobalObjectRareData()
- : profileGroup(0)
- {
- }
-
- WeakMapSet weakMaps;
- unsigned profileGroup;
- };
-
- protected:
-
- Register m_globalCallFrame[JSStack::CallFrameHeaderSize];
-
- WriteBarrier<JSObject> m_globalThis;
-
- WriteBarrier<RegExpConstructor> m_regExpConstructor;
- WriteBarrier<ErrorConstructor> m_errorConstructor;
- WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
- WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
- WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
- WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
- WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
- WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
-
- WriteBarrier<JSFunction> m_evalFunction;
- WriteBarrier<JSFunction> m_callFunction;
- WriteBarrier<JSFunction> m_applyFunction;
- WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
-
- WriteBarrier<ObjectPrototype> m_objectPrototype;
- WriteBarrier<FunctionPrototype> m_functionPrototype;
- WriteBarrier<ArrayPrototype> m_arrayPrototype;
- WriteBarrier<BooleanPrototype> m_booleanPrototype;
- WriteBarrier<StringPrototype> m_stringPrototype;
- WriteBarrier<NumberPrototype> m_numberPrototype;
- WriteBarrier<DatePrototype> m_datePrototype;
- WriteBarrier<RegExpPrototype> m_regExpPrototype;
- WriteBarrier<ErrorPrototype> m_errorPrototype;
-
- WriteBarrier<Structure> m_withScopeStructure;
- WriteBarrier<Structure> m_strictEvalActivationStructure;
- 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_booleanObjectStructure;
- WriteBarrier<Structure> m_callbackConstructorStructure;
- WriteBarrier<Structure> m_callbackFunctionStructure;
- WriteBarrier<Structure> m_callbackObjectStructure;
- WriteBarrier<Structure> m_dateStructure;
- WriteBarrier<Structure> m_emptyObjectStructure;
- WriteBarrier<Structure> m_nullPrototypeObjectStructure;
- WriteBarrier<Structure> m_errorStructure;
- WriteBarrier<Structure> m_functionStructure;
- WriteBarrier<Structure> m_boundFunctionStructure;
- WriteBarrier<Structure> m_namedFunctionStructure;
- PropertyOffset m_functionNameOffset;
- WriteBarrier<Structure> m_numberObjectStructure;
- WriteBarrier<Structure> m_privateNameStructure;
- WriteBarrier<Structure> m_regExpMatchesArrayStructure;
- WriteBarrier<Structure> m_regExpStructure;
- WriteBarrier<Structure> m_stringObjectStructure;
- WriteBarrier<Structure> m_internalFunctionStructure;
-
- void* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
-
- Debugger* m_debugger;
-
- RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint;
- RefPtr<WatchpointSet> m_havingABadTimeWatchpoint;
-
- OwnPtr<JSGlobalObjectRareData> m_rareData;
-
- WeakRandom m_weakRandom;
-
- bool m_evalEnabled;
- String m_evalDisabledErrorMessage;
- bool m_experimentsEnabled;
-
- static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable;
- const GlobalObjectMethodTable* m_globalObjectMethodTable;
-
- void createRareDataIfNeeded()
- {
- if (m_rareData)
- return;
- m_rareData = adoptPtr(new JSGlobalObjectRareData);
- }
-
- public:
- typedef JSSegmentedVariableObject Base;
-
- static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure)
- {
- JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(globalData.heap)) JSGlobalObject(globalData, structure);
- globalObject->finishCreation(globalData);
- globalData.heap.addFinalizer(globalObject, destroy);
- return globalObject;
- }
-
- static JS_EXPORTDATA const ClassInfo s_info;
-
- bool hasDebugger() const { return m_debugger; }
- bool hasProfiler() const { return globalObjectMethodTable()->supportsProfiling(this); }
-
- protected:
- JS_EXPORT_PRIVATE explicit JSGlobalObject(JSGlobalData&, Structure*, const GlobalObjectMethodTable* = 0);
-
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- structure()->setGlobalObject(globalData, this);
- m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this);
- init(this);
- }
-
- void finishCreation(JSGlobalData& globalData, JSObject* thisValue)
- {
- Base::finishCreation(globalData);
- structure()->setGlobalObject(globalData, this);
- m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this);
- init(thisValue);
- }
-
- public:
- JS_EXPORT_PRIVATE ~JSGlobalObject();
- JS_EXPORT_PRIVATE static void destroy(JSCell*);
- // We don't need a destructor because we use a finalizer instead.
- static const bool needsDestruction = false;
-
- JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+struct GlobalObjectMethodTable {
+ typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);
+ AllowsAccessFromFunctionPtr allowsAccessFrom;
- JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
- bool hasOwnPropertyForWrite(ExecState*, PropertyName);
- JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
+ typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*);
+ SupportsProfilingFunctionPtr supportsProfiling;
- JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+ typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);
+ SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo;
- JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, PropertyName, JSObject* getterFunc, unsigned attributes);
- JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, PropertyName, JSObject* setterFunc, unsigned attributes);
- JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
+ typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*);
+ ShouldInterruptScriptFunctionPtr shouldInterruptScript;
- // We use this in the code generator as we perform symbol table
- // lookups prior to initializing the properties
- bool symbolTableHasProperty(PropertyName);
+ typedef bool (*JavaScriptExperimentsEnabledFunctionPtr)(const JSGlobalObject*);
+ JavaScriptExperimentsEnabledFunctionPtr javaScriptExperimentsEnabled;
+};
- // The following accessors return pristine values, even if a script
- // replaces the global object's associated property.
+class JSGlobalObject : public JSSegmentedVariableObject {
+private:
+ typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
+ typedef HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > OpaqueJSClassDataMap;
- RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
-
- ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
- NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
- NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
- NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
- NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
- NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
- NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
-
- JSFunction* evalFunction() const { return m_evalFunction.get(); }
- JSFunction* callFunction() const { return m_callFunction.get(); }
- JSFunction* applyFunction() const { return m_applyFunction.get(); }
- GetterSetter* throwTypeErrorGetterSetter(ExecState* exec)
+ struct JSGlobalObjectRareData {
+ JSGlobalObjectRareData()
+ : profileGroup(0)
{
- if (!m_throwTypeErrorGetterSetter)
- createThrowTypeError(exec);
- return m_throwTypeErrorGetterSetter.get();
}
- ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
- FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
- ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
- BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
- StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
- NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
- DatePrototype* datePrototype() const { return m_datePrototype.get(); }
- RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
- ErrorPrototype* errorPrototype() const { return m_errorPrototype.get(); }
-
- Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
- Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
- 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));
- }
-
- bool isOriginalArrayStructure(Structure* structure)
- {
- return originalArrayStructureForIndexingType(structure->indexingType() | IsArray) == structure;
- }
+ WeakMapSet weakMaps;
+ unsigned profileGroup;
- Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
- Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
- Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
- Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
- Structure* dateStructure() const { return m_dateStructure.get(); }
- Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); }
- Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
- Structure* errorStructure() const { return m_errorStructure.get(); }
- Structure* functionStructure() const { return m_functionStructure.get(); }
- Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
- Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
- PropertyOffset functionNameOffset() const { return m_functionNameOffset; }
- Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
- Structure* privateNameStructure() const { return m_privateNameStructure.get(); }
- Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
- Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
- Structure* regExpStructure() const { return m_regExpStructure.get(); }
- Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
-
- void* actualPointerFor(Special::Pointer pointer)
- {
- ASSERT(pointer < Special::TableSize);
- return m_specialPointers[pointer];
- }
+ OpaqueJSClassDataMap opaqueJSClassData;
+ };
- WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); }
- WatchpointSet* havingABadTimeWatchpoint() { return m_havingABadTimeWatchpoint.get(); }
+protected:
+
+ Register m_globalCallFrame[JSStack::CallFrameHeaderSize];
+
+ WriteBarrier<JSObject> m_globalThis;
+
+ WriteBarrier<RegExpConstructor> m_regExpConstructor;
+ WriteBarrier<ErrorConstructor> m_errorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
+ WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
+
+ WriteBarrier<JSFunction> m_evalFunction;
+ WriteBarrier<JSFunction> m_callFunction;
+ WriteBarrier<JSFunction> m_applyFunction;
+ WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
+
+ WriteBarrier<ObjectPrototype> m_objectPrototype;
+ WriteBarrier<FunctionPrototype> m_functionPrototype;
+ WriteBarrier<ArrayPrototype> m_arrayPrototype;
+ WriteBarrier<BooleanPrototype> m_booleanPrototype;
+ WriteBarrier<StringPrototype> m_stringPrototype;
+ WriteBarrier<NumberPrototype> m_numberPrototype;
+ WriteBarrier<DatePrototype> m_datePrototype;
+ WriteBarrier<RegExpPrototype> m_regExpPrototype;
+ WriteBarrier<ErrorPrototype> m_errorPrototype;
+
+ WriteBarrier<Structure> m_withScopeStructure;
+ WriteBarrier<Structure> m_strictEvalActivationStructure;
+ WriteBarrier<Structure> m_activationStructure;
+ WriteBarrier<Structure> m_nameScopeStructure;
+ WriteBarrier<Structure> m_argumentsStructure;
- bool isHavingABadTime() const
- {
- return m_havingABadTimeWatchpoint->hasBeenInvalidated();
- }
+ // 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];
- void haveABadTime(JSGlobalData&);
+ WriteBarrier<Structure> m_booleanObjectStructure;
+ WriteBarrier<Structure> m_callbackConstructorStructure;
+ WriteBarrier<Structure> m_callbackFunctionStructure;
+ WriteBarrier<Structure> m_callbackObjectStructure;
+#if JSC_OBJC_API_ENABLED
+ WriteBarrier<Structure> m_objcCallbackFunctionStructure;
+ WriteBarrier<Structure> m_objcWrapperObjectStructure;
+#endif
+ WriteBarrier<Structure> m_dateStructure;
+ WriteBarrier<Structure> m_nullPrototypeObjectStructure;
+ WriteBarrier<Structure> m_errorStructure;
+ WriteBarrier<Structure> m_functionStructure;
+ WriteBarrier<Structure> m_boundFunctionStructure;
+ WriteBarrier<Structure> m_namedFunctionStructure;
+ PropertyOffset m_functionNameOffset;
+ WriteBarrier<Structure> m_numberObjectStructure;
+ WriteBarrier<Structure> m_privateNameStructure;
+ WriteBarrier<Structure> m_regExpMatchesArrayStructure;
+ WriteBarrier<Structure> m_regExpStructure;
+ WriteBarrier<Structure> m_stringObjectStructure;
+ WriteBarrier<Structure> m_internalFunctionStructure;
- bool arrayPrototypeChainIsSane();
-
- void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
- unsigned profileGroup() const
- {
- if (!m_rareData)
- return 0;
- return m_rareData->profileGroup;
- }
+ void* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
- Debugger* debugger() const { return m_debugger; }
- void setDebugger(Debugger* debugger) { m_debugger = debugger; }
+ Debugger* m_debugger;
- const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
+ RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint;
+ RefPtr<WatchpointSet> m_havingABadTimeWatchpoint;
- static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }
- static bool supportsProfiling(const JSGlobalObject*) { return false; }
- static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
+ OwnPtr<JSGlobalObjectRareData> m_rareData;
- JS_EXPORT_PRIVATE ExecState* globalExec();
+ WeakRandom m_weakRandom;
- static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
- static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return false; }
+ bool m_evalEnabled;
+ String m_evalDisabledErrorMessage;
+ bool m_experimentsEnabled;
- bool isDynamicScope(bool& requiresDynamicChecks) const;
+ static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable;
+ const GlobalObjectMethodTable* m_globalObjectMethodTable;
- bool evalEnabled() const { return m_evalEnabled; }
- const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
- void setEvalEnabled(bool enabled, const String& errorMessage = String())
- {
- m_evalEnabled = enabled;
- m_evalDisabledErrorMessage = errorMessage;
- }
-
- void resetPrototype(JSGlobalData&, JSValue prototype);
-
- JSGlobalData& globalData() const { return *Heap::heap(this)->globalData(); }
- JSObject* globalThis() const;
+ void createRareDataIfNeeded()
+ {
+ if (m_rareData)
+ return;
+ m_rareData = adoptPtr(new JSGlobalObjectRareData);
+ }
+
+public:
+ typedef JSSegmentedVariableObject Base;
- static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
- {
- return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
- }
+ static JSGlobalObject* create(VM& vm, Structure* structure)
+ {
+ JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(vm.heap)) JSGlobalObject(vm, structure);
+ globalObject->finishCreation(vm);
+ vm.heap.addFinalizer(globalObject, destroy);
+ return globalObject;
+ }
- void registerWeakMap(OpaqueJSWeakObjectMap* map)
- {
- createRareDataIfNeeded();
- m_rareData->weakMaps.add(map);
- }
+ static JS_EXPORTDATA const ClassInfo s_info;
- void unregisterWeakMap(OpaqueJSWeakObjectMap* map)
- {
- if (m_rareData)
- m_rareData->weakMaps.remove(map);
- }
+ bool hasDebugger() const { return m_debugger; }
+ bool hasProfiler() const { return globalObjectMethodTable()->supportsProfiling(this); }
- double weakRandomNumber() { return m_weakRandom.get(); }
- unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
+protected:
+ JS_EXPORT_PRIVATE explicit JSGlobalObject(VM&, Structure*, const GlobalObjectMethodTable* = 0);
- UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception);
- UnlinkedEvalCodeBlock* createEvalCodeBlock(CallFrame*, EvalExecutable*, JSObject** exception);
- UnlinkedFunctionExecutable* createFunctionExecutableFromGlobalCode(CallFrame*, const Identifier&, const SourceCode&, JSObject** exception);
+ void finishCreation(VM& vm)
+ {
+ Base::finishCreation(vm);
+ structure()->setGlobalObject(vm, this);
+ m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this);
+ init(this);
+ }
- protected:
+ void finishCreation(VM& vm, JSObject* thisValue)
+ {
+ Base::finishCreation(vm);
+ structure()->setGlobalObject(vm, this);
+ m_experimentsEnabled = m_globalObjectMethodTable->javaScriptExperimentsEnabled(this);
+ init(thisValue);
+ }
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
+public:
+ JS_EXPORT_PRIVATE ~JSGlobalObject();
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
+ // We don't need a destructor because we use a finalizer instead.
+ static const bool needsDestruction = false;
- struct GlobalPropertyInfo {
- GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
- : identifier(i)
- , value(v)
- , attributes(a)
- {
- }
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- const Identifier identifier;
- JSValue value;
- unsigned attributes;
- };
- JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+ bool hasOwnPropertyForWrite(ExecState*, PropertyName);
+ JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
- JS_EXPORT_PRIVATE static JSC::JSObject* toThisObject(JSC::JSCell*, JSC::ExecState*);
+ JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
- JS_EXPORT_PRIVATE void setGlobalThis(JSGlobalData&, JSObject* globalThis);
+ JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, PropertyName, JSObject* getterFunc, unsigned attributes);
+ JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, PropertyName, JSObject* setterFunc, unsigned attributes);
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
- private:
- friend class LLIntOffsetsExtractor;
-
- // FIXME: Fold reset into init.
- JS_EXPORT_PRIVATE void init(JSObject* thisValue);
- void reset(JSValue prototype);
+ // We use this in the code generator as we perform symbol table
+ // lookups prior to initializing the properties
+ bool symbolTableHasProperty(PropertyName);
- void createThrowTypeError(ExecState*);
+ // The following accessors return pristine values, even if a script
+ // replaces the global object's associated property.
- JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
- };
+ RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
- JSGlobalObject* asGlobalObject(JSValue);
+ ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
+ NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
+ NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
+ NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
+ NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
+ NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
+ NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
- inline JSGlobalObject* asGlobalObject(JSValue value)
+ JSFunction* evalFunction() const { return m_evalFunction.get(); }
+ JSFunction* callFunction() const { return m_callFunction.get(); }
+ JSFunction* applyFunction() const { return m_applyFunction.get(); }
+ GetterSetter* throwTypeErrorGetterSetter(ExecState* exec)
{
- ASSERT(asObject(value)->isGlobalObject());
- return jsCast<JSGlobalObject*>(asObject(value));
+ if (!m_throwTypeErrorGetterSetter)
+ createThrowTypeError(exec);
+ return m_throwTypeErrorGetterSetter.get();
}
- inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, PropertyName propertyName)
+ ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
+ FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
+ ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
+ BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
+ StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
+ NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
+ DatePrototype* datePrototype() const { return m_datePrototype.get(); }
+ RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
+ ErrorPrototype* errorPrototype() const { return m_errorPrototype.get(); }
+
+ Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
+ Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
+ 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
{
- PropertySlot slot;
- if (Base::getOwnPropertySlot(this, exec, propertyName, slot))
- return true;
- bool slotIsWriteable;
- return symbolTableGet(this, propertyName, slot, slotIsWriteable);
+ ASSERT(indexingType & IsArray);
+ return m_originalArrayStructureForIndexingShape[(indexingType & IndexingShapeMask) >> IndexingShapeShift].get();
}
-
- inline bool JSGlobalObject::symbolTableHasProperty(PropertyName propertyName)
+ Structure* arrayStructureForIndexingTypeDuringAllocation(IndexingType indexingType) const
{
- SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
- return !entry.isNull();
+ ASSERT(indexingType & IsArray);
+ return m_arrayStructureForIndexingShapeDuringAllocation[(indexingType & IndexingShapeMask) >> IndexingShapeShift].get();
}
-
- inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
+ Structure* arrayStructureForProfileDuringAllocation(ArrayAllocationProfile* profile) const
{
- if (isObject())
- return m_prototype.get();
-
- ASSERT(typeInfo().type() == StringType);
- return globalObject->stringPrototype();
+ return arrayStructureForIndexingTypeDuringAllocation(ArrayAllocationProfile::selectIndexingTypeFor(profile));
}
-
- inline JSValue Structure::prototypeForLookup(ExecState* exec) const
+
+ bool isOriginalArrayStructure(Structure* structure)
{
- return prototypeForLookup(exec->lexicalGlobalObject());
+ return originalArrayStructureForIndexingType(structure->indexingType() | IsArray) == structure;
}
-
- inline StructureChain* Structure::prototypeChain(JSGlobalData& globalData, JSGlobalObject* globalObject) const
+
+ Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
+ Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
+ Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
+ Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
+#if JSC_OBJC_API_ENABLED
+ Structure* objcCallbackFunctionStructure() const { return m_objcCallbackFunctionStructure.get(); }
+ Structure* objcWrapperObjectStructure() const { return m_objcWrapperObjectStructure.get(); }
+#endif
+ Structure* dateStructure() const { return m_dateStructure.get(); }
+ Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
+ Structure* errorStructure() const { return m_errorStructure.get(); }
+ Structure* functionStructure() const { return m_functionStructure.get(); }
+ Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
+ Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
+ PropertyOffset functionNameOffset() const { return m_functionNameOffset; }
+ Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
+ Structure* privateNameStructure() const { return m_privateNameStructure.get(); }
+ Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
+ Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
+ Structure* regExpStructure() const { return m_regExpStructure.get(); }
+ Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
+
+ void* actualPointerFor(Special::Pointer pointer)
{
- // We cache our prototype chain so our clients can share it.
- if (!isValid(globalObject, m_cachedPrototypeChain.get())) {
- JSValue prototype = prototypeForLookup(globalObject);
- m_cachedPrototypeChain.set(globalData, this, StructureChain::create(globalData, prototype.isNull() ? 0 : asObject(prototype)->structure()));
- }
- return m_cachedPrototypeChain.get();
+ ASSERT(pointer < Special::TableSize);
+ return m_specialPointers[pointer];
}
- inline StructureChain* Structure::prototypeChain(ExecState* exec) const
+ WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); }
+ WatchpointSet* havingABadTimeWatchpoint() { return m_havingABadTimeWatchpoint.get(); }
+
+ bool isHavingABadTime() const
{
- return prototypeChain(exec->globalData(), exec->lexicalGlobalObject());
+ return m_havingABadTimeWatchpoint->hasBeenInvalidated();
}
+
+ void haveABadTime(VM&);
+
+ bool arrayPrototypeChainIsSane();
- inline bool Structure::isValid(JSGlobalObject* globalObject, StructureChain* cachedPrototypeChain) const
- {
- if (!cachedPrototypeChain)
- return false;
-
- JSValue prototype = prototypeForLookup(globalObject);
- WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
- while(*cachedStructure && !prototype.isNull()) {
- if (asObject(prototype)->structure() != cachedStructure->get())
- return false;
- ++cachedStructure;
- prototype = asObject(prototype)->prototype();
- }
- return prototype.isNull() && !*cachedStructure;
+ void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
+ unsigned profileGroup() const
+ {
+ if (!m_rareData)
+ return 0;
+ return m_rareData->profileGroup;
}
- inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
- {
- return isValid(exec->lexicalGlobalObject(), cachedPrototypeChain);
- }
+ Debugger* debugger() const { return m_debugger; }
+ void setDebugger(Debugger* debugger) { m_debugger = debugger; }
- inline JSGlobalObject* ExecState::dynamicGlobalObject()
- {
- if (this == lexicalGlobalObject()->globalExec())
- return lexicalGlobalObject();
+ const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
- // For any ExecState that's not a globalExec, the
- // dynamic global object must be set since code is running
- ASSERT(globalData().dynamicGlobalObject);
- return globalData().dynamicGlobalObject;
- }
+ static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }
+ static bool supportsProfiling(const JSGlobalObject*) { return false; }
+ static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
- inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
- {
- return constructEmptyObject(exec, globalObject->emptyObjectStructure());
- }
+ JS_EXPORT_PRIVATE ExecState* globalExec();
- inline JSObject* constructEmptyObject(ExecState* exec)
- {
- return constructEmptyObject(exec, exec->lexicalGlobalObject());
- }
+ static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
+ static bool javaScriptExperimentsEnabled(const JSGlobalObject*) { return false; }
- inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, 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));
- }
+ bool isDynamicScope(bool& requiresDynamicChecks) const;
- inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, unsigned initialLength = 0)
+ bool evalEnabled() const { return m_evalEnabled; }
+ const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; }
+ void setEvalEnabled(bool enabled, const String& errorMessage = String())
{
- return constructEmptyArray(exec, profile, exec->lexicalGlobalObject(), initialLength);
+ m_evalEnabled = enabled;
+ m_evalDisabledErrorMessage = errorMessage;
}
-
- inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values)
+
+ void resetPrototype(VM&, JSValue prototype);
+
+ VM& vm() const { return *Heap::heap(this)->vm(); }
+ JSObject* globalThis() const;
+
+ static Structure* createStructure(VM& vm, JSValue prototype)
{
- return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values));
+ return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
}
- inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values)
+ void registerWeakMap(OpaqueJSWeakObjectMap* map)
{
- return constructArray(exec, profile, exec->lexicalGlobalObject(), values);
+ createRareDataIfNeeded();
+ m_rareData->weakMaps.add(map);
}
- inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
+ void unregisterWeakMap(OpaqueJSWeakObjectMap* map)
{
- return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values, length));
+ if (m_rareData)
+ m_rareData->weakMaps.remove(map);
}
- inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length)
+ OpaqueJSClassDataMap& opaqueJSClassData()
{
- return constructArray(exec, profile, exec->lexicalGlobalObject(), values, length);
+ createRareDataIfNeeded();
+ return m_rareData->opaqueJSClassData;
}
- class DynamicGlobalObjectScope {
- WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
- public:
- JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
+ double weakRandomNumber() { return m_weakRandom.get(); }
+ unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
+
+ UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception);
+ UnlinkedEvalCodeBlock* createEvalCodeBlock(CodeCache*, CallFrame*, JSScope*, EvalExecutable*, JSObject** exception);
+
+protected:
- ~DynamicGlobalObjectScope()
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
+
+ struct GlobalPropertyInfo {
+ GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
+ : identifier(i)
+ , value(v)
+ , attributes(a)
{
- m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
}
- private:
- JSGlobalObject*& m_dynamicGlobalObjectSlot;
- JSGlobalObject* m_savedDynamicGlobalObject;
+ const Identifier identifier;
+ JSValue value;
+ unsigned attributes;
};
+ JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
- inline bool JSGlobalObject::isDynamicScope(bool&) const
- {
- return true;
- }
+ JS_EXPORT_PRIVATE static JSC::JSObject* toThisObject(JSC::JSCell*, JSC::ExecState*);
- inline JSObject* JSScope::globalThis()
- {
- return globalObject()->globalThis();
- }
+ JS_EXPORT_PRIVATE void setGlobalThis(VM&, JSObject* globalThis);
- inline JSObject* JSGlobalObject::globalThis() const
- {
- return m_globalThis.get();
+private:
+ friend class LLIntOffsetsExtractor;
+
+ // FIXME: Fold reset into init.
+ JS_EXPORT_PRIVATE void init(JSObject* thisValue);
+ void reset(JSValue prototype);
+
+ void createThrowTypeError(ExecState*);
+
+ JS_EXPORT_PRIVATE static void clearRareData(JSCell*);
+};
+
+JSGlobalObject* asGlobalObject(JSValue);
+
+inline JSGlobalObject* asGlobalObject(JSValue value)
+{
+ ASSERT(asObject(value)->isGlobalObject());
+ return jsCast<JSGlobalObject*>(asObject(value));
+}
+
+inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, PropertyName propertyName)
+{
+ PropertySlot slot;
+ if (Base::getOwnPropertySlot(this, exec, propertyName, slot))
+ return true;
+ bool slotIsWriteable;
+ return symbolTableGet(this, propertyName, slot, slotIsWriteable);
+}
+
+inline bool JSGlobalObject::symbolTableHasProperty(PropertyName propertyName)
+{
+ SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
+ return !entry.isNull();
+}
+
+inline JSGlobalObject* ExecState::dynamicGlobalObject()
+{
+ if (this == lexicalGlobalObject()->globalExec())
+ return lexicalGlobalObject();
+
+ // For any ExecState that's not a globalExec, the
+ // dynamic global object must be set since code is running
+ ASSERT(vm().dynamicGlobalObject);
+ return vm().dynamicGlobalObject;
+}
+
+inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, unsigned initialLength = 0)
+{
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, JSArray::create(exec->vm(), initialLength >= MIN_SPARSE_ARRAY_INDEX ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : globalObject->arrayStructureForProfileDuringAllocation(profile), initialLength));
+}
+
+inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, unsigned initialLength = 0)
+{
+ return constructEmptyArray(exec, profile, exec->lexicalGlobalObject(), initialLength);
+}
+
+inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const ArgList& values)
+{
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values));
+}
+
+inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const ArgList& values)
+{
+ return constructArray(exec, profile, exec->lexicalGlobalObject(), values);
+}
+
+inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
+{
+ return ArrayAllocationProfile::updateLastAllocationFor(profile, constructArray(exec, globalObject->arrayStructureForProfileDuringAllocation(profile), values, length));
+}
+
+inline JSArray* constructArray(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, unsigned length)
+{
+ return constructArray(exec, profile, exec->lexicalGlobalObject(), values, length);
+}
+
+class DynamicGlobalObjectScope {
+ WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
+public:
+ JS_EXPORT_PRIVATE DynamicGlobalObjectScope(VM&, JSGlobalObject*);
+
+ ~DynamicGlobalObjectScope()
+ {
+ m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
}
+private:
+ JSGlobalObject*& m_dynamicGlobalObjectSlot;
+ JSGlobalObject* m_savedDynamicGlobalObject;
+};
+
+inline bool JSGlobalObject::isDynamicScope(bool&) const
+{
+ return true;
+}
+
+inline JSObject* JSScope::globalThis()
+{
+ return globalObject()->globalThis();
+}
+
+inline JSObject* JSGlobalObject::globalThis() const
+{
+ return m_globalThis.get();
+}
+
} // namespace JSC
#endif // JSGlobalObject_h
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index 1010ad2b7..0efaf84bc 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -34,6 +34,7 @@
#include "Lexer.h"
#include "LiteralParser.h"
#include "Nodes.h"
+#include "Operations.h"
#include "Parser.h"
#include <wtf/dtoa.h>
#include <stdio.h>
@@ -363,7 +364,7 @@ static double jsHexIntegerLiteral(const CharType*& data, const CharType* end)
template <typename CharType>
static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
{
- ASSERT(data < end);
+ RELEASE_ASSERT(data < end);
size_t parsedLength;
double number = parseDouble(data, end - data, parsedLength);
@@ -514,7 +515,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
}
JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject();
- EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
+ EvalExecutable* eval = EvalExecutable::create(exec, exec->vm().codeCache(), makeSource(s), false);
JSObject* error = eval->compile(exec, calleeGlobalObject);
if (error)
return throwVMError(exec, error);
@@ -559,13 +560,13 @@ EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
{
- return JSValue::encode(jsBoolean(isnan(exec->argument(0).toNumber(exec))));
+ return JSValue::encode(jsBoolean(std::isnan(exec->argument(0).toNumber(exec))));
}
EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)
{
double n = exec->argument(0).toNumber(exec);
- return JSValue::encode(jsBoolean(isfinite(n)));
+ return JSValue::encode(jsBoolean(std::isfinite(n)));
}
EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
@@ -735,7 +736,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
if (!thisObject->isExtensible())
return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
- if (!thisObject->setPrototypeWithCycleCheck(exec->globalData(), value))
+ if (!thisObject->setPrototypeWithCycleCheck(exec->vm(), value))
throwError(exec, createError(exec, "cyclic __proto__ value"));
return JSValue::encode(jsUndefined());
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
index 757c9dcac..f4512e405 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
@@ -24,39 +24,39 @@
#ifndef JSGlobalObjectFunctions_h
#define JSGlobalObjectFunctions_h
-#include "JSValue.h"
+#include "JSCJSValue.h"
#include <wtf/unicode/Unicode.h>
namespace JSC {
- class ArgList;
- class ExecState;
- class JSObject;
-
- // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there
- // is a 0.5% reduction.
-
- EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
- EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
-
- static const double mantissaOverflowLowerBound = 9007199254740992.0;
- double parseIntOverflow(const LChar*, int length, int radix);
- ALWAYS_INLINE double parseIntOverflow(const char* s, int length, int radix) { return parseIntOverflow(reinterpret_cast<const LChar*>(s), length, radix); }
- double parseIntOverflow(const UChar*, int length, int radix);
- bool isStrWhiteSpace(UChar);
- double jsToNumber(const WTF::String&);
+class ArgList;
+class ExecState;
+class JSObject;
+
+// FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there
+// is a 0.5% reduction.
+
+EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
+EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
+
+static const double mantissaOverflowLowerBound = 9007199254740992.0;
+double parseIntOverflow(const LChar*, int length, int radix);
+ALWAYS_INLINE double parseIntOverflow(const char* s, int length, int radix) { return parseIntOverflow(reinterpret_cast<const LChar*>(s), length, radix); }
+double parseIntOverflow(const UChar*, int length, int radix);
+bool isStrWhiteSpace(UChar);
+double jsToNumber(const WTF::String&);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp
index 5e3d12c92..4baa2a603 100644
--- a/Source/JavaScriptCore/runtime/JSLock.cpp
+++ b/Source/JavaScriptCore/runtime/JSLock.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2008, 2012 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,7 +25,7 @@
#include "CallFrame.h"
#include "JSGlobalObject.h"
#include "JSObject.h"
-
+#include "Operations.h"
#if USE(PTHREADS)
#include <pthread.h>
@@ -51,32 +51,40 @@ void GlobalJSLock::initialize()
}
JSLockHolder::JSLockHolder(ExecState* exec)
- : m_globalData(&exec->globalData())
+ : m_vm(&exec->vm())
+{
+ init();
+}
+
+JSLockHolder::JSLockHolder(VM* vm)
+ : m_vm(vm)
{
- m_globalData->apiLock().lock();
+ init();
}
-JSLockHolder::JSLockHolder(JSGlobalData* globalData)
- : m_globalData(globalData)
+JSLockHolder::JSLockHolder(VM& vm)
+ : m_vm(&vm)
{
- m_globalData->apiLock().lock();
+ init();
}
-JSLockHolder::JSLockHolder(JSGlobalData& globalData)
- : m_globalData(&globalData)
+void JSLockHolder::init()
{
- m_globalData->apiLock().lock();
+ m_vm->apiLock().lock();
}
JSLockHolder::~JSLockHolder()
{
- m_globalData->apiLock().unlock();
+ RefPtr<JSLock> apiLock(&m_vm->apiLock());
+ m_vm.clear();
+ apiLock->unlock();
}
-JSLock::JSLock()
+JSLock::JSLock(VM* vm)
: m_ownerThread(0)
, m_lockCount(0)
, m_lockDropDepth(0)
+ , m_vm(vm)
{
m_spinLock.Init();
}
@@ -85,6 +93,12 @@ JSLock::~JSLock()
{
}
+void JSLock::willDestroyVM(VM* vm)
+{
+ ASSERT_UNUSED(vm, m_vm == vm);
+ m_vm = 0;
+}
+
void JSLock::lock()
{
ThreadIdentifier currentThread = WTF::currentThread();
@@ -119,12 +133,12 @@ void JSLock::unlock()
void JSLock::lock(ExecState* exec)
{
- exec->globalData().apiLock().lock();
+ exec->vm().apiLock().lock();
}
void JSLock::unlock(ExecState* exec)
{
- exec->globalData().apiLock().unlock();
+ exec->vm().apiLock().unlock();
}
bool JSLock::currentThreadIsHoldingLock()
@@ -201,21 +215,21 @@ void JSLock::grabAllLocks(unsigned lockCount)
JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
: m_lockCount(0)
- , m_globalData(&exec->globalData())
+ , m_vm(&exec->vm())
{
- m_lockCount = m_globalData->apiLock().dropAllLocks();
+ m_lockCount = m_vm->apiLock().dropAllLocks();
}
-JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData)
+JSLock::DropAllLocks::DropAllLocks(VM* vm)
: m_lockCount(0)
- , m_globalData(globalData)
+ , m_vm(vm)
{
- m_lockCount = m_globalData->apiLock().dropAllLocks();
+ m_lockCount = m_vm->apiLock().dropAllLocks();
}
JSLock::DropAllLocks::~DropAllLocks()
{
- m_globalData->apiLock().grabAllLocks(m_lockCount);
+ m_vm->apiLock().grabAllLocks(m_lockCount);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h
index 4c42dc0ae..83bcc2425 100644
--- a/Source/JavaScriptCore/runtime/JSLock.h
+++ b/Source/JavaScriptCore/runtime/JSLock.h
@@ -49,10 +49,10 @@ namespace JSC {
// thread acquired it to begin with.
class ExecState;
- class JSGlobalData;
+ class VM;
// This class is used to protect the initialization of the legacy single
- // shared JSGlobalData.
+ // shared VM.
class GlobalJSLock {
WTF_MAKE_NONCOPYABLE(GlobalJSLock);
public:
@@ -66,19 +66,21 @@ namespace JSC {
class JSLockHolder {
public:
- JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData*);
- JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData&);
+ JS_EXPORT_PRIVATE JSLockHolder(VM*);
+ JS_EXPORT_PRIVATE JSLockHolder(VM&);
JS_EXPORT_PRIVATE JSLockHolder(ExecState*);
JS_EXPORT_PRIVATE ~JSLockHolder();
private:
- RefPtr<JSGlobalData> m_globalData;
+ void init();
+
+ RefPtr<VM> m_vm;
};
- class JSLock {
+ class JSLock : public ThreadSafeRefCounted<JSLock> {
WTF_MAKE_NONCOPYABLE(JSLock);
public:
- JSLock();
+ JSLock(VM*);
JS_EXPORT_PRIVATE ~JSLock();
JS_EXPORT_PRIVATE void lock();
@@ -86,8 +88,10 @@ namespace JSC {
static void lock(ExecState*);
static void unlock(ExecState*);
- static void lock(JSGlobalData&);
- static void unlock(JSGlobalData&);
+ static void lock(VM&);
+ static void unlock(VM&);
+
+ VM* vm() { return m_vm; }
JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock();
@@ -95,16 +99,18 @@ namespace JSC {
unsigned dropAllLocksUnconditionally();
void grabAllLocks(unsigned lockCount);
+ void willDestroyVM(VM*);
+
class DropAllLocks {
WTF_MAKE_NONCOPYABLE(DropAllLocks);
public:
JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec);
- JS_EXPORT_PRIVATE DropAllLocks(JSGlobalData*);
+ JS_EXPORT_PRIVATE DropAllLocks(VM*);
JS_EXPORT_PRIVATE ~DropAllLocks();
private:
intptr_t m_lockCount;
- RefPtr<JSGlobalData> m_globalData;
+ RefPtr<VM> m_vm;
};
private:
@@ -113,6 +119,7 @@ namespace JSC {
ThreadIdentifier m_ownerThread;
intptr_t m_lockCount;
unsigned m_lockDropDepth;
+ VM* m_vm;
};
} // namespace
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.cpp b/Source/JavaScriptCore/runtime/JSNameScope.cpp
index 335631fd0..53468d6a8 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSNameScope.cpp
@@ -27,6 +27,7 @@
#include "JSNameScope.h"
#include "Error.h"
+#include "Operations.h"
namespace JSC {
@@ -69,7 +70,7 @@ void JSNameScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName,
if (symbolTablePut(thisObject, exec, propertyName, value, slot.isStrictMode()))
return;
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
bool JSNameScope::getOwnPropertySlot(JSCell* cell, ExecState*, PropertyName propertyName, PropertySlot& slot)
diff --git a/Source/JavaScriptCore/runtime/JSNameScope.h b/Source/JavaScriptCore/runtime/JSNameScope.h
index e67370d92..43763296c 100644
--- a/Source/JavaScriptCore/runtime/JSNameScope.h
+++ b/Source/JavaScriptCore/runtime/JSNameScope.h
@@ -56,15 +56,15 @@ public:
static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(NameScopeObjectType, StructureFlags), &s_info); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(NameScopeObjectType, StructureFlags), &s_info); }
static const ClassInfo s_info;
protected:
void finishCreation(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes)
{
- Base::finishCreation(exec->globalData());
- m_registerStore.set(exec->globalData(), this, value);
+ Base::finishCreation(exec->vm());
+ m_registerStore.set(exec->vm(), this, value);
symbolTable()->add(identifier.impl(), SymbolTableEntry(-1, attributes));
}
@@ -73,7 +73,7 @@ protected:
private:
JSNameScope(ExecState* exec, JSScope* next)
: Base(
- exec->globalData(),
+ exec->vm(),
exec->lexicalGlobalObject()->nameScopeStructure(),
reinterpret_cast<Register*>(&m_registerStore + 1),
next
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
index 53592ba2b..0e4332eb4 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -30,7 +30,7 @@
#include "config.h"
#include "JSNotAnObject.h"
-#include <wtf/UnusedParam.h>
+#include "Operations.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h
index 3636c9bd4..4ec73ac09 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h
@@ -39,7 +39,7 @@ namespace JSC {
class JSNotAnObject : public JSNonFinalObject {
private:
JSNotAnObject(ExecState* exec)
- : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get())
+ : JSNonFinalObject(exec->vm(), exec->vm().notAnObjectStructure.get())
{
}
@@ -49,13 +49,13 @@ namespace JSC {
static JSNotAnObject* create(ExecState* exec)
{
JSNotAnObject* object = new (NotNull, allocateCell<JSNotAnObject>(*exec->heap())) JSNotAnObject(exec);
- object->finishCreation(exec->globalData());
+ object->finishCreation(exec->vm());
return object;
}
- 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);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index e051ec7d9..91b412ec3 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -35,6 +35,8 @@
#include "Local.h"
#include "LocalScope.h"
#include "Lookup.h"
+#include "ObjectConstructor.h"
+#include "Operations.h"
#include "PropertyNameArray.h"
#include <wtf/MathExtras.h>
#include <wtf/text/StringBuilder.h>
@@ -53,13 +55,13 @@ static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
namespace JSC {
JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure)
- : JSNonFinalObject(globalObject->globalData(), structure)
+ : JSNonFinalObject(globalObject->vm(), structure)
{
}
void JSONObject::finishCreation(JSGlobalObject* globalObject)
{
- Base::finishCreation(globalObject->globalData());
+ Base::finishCreation(globalObject->vm());
ASSERT(inherits(&s_info));
}
@@ -88,7 +90,7 @@ public:
private:
class Holder {
public:
- Holder(JSGlobalData&, JSObject*);
+ Holder(VM&, JSObject*);
JSObject* object() const { return m_object.get(); }
@@ -125,7 +127,7 @@ private:
CallData m_replacerCallData;
const String m_gap;
- Vector<Holder, 16> m_holderStack;
+ Vector<Holder, 16, UnsafeVectorOverflow> m_holderStack;
String m_repeatedGap;
String m_indent;
};
@@ -215,7 +217,7 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const
if (m_replacer.asObject()->inherits(&JSArray::s_info)) {
m_usingArrayReplacer = true;
Handle<JSObject> array = m_replacer.asObject();
- unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
+ unsigned length = array->get(exec, exec->vm().propertyNames->length).toUInt32(exec);
for (unsigned i = 0; i < length; ++i) {
JSValue name = array->get(exec, i);
if (exec->hadException())
@@ -238,18 +240,18 @@ Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
{
JSObject* object = constructEmptyObject(m_exec);
if (m_exec->hadException())
- return Local<Unknown>(m_exec->globalData(), jsNull());
+ return Local<Unknown>(m_exec->vm(), jsNull());
- PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier);
- object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get());
+ PropertyNameForFunctionCall emptyPropertyName(m_exec->vm().propertyNames->emptyIdentifier);
+ object->putDirect(m_exec->vm(), m_exec->vm().propertyNames->emptyIdentifier, value.get());
StringBuilder result;
if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded)
- return Local<Unknown>(m_exec->globalData(), jsUndefined());
+ return Local<Unknown>(m_exec->vm(), jsUndefined());
if (m_exec->hadException())
- return Local<Unknown>(m_exec->globalData(), jsNull());
+ return Local<Unknown>(m_exec->vm(), jsNull());
- return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toString()));
+ return Local<Unknown>(m_exec->vm(), jsString(m_exec, result.toString()));
}
template <typename CharType>
@@ -318,10 +320,10 @@ void Stringifier::appendQuotedString(StringBuilder& builder, const String& value
inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionCall& propertyName)
{
ASSERT(!m_exec->hadException());
- if (!value.isObject() || !asObject(value)->hasProperty(m_exec, m_exec->globalData().propertyNames->toJSON))
+ if (!value.isObject() || !asObject(value)->hasProperty(m_exec, m_exec->vm().propertyNames->toJSON))
return value;
- JSValue toJSONFunction = asObject(value)->get(m_exec, m_exec->globalData().propertyNames->toJSON);
+ JSValue toJSONFunction = asObject(value)->get(m_exec, m_exec->vm().propertyNames->toJSON);
if (m_exec->hadException())
return jsNull();
@@ -385,7 +387,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
if (value.isNumber()) {
double number = value.asNumber();
- if (!isfinite(number))
+ if (!std::isfinite(number))
builder.appendLiteral("null");
else
builder.append(String::numberToStringECMAScript(number));
@@ -414,25 +416,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
}
}
bool holderStackWasEmpty = m_holderStack.isEmpty();
- m_holderStack.append(Holder(m_exec->globalData(), object));
+ m_holderStack.append(Holder(m_exec->vm(), object));
if (!holderStackWasEmpty)
return StringifySucceeded;
- // If this is the outermost call, then loop to handle everything on the holder stack.
- TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker);
- localTimeoutChecker.reset();
- unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck();
do {
while (m_holderStack.last().appendNextProperty(*this, builder)) {
if (m_exec->hadException())
return StringifyFailed;
- if (!--tickCount) {
- if (localTimeoutChecker.didTimeOut(m_exec)) {
- throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
- return StringifyFailed;
- }
- tickCount = localTimeoutChecker.ticksUntilNextCheck();
- }
}
m_holderStack.removeLast();
} while (!m_holderStack.isEmpty());
@@ -468,8 +459,8 @@ inline void Stringifier::startNewLine(StringBuilder& builder) const
builder.append(m_indent);
}
-inline Stringifier::Holder::Holder(JSGlobalData& globalData, JSObject* object)
- : m_object(globalData, object)
+inline Stringifier::Holder::Holder(VM& vm, JSObject* object)
+ : m_object(vm, object)
, m_isArray(object->inherits(&JSArray::s_info))
, m_index(0)
#ifndef NDEBUG
@@ -488,7 +479,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
if (!m_index) {
if (m_isArray) {
m_isJSArray = isJSArray(m_object.get());
- m_size = m_object->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
+ m_size = m_object->get(exec, exec->vm().propertyNames->length).toUInt32(exec);
builder.append('[');
} else {
if (stringifier.m_usingArrayReplacer)
@@ -613,7 +604,7 @@ class Walker {
public:
Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData)
: m_exec(exec)
- , m_function(exec->globalData(), function)
+ , m_function(exec->vm(), function)
, m_callType(callType)
, m_callData(callData)
{
@@ -636,26 +627,22 @@ private:
CallData m_callData;
};
-// We clamp recursion well beyond anything reasonable, but we also have a timeout check
-// to guard against "infinite" execution by inserting arbitrarily large objects.
+// We clamp recursion well beyond anything reasonable.
static const unsigned maximumFilterRecursion = 40000;
enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
{
- Vector<PropertyNameArray, 16> propertyStack;
- Vector<uint32_t, 16> indexStack;
- LocalStack<JSObject, 16> objectStack(m_exec->globalData());
- LocalStack<JSArray, 16> arrayStack(m_exec->globalData());
+ Vector<PropertyNameArray, 16, UnsafeVectorOverflow> propertyStack;
+ Vector<uint32_t, 16, UnsafeVectorOverflow> indexStack;
+ LocalStack<JSObject, 16> objectStack(m_exec->vm());
+ LocalStack<JSArray, 16> arrayStack(m_exec->vm());
- Vector<WalkerState, 16> stateStack;
+ Vector<WalkerState, 16, UnsafeVectorOverflow> stateStack;
WalkerState state = StateUnknown;
JSValue inValue = unfiltered;
JSValue outValue = jsNull();
- TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker);
- localTimeoutChecker.reset();
- unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck();
while (1) {
switch (state) {
arrayStartState:
@@ -672,12 +659,6 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
}
arrayStartVisitMember:
case ArrayStartVisitMember: {
- if (!--tickCount) {
- if (localTimeoutChecker.didTimeOut(m_exec))
- return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
- tickCount = localTimeoutChecker.ticksUntilNextCheck();
- }
-
JSArray* array = arrayStack.peek();
uint32_t index = indexStack.last();
if (index == array->length()) {
@@ -731,12 +712,6 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
}
objectStartVisitMember:
case ObjectStartVisitMember: {
- if (!--tickCount) {
- if (localTimeoutChecker.didTimeOut(m_exec))
- return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
- tickCount = localTimeoutChecker.ticksUntilNextCheck();
- }
-
JSObject* object = objectStack.peek();
uint32_t index = indexStack.last();
PropertyNameArray& properties = propertyStack.last();
@@ -794,16 +769,10 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
state = stateStack.last();
stateStack.removeLast();
-
- if (!--tickCount) {
- if (localTimeoutChecker.didTimeOut(m_exec))
- return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
- tickCount = localTimeoutChecker.ticksUntilNextCheck();
- }
}
JSObject* finalHolder = constructEmptyObject(m_exec);
PutPropertySlot slot;
- finalHolder->methodTable()->put(finalHolder, m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot);
+ finalHolder->methodTable()->put(finalHolder, m_exec, m_exec->vm().propertyNames->emptyIdentifier, outValue, slot);
return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
}
@@ -817,7 +786,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
return JSValue::encode(jsNull());
JSValue unfiltered;
- LocalScope scope(exec->globalData());
+ LocalScope scope(exec->vm());
if (source.is8Bit()) {
LiteralParser<LChar> jsonParser(exec, source.characters8(), source.length(), StrictJSON);
unfiltered = jsonParser.tryLiteralParse();
@@ -838,7 +807,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
CallType callType = getCallData(function, callData);
if (callType == CallTypeNone)
return JSValue::encode(unfiltered);
- return JSValue::encode(Walker(exec, Local<JSObject>(exec->globalData(), asObject(function)), callType, callData).walk(unfiltered));
+ return JSValue::encode(Walker(exec, Local<JSObject>(exec->vm(), asObject(function)), callType, callData).walk(unfiltered));
}
// ECMA-262 v5 15.12.3
@@ -846,17 +815,17 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec)
{
if (!exec->argumentCount())
return throwVMError(exec, createError(exec, ASCIILiteral("No input to stringify")));
- LocalScope scope(exec->globalData());
- Local<Unknown> value(exec->globalData(), exec->argument(0));
- Local<Unknown> replacer(exec->globalData(), exec->argument(1));
- Local<Unknown> space(exec->globalData(), exec->argument(2));
+ LocalScope scope(exec->vm());
+ Local<Unknown> value(exec->vm(), exec->argument(0));
+ Local<Unknown> replacer(exec->vm(), exec->argument(1));
+ Local<Unknown> space(exec->vm(), exec->argument(2));
return JSValue::encode(Stringifier(exec, replacer, space).stringify(value).get());
}
String JSONStringify(ExecState* exec, JSValue value, unsigned indent)
{
- LocalScope scope(exec->globalData());
- Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->globalData(), jsNull()), Local<Unknown>(exec->globalData(), jsNumber(indent))).stringify(Local<Unknown>(exec->globalData(), value));
+ LocalScope scope(exec->vm());
+ Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->vm(), jsNull()), Local<Unknown>(exec->vm(), jsNumber(indent))).stringify(Local<Unknown>(exec->vm(), value));
if (result.isUndefinedOrNull())
return String();
return result.getString(exec);
diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h
index b537b9144..c02809083 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.h
+++ b/Source/JavaScriptCore/runtime/JSONObject.h
@@ -43,9 +43,9 @@ namespace JSC {
return object;
}
- 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);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index e6f95bdfa..48fc23186 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel (eric@webkit.org)
*
* This library is free software; you can redistribute it and/or
@@ -30,6 +30,7 @@
#include "CopyVisitorInlines.h"
#include "DatePrototype.h"
#include "ErrorConstructor.h"
+#include "Executable.h"
#include "GetterSetter.h"
#include "IndexingHeaderInlines.h"
#include "JSFunction.h"
@@ -133,9 +134,9 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt
case ALL_CONTIGUOUS_INDEXING_TYPES:
case ALL_INT32_INDEXING_TYPES:
case ALL_DOUBLE_INDEXING_TYPES: {
- currentTarget = newButterfly->contiguous();
- currentSource = butterfly->contiguous();
- ASSERT(newButterfly->publicLength() <= newButterfly->vectorLength());
+ currentTarget = newButterfly->contiguous().data();
+ currentSource = butterfly->contiguous().data();
+ RELEASE_ASSERT(newButterfly->publicLength() <= newButterfly->vectorLength());
count = newButterfly->vectorLength();
break;
}
@@ -189,7 +190,7 @@ ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor& visitor, Butterfly* but
// Mark the array if appropriate.
switch (structure->indexingType()) {
case ALL_CONTIGUOUS_INDEXING_TYPES:
- visitor.appendValues(butterfly->contiguous(), butterfly->publicLength());
+ visitor.appendValues(butterfly->contiguous().data(), butterfly->publicLength());
break;
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
visitor.appendValues(butterfly->arrayStorage()->m_vector, butterfly->arrayStorage()->vectorLength());
@@ -328,7 +329,7 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
break;
}
@@ -341,7 +342,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV
JSObject* thisObject = jsCast<JSObject*>(cell);
ASSERT(value);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// Try indexed put first. This is required for correctness, since loads on property names that appear like
// valid indices will never look in the named property storage.
@@ -357,8 +358,8 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV
for (JSObject* obj = thisObject; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
prototype = obj->prototype();
if (prototype.isNull()) {
- ASSERT(!thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->globalData(), propertyName));
- if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value))
+ ASSERT(!thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName));
+ if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value))
&& slot.isStrictMode())
throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
return;
@@ -370,19 +371,19 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV
for (obj = thisObject; ; obj = asObject(prototype)) {
unsigned attributes;
JSCell* specificValue;
- PropertyOffset offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+ PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes, specificValue);
if (isValidOffset(offset)) {
if (attributes & ReadOnly) {
- ASSERT(thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->globalData(), propertyName) || obj == thisObject);
+ ASSERT(thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
if (slot.isStrictMode())
throwError(exec, createTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)));
return;
}
- JSValue gs = obj->getDirectOffset(offset);
+ JSValue gs = obj->getDirect(offset);
if (gs.isGetterSetter()) {
ASSERT(attributes & Accessor);
- ASSERT(thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->globalData(), propertyName) || obj == thisObject);
+ ASSERT(thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
if (slot.isStrictMode())
@@ -411,8 +412,8 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV
break;
}
- ASSERT(!thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->globalData(), propertyName) || obj == thisObject);
- if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode())
+ ASSERT(!thisObject->structure()->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
+ if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode())
throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
return;
}
@@ -432,7 +433,7 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
break;
case ALL_UNDECIDED_INDEXING_TYPES: {
- thisObject->convertUndecidedForValue(exec->globalData(), value);
+ thisObject->convertUndecidedForValue(exec->vm(), value);
// Reloop.
putByIndex(cell, exec, propertyName, value, shouldThrow);
return;
@@ -440,7 +441,7 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
case ALL_INT32_INDEXING_TYPES: {
if (!value.isInt32()) {
- thisObject->convertInt32ForValue(exec->globalData(), value);
+ thisObject->convertInt32ForValue(exec->vm(), value);
putByIndex(cell, exec, propertyName, value, shouldThrow);
return;
}
@@ -451,7 +452,7 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
Butterfly* butterfly = thisObject->m_butterfly;
if (propertyName >= butterfly->vectorLength())
break;
- butterfly->contiguous()[propertyName].set(exec->globalData(), thisObject, value);
+ butterfly->contiguous()[propertyName].set(exec->vm(), thisObject, value);
if (propertyName >= butterfly->publicLength())
butterfly->setPublicLength(propertyName + 1);
return;
@@ -459,14 +460,14 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
case ALL_DOUBLE_INDEXING_TYPES: {
if (!value.isNumber()) {
- thisObject->convertDoubleToContiguous(exec->globalData());
+ thisObject->convertDoubleToContiguous(exec->vm());
// Reloop.
putByIndex(cell, exec, propertyName, value, shouldThrow);
return;
}
double valueAsDouble = value.asNumber();
if (valueAsDouble != valueAsDouble) {
- thisObject->convertDoubleToContiguous(exec->globalData());
+ thisObject->convertDoubleToContiguous(exec->vm());
// Reloop.
putByIndex(cell, exec, propertyName, value, shouldThrow);
return;
@@ -498,7 +499,7 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
} else if (!valueSlot)
++storage->m_numValuesInVector;
- valueSlot.set(exec->globalData(), thisObject, value);
+ valueSlot.set(exec->vm(), thisObject, value);
return;
}
@@ -525,23 +526,23 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName,
++storage->m_numValuesInVector;
}
- valueSlot.set(exec->globalData(), thisObject, value);
+ valueSlot.set(exec->vm(), thisObject, value);
return;
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
thisObject->putByIndexBeyondVectorLength(exec, propertyName, value, shouldThrow);
}
-ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData& globalData, ArrayStorage* storage)
+ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(VM& vm, ArrayStorage* storage)
{
SparseArrayValueMap* map = storage->m_sparseMap.get();
if (!map)
- map = allocateSparseIndexMap(globalData);
+ map = allocateSparseIndexMap(vm);
if (map->sparseMode())
return storage;
@@ -554,34 +555,34 @@ ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists
// This will always be a new entry in the map, so no need to check we can write,
// and attributes are default so no need to set them.
if (value)
- map->add(this, i).iterator->value.set(globalData, this, value);
+ map->add(this, i).iterator->value.set(vm, this, value);
}
- Butterfly* newButterfly = storage->butterfly()->resizeArray(globalData, structure(), 0, ArrayStorage::sizeFor(0));
- if (!newButterfly)
- CRASH();
+ Butterfly* newButterfly = storage->butterfly()->resizeArray(vm, structure(), 0, ArrayStorage::sizeFor(0));
+ RELEASE_ASSERT(newButterfly);
m_butterfly = newButterfly;
newButterfly->arrayStorage()->m_indexBias = 0;
newButterfly->arrayStorage()->setVectorLength(0);
- newButterfly->arrayStorage()->m_sparseMap.set(globalData, this, map);
+ newButterfly->arrayStorage()->m_sparseMap.set(vm, this, map);
return newButterfly->arrayStorage();
}
-void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData)
+void JSObject::enterDictionaryIndexingMode(VM& vm)
{
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:
// 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(vm, ensureArrayStorageSlow(vm));
break;
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage());
+ enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, m_butterfly->arrayStorage());
break;
default:
@@ -589,20 +590,20 @@ void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData)
}
}
-void JSObject::notifyPresenceOfIndexedAccessors(JSGlobalData& globalData)
+void JSObject::notifyPresenceOfIndexedAccessors(VM& vm)
{
if (mayInterceptIndexedAccesses())
return;
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AddIndexedAccessors));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AddIndexedAccessors));
- if (!mayBeUsedAsPrototype(globalData))
+ if (!vm.prototypeMap.isPrototype(this))
return;
- globalObject()->haveABadTime(globalData);
+ globalObject()->haveABadTime(vm);
}
-Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsigned length, size_t elementSize)
+Butterfly* JSObject::createInitialIndexedStorage(VM& vm, unsigned length, size_t elementSize)
{
ASSERT(length < MAX_ARRAY_INDEX);
IndexingType oldType = structure()->indexingType();
@@ -611,105 +612,105 @@ Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsig
ASSERT(!indexingShouldBeSparse());
unsigned vectorLength = std::max(length, BASE_VECTOR_LEN);
Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(m_butterfly,
- globalData, structure(), structure()->outOfLineCapacity(), false, 0,
+ vm, structure(), structure()->outOfLineCapacity(), false, 0,
elementSize * vectorLength);
newButterfly->setPublicLength(length);
newButterfly->setVectorLength(vectorLength);
return newButterfly;
}
-Butterfly* JSObject::createInitialUndecided(JSGlobalData& globalData, unsigned length)
+Butterfly* JSObject::createInitialUndecided(VM& vm, unsigned length)
{
- Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue));
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateUndecided);
- setButterfly(globalData, newButterfly, newStructure);
+ Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), AllocateUndecided);
+ setButterfly(vm, newButterfly, newStructure);
return newButterfly;
}
-WriteBarrier<Unknown>* JSObject::createInitialInt32(JSGlobalData& globalData, unsigned length)
+ContiguousJSValues JSObject::createInitialInt32(VM& vm, unsigned length)
{
- Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue));
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateInt32);
- setButterfly(globalData, newButterfly, newStructure);
+ Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), AllocateInt32);
+ setButterfly(vm, newButterfly, newStructure);
return newButterfly->contiguousInt32();
}
-double* JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length)
+ContiguousDoubles JSObject::createInitialDouble(VM& vm, unsigned length)
{
- Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(double));
+ Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(double));
for (unsigned i = newButterfly->vectorLength(); i--;)
newButterfly->contiguousDouble()[i] = QNaN;
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateDouble);
- setButterfly(globalData, newButterfly, newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), AllocateDouble);
+ setButterfly(vm, newButterfly, newStructure);
return newButterfly->contiguousDouble();
}
-WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length)
+ContiguousJSValues JSObject::createInitialContiguous(VM& vm, unsigned length)
{
- Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue));
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous);
- setButterfly(globalData, newButterfly, newStructure);
+ Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), AllocateContiguous);
+ setButterfly(vm, newButterfly, newStructure);
return newButterfly->contiguous();
}
-ArrayStorage* JSObject::createArrayStorage(JSGlobalData& globalData, unsigned length, unsigned vectorLength)
+ArrayStorage* JSObject::createArrayStorage(VM& vm, unsigned length, unsigned vectorLength)
{
IndexingType oldType = structure()->indexingType();
ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(m_butterfly,
- globalData, structure(), structure()->outOfLineCapacity(), false, 0,
+ vm, structure(), structure()->outOfLineCapacity(), false, 0,
ArrayStorage::sizeFor(vectorLength));
- if (!newButterfly)
- CRASH();
+ RELEASE_ASSERT(newButterfly);
+
ArrayStorage* result = newButterfly->arrayStorage();
result->setLength(length);
result->setVectorLength(vectorLength);
result->m_sparseMap.clear();
result->m_numValuesInVector = 0;
result->m_indexBias = 0;
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), structure()->suggestedArrayStorageTransition());
- setButterfly(globalData, newButterfly, newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), structure()->suggestedArrayStorageTransition());
+ setButterfly(vm, newButterfly, newStructure);
return result;
}
-ArrayStorage* JSObject::createInitialArrayStorage(JSGlobalData& globalData)
+ArrayStorage* JSObject::createInitialArrayStorage(VM& vm)
{
- return createArrayStorage(globalData, 0, BASE_VECTOR_LEN);
+ return createArrayStorage(vm, 0, BASE_VECTOR_LEN);
}
-WriteBarrier<Unknown>* JSObject::convertUndecidedToInt32(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertUndecidedToInt32(VM& vm)
{
ASSERT(hasUndecided(structure()->indexingType()));
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateInt32));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateInt32));
return m_butterfly->contiguousInt32();
}
-double* JSObject::convertUndecidedToDouble(JSGlobalData& globalData)
+ContiguousDoubles JSObject::convertUndecidedToDouble(VM& vm)
{
ASSERT(hasUndecided(structure()->indexingType()));
for (unsigned i = m_butterfly->vectorLength(); i--;)
m_butterfly->contiguousDouble()[i] = QNaN;
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble));
return m_butterfly->contiguousDouble();
}
-WriteBarrier<Unknown>* JSObject::convertUndecidedToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertUndecidedToContiguous(VM& vm)
{
ASSERT(hasUndecided(structure()->indexingType()));
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
return m_butterfly->contiguous();
}
-ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSGlobalData& globalData, unsigned neededLength)
+ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(VM& vm, unsigned neededLength)
{
unsigned publicLength = m_butterfly->publicLength();
unsigned propertyCapacity = structure()->outOfLineCapacity();
unsigned propertySize = structure()->outOfLineSize();
Butterfly* newButterfly = Butterfly::createUninitialized(
- globalData, 0, propertyCapacity, true, ArrayStorage::sizeFor(neededLength));
+ vm, 0, propertyCapacity, true, ArrayStorage::sizeFor(neededLength));
memcpy(
newButterfly->propertyStorage() - propertySize,
@@ -726,29 +727,29 @@ ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSG
return newStorage;
}
-ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength)
+ArrayStorage* JSObject::convertUndecidedToArrayStorage(VM& vm, NonPropertyTransition transition, unsigned neededLength)
{
ASSERT(hasUndecided(structure()->indexingType()));
- ArrayStorage* storage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength);
+ ArrayStorage* storage = constructConvertedArrayStorageWithoutCopyingElements(vm, neededLength);
// No need to copy elements.
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition);
- setButterfly(globalData, storage->butterfly(), newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), transition);
+ setButterfly(vm, storage->butterfly(), newStructure);
return storage;
}
-ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertUndecidedToArrayStorage(VM& vm, NonPropertyTransition transition)
{
- return convertUndecidedToArrayStorage(globalData, transition, m_butterfly->vectorLength());
+ return convertUndecidedToArrayStorage(vm, transition, m_butterfly->vectorLength());
}
-ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData)
+ArrayStorage* JSObject::convertUndecidedToArrayStorage(VM& vm)
{
- return convertUndecidedToArrayStorage(globalData, structure()->suggestedArrayStorageTransition());
+ return convertUndecidedToArrayStorage(vm, structure()->suggestedArrayStorageTransition());
}
-double* JSObject::convertInt32ToDouble(JSGlobalData& globalData)
+ContiguousDoubles JSObject::convertInt32ToDouble(VM& vm)
{
ASSERT(hasInt32(structure()->indexingType()));
@@ -764,23 +765,23 @@ double* JSObject::convertInt32ToDouble(JSGlobalData& globalData)
*currentAsDouble = v.asInt32();
}
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateDouble));
return m_butterfly->contiguousDouble();
}
-WriteBarrier<Unknown>* JSObject::convertInt32ToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertInt32ToContiguous(VM& vm)
{
ASSERT(hasInt32(structure()->indexingType()));
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
return m_butterfly->contiguous();
}
-ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength)
+ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm, NonPropertyTransition transition, unsigned neededLength)
{
ASSERT(hasInt32(structure()->indexingType()));
- ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength);
+ ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, neededLength);
for (unsigned i = m_butterfly->publicLength(); i--;) {
JSValue v = m_butterfly->contiguous()[i].get();
if (!v)
@@ -789,22 +790,23 @@ ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, Non
newStorage->m_numValuesInVector++;
}
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition);
- setButterfly(globalData, newStorage->butterfly(), newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), transition);
+ setButterfly(vm, newStorage->butterfly(), newStructure);
return newStorage;
}
-ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm, NonPropertyTransition transition)
{
- return convertInt32ToArrayStorage(globalData, transition, m_butterfly->vectorLength());
+ return convertInt32ToArrayStorage(vm, transition, m_butterfly->vectorLength());
}
-ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData)
+ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm)
{
- return convertInt32ToArrayStorage(globalData, structure()->suggestedArrayStorageTransition());
+ return convertInt32ToArrayStorage(vm, structure()->suggestedArrayStorageTransition());
}
-WriteBarrier<Unknown>* JSObject::convertDoubleToContiguous(JSGlobalData& globalData)
+template<JSObject::DoubleToContiguousMode mode>
+ContiguousJSValues JSObject::genericConvertDoubleToContiguous(VM& vm)
{
ASSERT(hasDouble(structure()->indexingType()));
@@ -816,18 +818,38 @@ WriteBarrier<Unknown>* JSObject::convertDoubleToContiguous(JSGlobalData& globalD
currentAsValue->clear();
continue;
}
- currentAsValue->setWithoutWriteBarrier(JSValue(JSValue::EncodeAsDouble, value));
+ JSValue v;
+ switch (mode) {
+ case EncodeValueAsDouble:
+ v = JSValue(JSValue::EncodeAsDouble, value);
+ break;
+ case RageConvertDoubleToValue:
+ v = jsNumber(value);
+ break;
+ }
+ ASSERT(v.isNumber());
+ currentAsValue->setWithoutWriteBarrier(v);
}
- setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous));
+ setStructure(vm, Structure::nonPropertyTransition(vm, structure(), AllocateContiguous));
return m_butterfly->contiguous();
}
-ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength)
+ContiguousJSValues JSObject::convertDoubleToContiguous(VM& vm)
+{
+ return genericConvertDoubleToContiguous<EncodeValueAsDouble>(vm);
+}
+
+ContiguousJSValues JSObject::rageConvertDoubleToContiguous(VM& vm)
+{
+ return genericConvertDoubleToContiguous<RageConvertDoubleToValue>(vm);
+}
+
+ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm, NonPropertyTransition transition, unsigned neededLength)
{
ASSERT(hasDouble(structure()->indexingType()));
- ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength);
+ ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, neededLength);
for (unsigned i = m_butterfly->publicLength(); i--;) {
double value = m_butterfly->contiguousDouble()[i];
if (value != value)
@@ -836,26 +858,26 @@ ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, No
newStorage->m_numValuesInVector++;
}
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition);
- setButterfly(globalData, newStorage->butterfly(), newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), transition);
+ setButterfly(vm, newStorage->butterfly(), newStructure);
return newStorage;
}
-ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm, NonPropertyTransition transition)
{
- return convertDoubleToArrayStorage(globalData, transition, m_butterfly->vectorLength());
+ return convertDoubleToArrayStorage(vm, transition, m_butterfly->vectorLength());
}
-ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData)
+ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm)
{
- return convertDoubleToArrayStorage(globalData, structure()->suggestedArrayStorageTransition());
+ return convertDoubleToArrayStorage(vm, structure()->suggestedArrayStorageTransition());
}
-ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength)
+ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm, NonPropertyTransition transition, unsigned neededLength)
{
ASSERT(hasContiguous(structure()->indexingType()));
- ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength);
+ ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(vm, neededLength);
for (unsigned i = m_butterfly->publicLength(); i--;) {
JSValue v = m_butterfly->contiguous()[i].get();
if (!v)
@@ -864,200 +886,220 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData
newStorage->m_numValuesInVector++;
}
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition);
- setButterfly(globalData, newStorage->butterfly(), newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), transition);
+ setButterfly(vm, newStorage->butterfly(), newStructure);
return newStorage;
}
-ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm, NonPropertyTransition transition)
{
- return convertContiguousToArrayStorage(globalData, transition, m_butterfly->vectorLength());
+ return convertContiguousToArrayStorage(vm, transition, m_butterfly->vectorLength());
}
-ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData)
+ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm)
{
- return convertContiguousToArrayStorage(globalData, structure()->suggestedArrayStorageTransition());
+ return convertContiguousToArrayStorage(vm, structure()->suggestedArrayStorageTransition());
}
-void JSObject::convertUndecidedForValue(JSGlobalData& globalData, JSValue value)
+void JSObject::convertUndecidedForValue(VM& vm, JSValue value)
{
if (value.isInt32()) {
- convertUndecidedToInt32(globalData);
+ convertUndecidedToInt32(vm);
return;
}
if (value.isDouble()) {
- convertUndecidedToDouble(globalData);
+ convertUndecidedToDouble(vm);
return;
}
- convertUndecidedToContiguous(globalData);
+ convertUndecidedToContiguous(vm);
}
-void JSObject::convertInt32ForValue(JSGlobalData& globalData, JSValue value)
+void JSObject::convertInt32ForValue(VM& vm, JSValue value)
{
ASSERT(!value.isInt32());
if (value.isDouble()) {
- convertInt32ToDouble(globalData);
+ convertInt32ToDouble(vm);
return;
}
- convertInt32ToContiguous(globalData);
+ convertInt32ToContiguous(vm);
}
-void JSObject::setIndexQuicklyToUndecided(JSGlobalData& globalData, unsigned index, JSValue value)
+void JSObject::setIndexQuicklyToUndecided(VM& vm, unsigned index, JSValue value)
{
ASSERT(index < m_butterfly->publicLength());
ASSERT(index < m_butterfly->vectorLength());
- convertUndecidedForValue(globalData, value);
- setIndexQuickly(globalData, index, value);
+ convertUndecidedForValue(vm, value);
+ setIndexQuickly(vm, index, value);
}
-void JSObject::convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value)
+void JSObject::convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(VM& vm, unsigned index, JSValue value)
{
ASSERT(!value.isInt32());
- convertInt32ForValue(globalData, value);
- setIndexQuickly(globalData, index, value);
+ convertInt32ForValue(vm, value);
+ setIndexQuickly(vm, index, value);
}
-void JSObject::convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value)
+void JSObject::convertDoubleToContiguousWhilePerformingSetIndex(VM& vm, unsigned index, JSValue value)
{
ASSERT(!value.isNumber() || value.asNumber() != value.asNumber());
- convertDoubleToContiguous(globalData);
- setIndexQuickly(globalData, index, value);
+ convertDoubleToContiguous(vm);
+ setIndexQuickly(vm, index, value);
}
-WriteBarrier<Unknown>* JSObject::ensureInt32Slow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::ensureInt32Slow(VM& vm)
{
+ ASSERT(inherits(&s_info));
+
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES:
if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
- return 0;
- return createInitialInt32(globalData, 0);
+ return ContiguousJSValues();
+ return createInitialInt32(vm, 0);
case ALL_UNDECIDED_INDEXING_TYPES:
- return convertUndecidedToInt32(globalData);
+ return convertUndecidedToInt32(vm);
case ALL_DOUBLE_INDEXING_TYPES:
case ALL_CONTIGUOUS_INDEXING_TYPES:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return 0;
+ return ContiguousJSValues();
default:
CRASH();
- return 0;
+ return ContiguousJSValues();
}
}
-double* JSObject::ensureDoubleSlow(JSGlobalData& globalData)
+ContiguousDoubles JSObject::ensureDoubleSlow(VM& vm)
{
+ ASSERT(inherits(&s_info));
+
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES:
if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
- return 0;
- return createInitialDouble(globalData, 0);
+ return ContiguousDoubles();
+ return createInitialDouble(vm, 0);
case ALL_UNDECIDED_INDEXING_TYPES:
- return convertUndecidedToDouble(globalData);
+ return convertUndecidedToDouble(vm);
case ALL_INT32_INDEXING_TYPES:
- return convertInt32ToDouble(globalData);
+ return convertInt32ToDouble(vm);
case ALL_CONTIGUOUS_INDEXING_TYPES:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return 0;
+ return ContiguousDoubles();
default:
CRASH();
- return 0;
+ return ContiguousDoubles();
}
}
-WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::ensureContiguousSlow(VM& vm, DoubleToContiguousMode mode)
{
+ ASSERT(inherits(&s_info));
+
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES:
if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
- return 0;
- return createInitialContiguous(globalData, 0);
+ return ContiguousJSValues();
+ return createInitialContiguous(vm, 0);
case ALL_UNDECIDED_INDEXING_TYPES:
- return convertUndecidedToContiguous(globalData);
+ return convertUndecidedToContiguous(vm);
case ALL_INT32_INDEXING_TYPES:
- return convertInt32ToContiguous(globalData);
+ return convertInt32ToContiguous(vm);
case ALL_DOUBLE_INDEXING_TYPES:
- return convertDoubleToContiguous(globalData);
+ if (mode == RageConvertDoubleToValue)
+ return rageConvertDoubleToContiguous(vm);
+ return convertDoubleToContiguous(vm);
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return 0;
+ return ContiguousJSValues();
default:
CRASH();
- return 0;
+ return ContiguousJSValues();
}
}
-ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::ensureContiguousSlow(VM& vm)
{
+ return ensureContiguousSlow(vm, EncodeValueAsDouble);
+}
+
+ContiguousJSValues JSObject::rageEnsureContiguousSlow(VM& vm)
+{
+ return ensureContiguousSlow(vm, RageConvertDoubleToValue);
+}
+
+ArrayStorage* JSObject::ensureArrayStorageSlow(VM& vm)
+{
+ ASSERT(inherits(&s_info));
+
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES:
if (UNLIKELY(indexingShouldBeSparse()))
- return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData);
- return createInitialArrayStorage(globalData);
+ return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(vm);
+ return createInitialArrayStorage(vm);
case ALL_UNDECIDED_INDEXING_TYPES:
ASSERT(!indexingShouldBeSparse());
ASSERT(!structure()->needsSlowPutIndexing());
- return convertUndecidedToArrayStorage(globalData);
+ return convertUndecidedToArrayStorage(vm);
case ALL_INT32_INDEXING_TYPES:
ASSERT(!indexingShouldBeSparse());
ASSERT(!structure()->needsSlowPutIndexing());
- return convertInt32ToArrayStorage(globalData);
+ return convertInt32ToArrayStorage(vm);
case ALL_DOUBLE_INDEXING_TYPES:
ASSERT(!indexingShouldBeSparse());
ASSERT(!structure()->needsSlowPutIndexing());
- return convertDoubleToArrayStorage(globalData);
+ return convertDoubleToArrayStorage(vm);
case ALL_CONTIGUOUS_INDEXING_TYPES:
ASSERT(!indexingShouldBeSparse());
ASSERT(!structure()->needsSlowPutIndexing());
- return convertContiguousToArrayStorage(globalData);
+ return convertContiguousToArrayStorage(vm);
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return 0;
}
}
-ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData& globalData)
+ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(VM& vm)
{
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES: {
- createArrayStorage(globalData, 0, 0);
- SparseArrayValueMap* map = allocateSparseIndexMap(globalData);
+ createArrayStorage(vm, 0, 0);
+ SparseArrayValueMap* map = allocateSparseIndexMap(vm);
map->setSparseMode();
return arrayStorage();
}
case ALL_UNDECIDED_INDEXING_TYPES:
- return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertUndecidedToArrayStorage(globalData));
+ return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, convertUndecidedToArrayStorage(vm));
case ALL_INT32_INDEXING_TYPES:
- return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertInt32ToArrayStorage(globalData));
+ return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, convertInt32ToArrayStorage(vm));
case ALL_DOUBLE_INDEXING_TYPES:
- return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertDoubleToArrayStorage(globalData));
+ return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, convertDoubleToArrayStorage(vm));
case ALL_CONTIGUOUS_INDEXING_TYPES:
- return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData));
+ return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, convertContiguousToArrayStorage(vm));
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage());
+ return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(vm, m_butterfly->arrayStorage());
default:
CRASH();
@@ -1065,29 +1107,29 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J
}
}
-void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData)
+void JSObject::switchToSlowPutArrayStorage(VM& vm)
{
switch (structure()->indexingType()) {
case ALL_UNDECIDED_INDEXING_TYPES:
- convertUndecidedToArrayStorage(globalData, AllocateSlowPutArrayStorage);
+ convertUndecidedToArrayStorage(vm, AllocateSlowPutArrayStorage);
break;
case ALL_INT32_INDEXING_TYPES:
- convertInt32ToArrayStorage(globalData, AllocateSlowPutArrayStorage);
+ convertInt32ToArrayStorage(vm, AllocateSlowPutArrayStorage);
break;
case ALL_DOUBLE_INDEXING_TYPES:
- convertDoubleToArrayStorage(globalData, AllocateSlowPutArrayStorage);
+ convertDoubleToArrayStorage(vm, AllocateSlowPutArrayStorage);
break;
case ALL_CONTIGUOUS_INDEXING_TYPES:
- convertContiguousToArrayStorage(globalData, AllocateSlowPutArrayStorage);
+ convertContiguousToArrayStorage(vm, AllocateSlowPutArrayStorage);
break;
case NonArrayWithArrayStorage:
case ArrayWithArrayStorage: {
- Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), SwitchToSlowPutArrayStorage);
- setStructure(globalData, newStructure);
+ Structure* newStructure = Structure::nonPropertyTransition(vm, structure(), SwitchToSlowPutArrayStorage);
+ setStructure(vm, newStructure);
break;
}
@@ -1101,23 +1143,23 @@ void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
PutPropertySlot slot;
- object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getCallableObject(value));
+ object->putDirectInternal<PutModeDefineOwnProperty>(exec->vm(), propertyName, value, attributes, slot, getCallableObject(value));
}
-void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
+void JSObject::setPrototype(VM& vm, JSValue prototype)
{
ASSERT(prototype);
if (prototype.isObject())
- asObject(prototype)->notifyUsedAsPrototype(globalData);
+ vm.prototypeMap.addPrototype(asObject(prototype));
- Structure* newStructure = Structure::changePrototypeTransition(globalData, structure(), prototype);
- setStructure(globalData, newStructure);
+ Structure* newStructure = Structure::changePrototypeTransition(vm, structure(), prototype);
+ setStructure(vm, newStructure);
if (!newStructure->anyObjectInChainMayInterceptIndexedAccesses())
return;
- if (mayBeUsedAsPrototype(globalData)) {
- newStructure->globalObject()->haveABadTime(globalData);
+ if (vm.prototypeMap.isPrototype(this)) {
+ newStructure->globalObject()->haveABadTime(vm);
return;
}
@@ -1127,10 +1169,10 @@ void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
if (shouldUseSlowPut(structure()->indexingType()))
return;
- switchToSlowPutArrayStorage(globalData);
+ switchToSlowPutArrayStorage(vm);
}
-bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
+bool JSObject::setPrototypeWithCycleCheck(VM& vm, JSValue prototype)
{
JSValue checkFor = this;
if (this->isGlobalObject())
@@ -1142,33 +1184,10 @@ bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prot
return false;
nextPrototype = asObject(nextPrototype)->prototype();
}
- setPrototype(globalData, prototype);
+ setPrototype(vm, prototype);
return true;
}
-void JSObject::resetInheritorID(JSGlobalData& globalData)
-{
- PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey);
- if (!isValidOffset(offset))
- return;
-
- putDirectOffset(globalData, offset, jsUndefined());
-}
-
-Structure* JSObject::inheritorID(JSGlobalData& globalData)
-{
- if (WriteBarrierBase<Unknown>* location = getDirectLocation(globalData, globalData.m_inheritorIDKey)) {
- JSValue value = location->get();
- if (value.isCell()) {
- Structure* inheritorID = jsCast<Structure*>(value);
- ASSERT(inheritorID->isEmpty());
- return inheritorID;
- }
- ASSERT(value.isUndefined());
- }
- return createInheritorID(globalData);
-}
-
bool JSObject::allowsAccessFrom(ExecState* exec)
{
JSGlobalObject* globalObject = this->globalObject();
@@ -1185,21 +1204,21 @@ void JSObject::putDirectAccessor(ExecState* exec, PropertyName propertyName, JSV
return;
}
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
PutPropertySlot slot;
- putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value));
+ putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
// if we override an existing non-getter or non-setter.
if (slot.type() != PutPropertySlot::NewProperty)
- setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes));
+ setStructure(vm, Structure::attributeChangeTransition(vm, structure(), propertyName, attributes));
if (attributes & ReadOnly)
structure()->setContainsReadOnlyProperties();
- structure()->setHasGetterSetterProperties(propertyName == globalData.propertyNames->underscoreProto);
+ structure()->setHasGetterSetterProperties(propertyName == vm.propertyNames->underscoreProto);
}
bool JSObject::hasProperty(ExecState* exec, PropertyName propertyName) const
@@ -1228,19 +1247,22 @@ bool JSObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName proper
unsigned attributes;
JSCell* specificValue;
- if (isValidOffset(thisObject->structure()->get(exec->globalData(), propertyName, attributes, specificValue))) {
- if (attributes & DontDelete && !exec->globalData().isInDefineOwnProperty())
+ if (isValidOffset(thisObject->structure()->get(exec->vm(), propertyName, attributes, specificValue))) {
+ if (attributes & DontDelete && !exec->vm().isInDefineOwnProperty())
return false;
- thisObject->removeDirect(exec->globalData(), propertyName);
+ thisObject->removeDirect(exec->vm(), propertyName);
return true;
}
// Look in the static hashtable of properties
const HashEntry* entry = thisObject->findPropertyHashEntry(exec, propertyName);
- if (entry && entry->attributes() & DontDelete && !exec->globalData().isInDefineOwnProperty())
- return false; // this builtin property can't be deleted
+ if (entry) {
+ if (entry->attributes() & DontDelete && !exec->vm().isInDefineOwnProperty())
+ return false; // this builtin property can't be deleted
+
+ putEntry(exec, entry, propertyName, jsUndefined(), thisObject);
+ }
- // FIXME: Should the code here actually do some deletion?
return true;
}
@@ -1301,7 +1323,7 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
@@ -1378,7 +1400,7 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value)
return defaultHasInstance(exec, value, get(exec, exec->propertyNames().prototype));
if (info.implementsHasInstance())
return methodTable()->customHasInstance(this, exec, value);
- throwError(exec, createInvalidParamError(exec, "instanceof" , this));
+ throwError(exec, createInvalidParameterError(exec, "instanceof" , this));
return false;
}
@@ -1411,7 +1433,7 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
bool JSObject::getPropertySpecificValue(ExecState* exec, PropertyName propertyName, JSCell*& specificValue) const
{
unsigned attributes;
- if (isValidOffset(structure()->get(exec->globalData(), propertyName, attributes, specificValue)))
+ if (isValidOffset(structure()->get(exec->vm(), propertyName, attributes, specificValue)))
return true;
// This could be a function within the static table? - should probably
@@ -1488,13 +1510,13 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa
}
if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
- Vector<unsigned> keys;
- keys.reserveCapacity(map->size());
+ Vector<unsigned, 0, UnsafeVectorOverflow> keys;
+ keys.reserveInitialCapacity(map->size());
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
if (mode == IncludeDontEnumProperties || !(it->value.attributes & DontEnum))
- keys.append(static_cast<unsigned>(it->key));
+ keys.uncheckedAppend(static_cast<unsigned>(it->key));
}
std::sort(keys.begin(), keys.end());
@@ -1505,7 +1527,7 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
object->methodTable()->getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
@@ -1516,7 +1538,7 @@ void JSObject::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, Pr
getClassPropertyNames(exec, object->classInfo(), propertyNames, mode, object->staticFunctionsReified());
bool canCachePropertiesFromStructure = !propertyNames.size();
- object->structure()->getPropertyNamesFromStructure(exec->globalData(), propertyNames, mode);
+ object->structure()->getPropertyNamesFromStructure(exec->vm(), propertyNames, mode);
if (canCachePropertiesFromStructure)
propertyNames.setNumCacheableSlotsForObject(object, propertyNames.size());
@@ -1543,27 +1565,27 @@ JSObject* JSObject::toThisObject(JSCell* cell, ExecState*)
return jsCast<JSObject*>(cell);
}
-void JSObject::seal(JSGlobalData& globalData)
+void JSObject::seal(VM& vm)
{
- if (isSealed(globalData))
+ if (isSealed(vm))
return;
- preventExtensions(globalData);
- setStructure(globalData, Structure::sealTransition(globalData, structure()));
+ preventExtensions(vm);
+ setStructure(vm, Structure::sealTransition(vm, structure()));
}
-void JSObject::freeze(JSGlobalData& globalData)
+void JSObject::freeze(VM& vm)
{
- if (isFrozen(globalData))
+ if (isFrozen(vm))
return;
- preventExtensions(globalData);
- setStructure(globalData, Structure::freezeTransition(globalData, structure()));
+ preventExtensions(vm);
+ setStructure(vm, Structure::freezeTransition(vm, structure()));
}
-void JSObject::preventExtensions(JSGlobalData& globalData)
+void JSObject::preventExtensions(VM& vm)
{
- enterDictionaryIndexingMode(globalData);
+ enterDictionaryIndexingMode(vm);
if (isExtensible())
- setStructure(globalData, Structure::preventExtensionsTransition(globalData, structure()));
+ setStructure(vm, Structure::preventExtensionsTransition(vm, structure()));
}
// This presently will flatten to an uncachable dictionary; this is suitable
@@ -1571,7 +1593,7 @@ void JSObject::preventExtensions(JSGlobalData& globalData)
void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
{
ASSERT(!staticFunctionsReified());
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// If this object's ClassInfo has no static properties, then nothing to reify!
// We can safely set the flag to avoid the expensive check again in the future.
@@ -1581,46 +1603,46 @@ void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
}
if (!structure()->isUncacheableDictionary())
- setStructure(globalData, Structure::toUncacheableDictionaryTransition(globalData, structure()));
+ setStructure(vm, Structure::toUncacheableDictionaryTransition(vm, structure()));
for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
const HashTable* hashTable = info->propHashTable(globalObject()->globalExec());
if (!hashTable)
continue;
PropertySlot slot;
- for (HashTable::ConstIterator iter = hashTable->begin(globalData); iter != hashTable->end(globalData); ++iter) {
+ for (HashTable::ConstIterator iter = hashTable->begin(vm); iter != hashTable->end(vm); ++iter) {
if (iter->attributes() & Function)
- setUpStaticFunctionSlot(globalObject()->globalExec(), *iter, this, Identifier(&globalData, iter->key()), slot);
+ setUpStaticFunctionSlot(globalObject()->globalExec(), *iter, this, Identifier(&vm, iter->key()), slot);
}
}
structure()->setStaticFunctionsReified();
}
-bool JSObject::removeDirect(JSGlobalData& globalData, PropertyName propertyName)
+bool JSObject::removeDirect(VM& vm, PropertyName propertyName)
{
- if (!isValidOffset(structure()->get(globalData, propertyName)))
+ if (!isValidOffset(structure()->get(vm, propertyName)))
return false;
PropertyOffset offset;
if (structure()->isUncacheableDictionary()) {
- offset = structure()->removePropertyWithoutTransition(globalData, propertyName);
+ offset = structure()->removePropertyWithoutTransition(vm, propertyName);
if (offset == invalidOffset)
return false;
- putUndefinedAtDirectOffset(offset);
+ putDirectUndefined(offset);
return true;
}
- setStructure(globalData, Structure::removePropertyTransition(globalData, structure(), propertyName, offset));
+ setStructure(vm, Structure::removePropertyTransition(vm, structure(), propertyName, offset));
if (offset == invalidOffset)
return false;
- putUndefinedAtDirectOffset(offset);
+ putDirectUndefined(offset);
return true;
}
NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, PropertyOffset offset)
{
- if (JSObject* getterFunction = asGetterSetter(getDirectOffset(offset))->getter()) {
+ if (JSObject* getterFunction = asGetterSetter(getDirect(offset))->getter()) {
if (!structure()->isDictionary())
slot.setCacheableGetterSlot(this, getterFunction, offset);
else
@@ -1629,49 +1651,13 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, PropertyO
slot.setUndefined();
}
-void JSObject::notifyUsedAsPrototype(JSGlobalData& globalData)
-{
- PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey);
- if (isValidOffset(offset))
- return;
-
- PutPropertySlot slot;
- putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, jsUndefined(), DontEnum, slot, 0);
-
- // Note that this method makes the somewhat odd decision to not check if this
- // object currently has indexed accessors. We could do that check here, and if
- // indexed accessors were found, we could tell the global object to have a bad
- // time. But we avoid this, to allow the following to be always fast:
- //
- // 1) Create an object.
- // 2) Give it a setter or read-only property that happens to have a numeric name.
- // 3) Allocate objects that use this object as a prototype.
- //
- // This avoids anyone having a bad time. Even if the instance objects end up
- // having indexed storage, the creation of indexed storage leads to a prototype
- // chain walk that detects the presence of indexed setters and then does the
- // right thing. As a result, having a bad time only happens if you add an
- // indexed setter (or getter, or read-only field) to an object that is already
- // used as a prototype.
-}
-
-Structure* JSObject::createInheritorID(JSGlobalData& globalData)
-{
- Structure* inheritorID = createEmptyObjectStructure(globalData, globalObject(), this);
- ASSERT(inheritorID->isEmpty());
-
- PutPropertySlot slot;
- putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, inheritorID, DontEnum, slot, 0);
- return inheritorID;
-}
-
void JSObject::putIndexedDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, PropertyDescriptor& descriptor, PropertyDescriptor& oldDescriptor)
{
if (descriptor.isDataDescriptor()) {
if (descriptor.value())
- entryInMap->set(exec->globalData(), this, descriptor.value());
+ entryInMap->set(exec->vm(), this, descriptor.value());
else if (oldDescriptor.isAccessorDescriptor())
- entryInMap->set(exec->globalData(), this, jsUndefined());
+ entryInMap->set(exec->vm(), this, jsUndefined());
entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~Accessor;
return;
}
@@ -1690,11 +1676,11 @@ void JSObject::putIndexedDescriptor(ExecState* exec, SparseArrayEntry* entryInMa
GetterSetter* accessor = GetterSetter::create(exec);
if (getter)
- accessor->setGetter(exec->globalData(), getter);
+ accessor->setGetter(exec->vm(), getter);
if (setter)
- accessor->setSetter(exec->globalData(), setter);
+ accessor->setSetter(exec->vm(), setter);
- entryInMap->set(exec->globalData(), this, accessor);
+ entryInMap->set(exec->vm(), this, accessor);
entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~ReadOnly;
return;
}
@@ -1718,14 +1704,14 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, Propert
return putDirectIndex(exec, index, descriptor.value(), 0, throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
}
- ensureArrayStorageExistsAndEnterDictionaryIndexingMode(exec->globalData());
+ ensureArrayStorageExistsAndEnterDictionaryIndexingMode(exec->vm());
}
if (descriptor.attributes() & (ReadOnly | Accessor))
- notifyPresenceOfIndexedAccessors(exec->globalData());
+ notifyPresenceOfIndexedAccessors(exec->vm());
SparseArrayValueMap* map = m_butterfly->arrayStorage()->m_sparseMap.get();
- ASSERT(map);
+ RELEASE_ASSERT(map);
// 1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P.
SparseArrayValueMap::AddResult result = map->add(this, index);
@@ -1825,10 +1811,10 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, Propert
return true;
}
-SparseArrayValueMap* JSObject::allocateSparseIndexMap(JSGlobalData& globalData)
+SparseArrayValueMap* JSObject::allocateSparseIndexMap(VM& vm)
{
- SparseArrayValueMap* result = SparseArrayValueMap::create(globalData);
- arrayStorage()->m_sparseMap.set(globalData, this, result);
+ SparseArrayValueMap* result = SparseArrayValueMap::create(vm);
+ arrayStorage()->m_sparseMap.set(vm, this, result);
return result;
}
@@ -1882,23 +1868,23 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
// or equal to the vector length.
ASSERT(i >= m_butterfly->vectorLength());
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
if (i >= MAX_ARRAY_INDEX - 1
|| (i >= MIN_SPARSE_ARRAY_INDEX
&& !isDenseEnoughForVector(i, countElements<indexingShape>(m_butterfly)))) {
ASSERT(i <= MAX_ARRAY_INDEX);
- ensureArrayStorageSlow(globalData);
- SparseArrayValueMap* map = allocateSparseIndexMap(globalData);
+ ensureArrayStorageSlow(vm);
+ SparseArrayValueMap* map = allocateSparseIndexMap(vm);
map->putEntry(exec, this, i, value, false);
ASSERT(i >= arrayStorage()->length());
arrayStorage()->setLength(i + 1);
return;
}
- ensureLength(globalData, i + 1);
+ ensureLength(vm, i + 1);
- ASSERT(i < m_butterfly->vectorLength());
+ RELEASE_ASSERT(i < m_butterfly->vectorLength());
switch (indexingShape) {
case Int32Shape:
ASSERT(value.isInt32());
@@ -1914,7 +1900,7 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
}
case ContiguousShape:
- m_butterfly->contiguous()[i].set(globalData, this, value);
+ m_butterfly->contiguous()[i].set(vm, this, value);
break;
default:
@@ -1924,7 +1910,7 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, bool shouldThrow, ArrayStorage* storage)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// i should be a valid array index that is outside of the current vector.
ASSERT(i <= MAX_ARRAY_INDEX);
@@ -1942,15 +1928,15 @@ void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
storage->setLength(i + 1);
// Check that it is sensible to still be using a vector, and then try to grow the vector.
- if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) {
+ if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(vm, i + 1))) {
// success! - reread m_storage since it has likely been reallocated, and store to the vector.
storage = arrayStorage();
- storage->m_vector[i].set(globalData, this, value);
+ storage->m_vector[i].set(vm, this, value);
++storage->m_numValuesInVector;
return;
}
// We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
- map = allocateSparseIndexMap(exec->globalData());
+ map = allocateSparseIndexMap(exec->vm());
map->putEntry(exec, this, i, value, shouldThrow);
return;
}
@@ -1971,7 +1957,7 @@ void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
// We are currently using a map - check whether we still want to be doing so.
// We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
- if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) {
+ if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->vm(), length)) {
map->putEntry(exec, this, i, value, shouldThrow);
return;
}
@@ -1984,19 +1970,19 @@ void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
WriteBarrier<Unknown>* vector = storage->m_vector;
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
- vector[it->key].set(globalData, this, it->value.getNonSparseMode());
+ vector[it->key].set(vm, this, it->value.getNonSparseMode());
deallocateSparseIndexMap();
// Store the new property into the vector.
WriteBarrier<Unknown>& valueSlot = vector[i];
if (!valueSlot)
++storage->m_numValuesInVector;
- valueSlot.set(globalData, this, value);
+ valueSlot.set(vm, this, value);
}
void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// i should be a valid array index that is outside of the current vector.
ASSERT(i <= MAX_ARRAY_INDEX);
@@ -2006,22 +1992,22 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue
if (indexingShouldBeSparse()) {
putByIndexBeyondVectorLengthWithArrayStorage(
exec, i, value, shouldThrow,
- ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData));
+ ensureArrayStorageExistsAndEnterDictionaryIndexingMode(vm));
break;
}
if (i >= MIN_SPARSE_ARRAY_INDEX) {
putByIndexBeyondVectorLengthWithArrayStorage(
- exec, i, value, shouldThrow, createArrayStorage(globalData, 0, 0));
+ exec, i, value, shouldThrow, createArrayStorage(vm, 0, 0));
break;
}
if (structure()->needsSlowPutIndexing()) {
- ArrayStorage* storage = createArrayStorage(globalData, i + 1, getNewVectorLength(0, 0, i + 1));
- storage->m_vector[i].set(globalData, this, value);
+ ArrayStorage* storage = createArrayStorage(vm, i + 1, getNewVectorLength(0, 0, i + 1));
+ storage->m_vector[i].set(vm, this, value);
storage->m_numValuesInVector++;
break;
}
- createInitialContiguous(globalData, i + 1)[i].set(globalData, this, value);
+ createInitialContiguous(vm, i + 1)[i].set(vm, this, value);
break;
}
@@ -2060,13 +2046,13 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue
break;
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode, ArrayStorage* storage)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// i should be a valid array index that is outside of the current vector.
ASSERT(hasArrayStorage(structure()->indexingType()));
@@ -2089,15 +2075,15 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
if (LIKELY(
!attributes
&& (isDenseEnoughForVector(i, storage->m_numValuesInVector))
- && increaseVectorLength(globalData, i + 1))) {
+ && increaseVectorLength(vm, i + 1))) {
// success! - reread m_storage since it has likely been reallocated, and store to the vector.
storage = arrayStorage();
- storage->m_vector[i].set(globalData, this, value);
+ storage->m_vector[i].set(vm, this, value);
++storage->m_numValuesInVector;
return true;
}
// We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
- map = allocateSparseIndexMap(exec->globalData());
+ map = allocateSparseIndexMap(exec->vm());
return map->putDirect(exec, this, i, value, attributes, mode);
}
@@ -2118,7 +2104,7 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
// We are currently using a map - check whether we still want to be doing so.
// We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
- if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length))
+ if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->vm(), length))
return map->putDirect(exec, this, i, value, attributes, mode);
// Reread m_storage after increaseVectorLength, update m_numValuesInVector.
@@ -2129,51 +2115,51 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
WriteBarrier<Unknown>* vector = storage->m_vector;
SparseArrayValueMap::const_iterator end = map->end();
for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
- vector[it->key].set(globalData, this, it->value.getNonSparseMode());
+ vector[it->key].set(vm, this, it->value.getNonSparseMode());
deallocateSparseIndexMap();
// Store the new property into the vector.
WriteBarrier<Unknown>& valueSlot = vector[i];
if (!valueSlot)
++storage->m_numValuesInVector;
- valueSlot.set(globalData, this, value);
+ valueSlot.set(vm, this, value);
return true;
}
bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
// i should be a valid array index that is outside of the current vector.
ASSERT(i <= MAX_ARRAY_INDEX);
if (attributes & (ReadOnly | Accessor))
- notifyPresenceOfIndexedAccessors(globalData);
+ notifyPresenceOfIndexedAccessors(vm);
switch (structure()->indexingType()) {
case ALL_BLANK_INDEXING_TYPES: {
if (indexingShouldBeSparse() || attributes) {
return putDirectIndexBeyondVectorLengthWithArrayStorage(
exec, i, value, attributes, mode,
- ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData));
+ ensureArrayStorageExistsAndEnterDictionaryIndexingMode(vm));
}
if (i >= MIN_SPARSE_ARRAY_INDEX) {
return putDirectIndexBeyondVectorLengthWithArrayStorage(
- exec, i, value, attributes, mode, createArrayStorage(globalData, 0, 0));
+ exec, i, value, attributes, mode, createArrayStorage(vm, 0, 0));
}
if (structure()->needsSlowPutIndexing()) {
- ArrayStorage* storage = createArrayStorage(globalData, i + 1, getNewVectorLength(0, 0, i + 1));
- storage->m_vector[i].set(globalData, this, value);
+ ArrayStorage* storage = createArrayStorage(vm, i + 1, getNewVectorLength(0, 0, i + 1));
+ storage->m_vector[i].set(vm, this, value);
storage->m_numValuesInVector++;
return true;
}
- createInitialContiguous(globalData, i + 1)[i].set(globalData, this, value);
+ createInitialContiguous(vm, i + 1)[i].set(vm, this, value);
return true;
}
case ALL_UNDECIDED_INDEXING_TYPES: {
- convertUndecidedForValue(exec->globalData(), value);
+ convertUndecidedForValue(exec->vm(), value);
// Reloop.
return putDirectIndex(exec, i, value, attributes, mode);
}
@@ -2181,10 +2167,10 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV
case ALL_INT32_INDEXING_TYPES: {
if (attributes & (ReadOnly | Accessor)) {
return putDirectIndexBeyondVectorLengthWithArrayStorage(
- exec, i, value, attributes, mode, convertInt32ToArrayStorage(globalData));
+ exec, i, value, attributes, mode, convertInt32ToArrayStorage(vm));
}
if (!value.isInt32()) {
- convertInt32ForValue(globalData, value);
+ convertInt32ForValue(vm, value);
return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
}
putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value);
@@ -2194,15 +2180,15 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV
case ALL_DOUBLE_INDEXING_TYPES: {
if (attributes & (ReadOnly | Accessor)) {
return putDirectIndexBeyondVectorLengthWithArrayStorage(
- exec, i, value, attributes, mode, convertDoubleToArrayStorage(globalData));
+ exec, i, value, attributes, mode, convertDoubleToArrayStorage(vm));
}
if (!value.isNumber()) {
- convertDoubleToContiguous(globalData);
+ convertDoubleToContiguous(vm);
return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
}
double valueAsDouble = value.asNumber();
if (valueAsDouble != valueAsDouble) {
- convertDoubleToContiguous(globalData);
+ convertDoubleToContiguous(vm);
return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
}
putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value);
@@ -2212,7 +2198,7 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV
case ALL_CONTIGUOUS_INDEXING_TYPES: {
if (attributes & (ReadOnly | Accessor)) {
return putDirectIndexBeyondVectorLengthWithArrayStorage(
- exec, i, value, attributes, mode, convertContiguousToArrayStorage(globalData));
+ exec, i, value, attributes, mode, convertContiguousToArrayStorage(vm));
}
putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, i, value);
return true;
@@ -2222,11 +2208,21 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV
return putDirectIndexBeyondVectorLengthWithArrayStorage(exec, i, value, attributes, mode, arrayStorage());
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
+void JSObject::putDirectNativeFunction(ExecState* exec, JSGlobalObject* globalObject, const PropertyName& propertyName, unsigned functionLength, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes)
+{
+ StringImpl* name = propertyName.publicName();
+ ASSERT(name);
+
+ JSFunction* function =
+ JSFunction::create(exec, globalObject, functionLength, name, nativeFunction, intrinsic);
+ putDirect(exec->vm(), propertyName, function, attributes);
+}
+
ALWAYS_INLINE unsigned JSObject::getNewVectorLength(unsigned currentVectorLength, unsigned currentLength, unsigned desiredLength)
{
ASSERT(desiredLength <= MAX_STORAGE_VECTOR_LENGTH);
@@ -2313,7 +2309,7 @@ unsigned JSObject::countElements()
}
}
-bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength)
+bool JSObject::increaseVectorLength(VM& vm, unsigned newLength)
{
// This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
// to the vector. Callers have to account for that, because they can do it more efficiently.
@@ -2333,7 +2329,7 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength
// Fast case - there is no precapacity. In these cases a realloc makes sense.
if (LIKELY(!indexBias)) {
- Butterfly* newButterfly = storage->butterfly()->growArrayRight(globalData, structure(), structure()->outOfLineCapacity(), true, ArrayStorage::sizeFor(vectorLength), ArrayStorage::sizeFor(newVectorLength));
+ Butterfly* newButterfly = storage->butterfly()->growArrayRight(vm, structure(), structure()->outOfLineCapacity(), true, ArrayStorage::sizeFor(vectorLength), ArrayStorage::sizeFor(newVectorLength));
if (!newButterfly)
return false;
m_butterfly = newButterfly;
@@ -2344,7 +2340,7 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength
// Remove some, but not all of the precapacity. Atomic decay, & capped to not overflow array length.
unsigned newIndexBias = std::min(indexBias >> 1, MAX_STORAGE_VECTOR_LENGTH - newVectorLength);
Butterfly* newButterfly = storage->butterfly()->resizeArray(
- globalData,
+ vm,
structure()->outOfLineCapacity(), true, ArrayStorage::sizeFor(vectorLength),
newIndexBias, true, ArrayStorage::sizeFor(newVectorLength));
if (!newButterfly)
@@ -2356,7 +2352,7 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength
return true;
}
-void JSObject::ensureLengthSlow(JSGlobalData& globalData, unsigned length)
+void JSObject::ensureLengthSlow(VM& vm, unsigned length)
{
ASSERT(length < MAX_ARRAY_INDEX);
ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType()));
@@ -2367,33 +2363,33 @@ void JSObject::ensureLengthSlow(JSGlobalData& globalData, unsigned length)
MAX_STORAGE_VECTOR_LENGTH);
unsigned oldVectorLength = m_butterfly->vectorLength();
m_butterfly = m_butterfly->growArrayRight(
- globalData, structure(), structure()->outOfLineCapacity(), true,
+ vm, structure(), structure()->outOfLineCapacity(), true,
oldVectorLength * sizeof(EncodedJSValue),
newVectorLength * sizeof(EncodedJSValue));
if (hasDouble(structure()->indexingType())) {
for (unsigned i = oldVectorLength; i < newVectorLength; ++i)
- m_butterfly->contiguousDouble()[i] = QNaN;
+ m_butterfly->contiguousDouble().data()[i] = QNaN;
}
m_butterfly->setVectorLength(newVectorLength);
}
-Butterfly* JSObject::growOutOfLineStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
+Butterfly* JSObject::growOutOfLineStorage(VM& vm, size_t oldSize, size_t newSize)
{
ASSERT(newSize > oldSize);
// It's important that this function not rely on structure(), for the property
// capacity, since we might have already mutated the structure in-place.
- return m_butterfly->growPropertyStorage(globalData, structure(), oldSize, newSize);
+ return m_butterfly->growPropertyStorage(vm, structure(), oldSize, newSize);
}
bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
{
unsigned attributes = 0;
JSCell* cell = 0;
- PropertyOffset offset = object->structure()->get(exec->globalData(), propertyName, attributes, cell);
+ PropertyOffset offset = object->structure()->get(exec->vm(), propertyName, attributes, cell);
if (isValidOffset(offset)) {
- descriptor.setDescriptor(object->getDirectOffset(offset), attributes);
+ descriptor.setDescriptor(object->getDirect(offset), attributes);
return true;
}
@@ -2451,7 +2447,7 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
@@ -2475,9 +2471,9 @@ static bool putDescriptor(ExecState* exec, JSObject* target, PropertyName proper
if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
GetterSetter* accessor = GetterSetter::create(exec);
if (oldDescriptor.getterPresent())
- accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+ accessor->setGetter(exec->vm(), oldDescriptor.getterObject());
if (oldDescriptor.setterPresent())
- accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+ accessor->setSetter(exec->vm(), oldDescriptor.setterObject());
target->putDirectAccessor(exec, propertyName, accessor, attributes | Accessor);
return true;
}
@@ -2486,7 +2482,7 @@ static bool putDescriptor(ExecState* exec, JSObject* target, PropertyName proper
newValue = descriptor.value();
else if (oldDescriptor.value())
newValue = oldDescriptor.value();
- target->putDirect(exec->globalData(), propertyName, newValue, attributes & ~Accessor);
+ target->putDirect(exec->vm(), propertyName, newValue, attributes & ~Accessor);
if (attributes & ReadOnly)
target->structure()->setContainsReadOnlyProperties();
return true;
@@ -2495,13 +2491,13 @@ static bool putDescriptor(ExecState* exec, JSObject* target, PropertyName proper
GetterSetter* accessor = GetterSetter::create(exec);
if (descriptor.getterPresent())
- accessor->setGetter(exec->globalData(), descriptor.getterObject());
+ accessor->setGetter(exec->vm(), descriptor.getterObject());
else if (oldDescriptor.getterPresent())
- accessor->setGetter(exec->globalData(), oldDescriptor.getterObject());
+ accessor->setGetter(exec->vm(), oldDescriptor.getterObject());
if (descriptor.setterPresent())
- accessor->setSetter(exec->globalData(), descriptor.setterObject());
+ accessor->setSetter(exec->vm(), descriptor.setterObject());
else if (oldDescriptor.setterPresent())
- accessor->setSetter(exec->globalData(), oldDescriptor.setterObject());
+ accessor->setSetter(exec->vm(), oldDescriptor.setterObject());
target->putDirectAccessor(exec, propertyName, accessor, attributes | Accessor);
return true;
@@ -2511,7 +2507,7 @@ void JSObject::putDirectMayBeIndex(ExecState* exec, PropertyName propertyName, J
{
unsigned asIndex = propertyName.asIndex();
if (asIndex == PropertyName::NotAnIndex)
- putDirect(exec->globalData(), propertyName, value);
+ putDirect(exec->vm(), propertyName, value);
else
putDirectIndex(exec, asIndex, value);
}
@@ -2519,18 +2515,18 @@ void JSObject::putDirectMayBeIndex(ExecState* exec, PropertyName propertyName, J
class DefineOwnPropertyScope {
public:
DefineOwnPropertyScope(ExecState* exec)
- : m_globalData(exec->globalData())
+ : m_vm(exec->vm())
{
- m_globalData.setInDefineOwnProperty(true);
+ m_vm.setInDefineOwnProperty(true);
}
~DefineOwnPropertyScope()
{
- m_globalData.setInDefineOwnProperty(false);
+ m_vm.setInDefineOwnProperty(false);
}
private:
- JSGlobalData& m_globalData;
+ VM& m_vm;
};
bool JSObject::defineOwnNonIndexProperty(ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
@@ -2631,14 +2627,14 @@ bool JSObject::defineOwnNonIndexProperty(ExecState* exec, PropertyName propertyN
return false;
}
}
- JSValue accessor = getDirect(exec->globalData(), propertyName);
+ JSValue accessor = getDirect(exec->vm(), propertyName);
if (!accessor)
return false;
GetterSetter* getterSetter = asGetterSetter(accessor);
if (descriptor.setterPresent())
- getterSetter->setSetter(exec->globalData(), descriptor.setterObject());
+ getterSetter->setSetter(exec->vm(), descriptor.setterObject());
if (descriptor.getterPresent())
- getterSetter->setGetter(exec->globalData(), descriptor.getterObject());
+ getterSetter->setGetter(exec->vm(), descriptor.getterObject());
if (current.attributesEqual(descriptor))
return true;
methodTable()->deleteProperty(this, exec, propertyName);
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index 428e51f3c..c62dc2aec 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -37,7 +37,7 @@
#include "PutPropertySlot.h"
#include "Structure.h"
-#include "JSGlobalData.h"
+#include "VM.h"
#include "JSString.h"
#include "SlotVisitorInlines.h"
#include "SparseArrayValueMap.h"
@@ -121,16 +121,8 @@ public:
JS_EXPORT_PRIVATE static String className(const JSObject*);
JSValue prototype() const;
- void setPrototype(JSGlobalData&, JSValue prototype);
- bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
-
- Structure* inheritorID(JSGlobalData&);
- void notifyUsedAsPrototype(JSGlobalData&);
-
- bool mayBeUsedAsPrototype(JSGlobalData& globalData)
- {
- return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey));
- }
+ void setPrototype(VM&, JSValue prototype);
+ bool setPrototypeWithCycleCheck(VM&, JSValue prototype);
bool mayInterceptIndexedAccesses()
{
@@ -170,7 +162,7 @@ public:
void putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
{
if (canSetIndexQuickly(propertyName)) {
- setIndexQuickly(exec->globalData(), propertyName, value);
+ setIndexQuickly(exec->vm(), propertyName, value);
return;
}
methodTable()->putByIndex(this, exec, propertyName, value, shouldThrow);
@@ -184,7 +176,7 @@ public:
bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
{
if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) {
- setIndexQuickly(exec->globalData(), propertyName, value);
+ setIndexQuickly(exec->vm(), propertyName, value);
return true;
}
return putDirectIndexBeyondVectorLength(exec, propertyName, value, attributes, mode);
@@ -217,7 +209,7 @@ public:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i];
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
@@ -233,7 +225,7 @@ public:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
return m_butterfly->arrayStorage()->m_vector[i].get();
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return JSValue();
}
}
@@ -262,7 +254,7 @@ public:
return m_butterfly->arrayStorage()->m_vector[i].get();
break;
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
break;
}
return JSValue();
@@ -302,7 +294,7 @@ public:
return i < m_butterfly->arrayStorage()->vectorLength()
&& !!m_butterfly->arrayStorage()->m_vector[i];
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
@@ -319,25 +311,25 @@ public:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
return i < m_butterfly->vectorLength();
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
- void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v)
+ void setIndexQuickly(VM& vm, unsigned i, JSValue v)
{
switch (structure()->indexingType()) {
case ALL_INT32_INDEXING_TYPES: {
ASSERT(i < m_butterfly->vectorLength());
if (!v.isInt32()) {
- convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(globalData, i, v);
+ convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, 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);
+ m_butterfly->contiguous()[i].set(vm, this, v);
if (i >= m_butterfly->publicLength())
m_butterfly->setPublicLength(i + 1);
break;
@@ -345,12 +337,12 @@ public:
case ALL_DOUBLE_INDEXING_TYPES: {
ASSERT(i < m_butterfly->vectorLength());
if (!v.isNumber()) {
- convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v);
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
return;
}
double value = v.asNumber();
if (value != value) {
- convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v);
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
return;
}
m_butterfly->contiguousDouble()[i] = value;
@@ -362,7 +354,7 @@ public:
ArrayStorage* storage = m_butterfly->arrayStorage();
WriteBarrier<Unknown>& x = storage->m_vector[i];
JSValue old = x.get();
- x.set(globalData, this, v);
+ x.set(vm, this, v);
if (!old) {
++storage->m_numValuesInVector;
if (i >= storage->length())
@@ -371,22 +363,22 @@ public:
break;
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
- void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v)
+ void initializeIndex(VM& vm, unsigned i, JSValue v)
{
switch (structure()->indexingType()) {
case ALL_UNDECIDED_INDEXING_TYPES: {
- setIndexQuicklyToUndecided(globalData, i, v);
+ setIndexQuicklyToUndecided(vm, 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);
+ convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v);
break;
}
// Fall through.
@@ -394,19 +386,19 @@ public:
case ALL_CONTIGUOUS_INDEXING_TYPES: {
ASSERT(i < m_butterfly->publicLength());
ASSERT(i < m_butterfly->vectorLength());
- m_butterfly->contiguous()[i].set(globalData, this, v);
+ m_butterfly->contiguous()[i].set(vm, 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);
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
return;
}
double value = v.asNumber();
if (value != value) {
- convertDoubleToContiguousWhilePerformingSetIndex(globalData, i, v);
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
return;
}
m_butterfly->contiguousDouble()[i] = value;
@@ -416,11 +408,11 @@ public:
ArrayStorage* storage = m_butterfly->arrayStorage();
ASSERT(i < storage->length());
ASSERT(i < storage->m_numValuesInVector);
- storage->m_vector[i].set(globalData, this, v);
+ storage->m_vector[i].set(vm, this, v);
break;
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
}
@@ -436,7 +428,7 @@ public:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
return m_butterfly->arrayStorage()->m_sparseMap;
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
@@ -453,12 +445,12 @@ public:
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
return m_butterfly->arrayStorage()->inSparseMode();
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return false;
}
}
- void enterDictionaryIndexingMode(JSGlobalData&);
+ void enterDictionaryIndexingMode(VM&);
// putDirect is effectively an unchecked vesion of 'defineOwnProperty':
// - the prototype chain is not consulted
@@ -466,9 +458,9 @@ public:
// - attributes will be respected (after the call the property will exist with the given attributes)
// - the property name is assumed to not be an index.
JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
- void putDirect(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
- void putDirect(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
- void putDirectWithoutTransition(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
+ void putDirect(VM&, PropertyName, JSValue, unsigned attributes = 0);
+ void putDirect(VM&, PropertyName, JSValue, PutPropertySlot&);
+ void putDirectWithoutTransition(VM&, PropertyName, JSValue, unsigned attributes = 0);
void putDirectAccessor(ExecState*, PropertyName, JSValue, unsigned attributes);
bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
@@ -501,25 +493,18 @@ public:
bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const;
// This get function only looks at the property map.
- JSValue getDirect(JSGlobalData& globalData, PropertyName propertyName) const
+ JSValue getDirect(VM& vm, PropertyName propertyName) const
{
- PropertyOffset offset = structure()->get(globalData, propertyName);
- checkOffset(offset, structure()->typeInfo().type());
- return offset != invalidOffset ? getDirectOffset(offset) : JSValue();
+ PropertyOffset offset = structure()->get(vm, propertyName);
+ checkOffset(offset, structure()->inlineCapacity());
+ return offset != invalidOffset ? getDirect(offset) : JSValue();
}
- WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName)
+ PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName)
{
- PropertyOffset offset = structure()->get(globalData, propertyName);
- checkOffset(offset, structure()->typeInfo().type());
- return isValidOffset(offset) ? locationForOffset(offset) : 0;
- }
-
- WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes)
- {
- JSCell* specificFunction;
- PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction);
- return isValidOffset(offset) ? locationForOffset(offset) : 0;
+ PropertyOffset offset = structure()->get(vm, propertyName);
+ checkOffset(offset, structure()->inlineCapacity());
+ return offset;
}
bool hasInlineStorage() const { return structure()->hasInlineStorage(); }
@@ -562,21 +547,9 @@ public:
return &outOfLineStorage()[offsetInOutOfLineStorage(offset)];
}
- PropertyOffset offsetForLocation(WriteBarrierBase<Unknown>* location) const
- {
- PropertyOffset result;
- size_t offsetInInlineStorage = location - inlineStorageUnsafe();
- if (offsetInInlineStorage < static_cast<size_t>(firstOutOfLineOffset))
- result = offsetInInlineStorage;
- else
- result = outOfLineStorage() - location + (firstOutOfLineOffset - 1);
- validateOffset(result, structure()->typeInfo().type());
- return result;
- }
+ void transitionTo(VM&, Structure*);
- void transitionTo(JSGlobalData&, Structure*);
-
- bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed.
+ bool removeDirect(VM&, PropertyName); // Return true if anything is removed.
bool hasCustomProperties() { return structure()->didTransition(); }
bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
@@ -585,26 +558,29 @@ public:
// - provides no special handling for __proto__
// - does not walk the prototype chain (to check for accessors or non-writable properties).
// This is used by JSActivation.
- bool putOwnDataProperty(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
+ bool putOwnDataProperty(VM&, PropertyName, JSValue, PutPropertySlot&);
// Fast access to known property offsets.
- JSValue getDirectOffset(PropertyOffset offset) const { return locationForOffset(offset)->get(); }
- void putDirectOffset(JSGlobalData& globalData, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(globalData, this, value); }
- void putUndefinedAtDirectOffset(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
+ JSValue getDirect(PropertyOffset offset) const { return locationForOffset(offset)->get(); }
+ void putDirect(VM& vm, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(vm, this, value); }
+ void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
+
+ void putDirectNativeFunction(ExecState*, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
bool isGlobalObject() const;
bool isVariableObject() const;
+ bool isStaticScopeObject() const;
bool isNameScopeObject() const;
bool isActivationObject() const;
bool isErrorInstance() const;
- void seal(JSGlobalData&);
- void freeze(JSGlobalData&);
- JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&);
- bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); }
- bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); }
+ void seal(VM&);
+ void freeze(VM&);
+ JS_EXPORT_PRIVATE void preventExtensions(VM&);
+ bool isSealed(VM& vm) { return structure()->isSealed(vm); }
+ bool isFrozen(VM& vm) { return structure()->isFrozen(vm); }
bool isExtensible() { return structure()->isExtensible(); }
bool indexingShouldBeSparse()
{
@@ -615,16 +591,16 @@ public:
bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
void reifyStaticFunctionsForDelete(ExecState* exec);
- JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(JSGlobalData&, size_t oldSize, size_t newSize);
- void setButterfly(JSGlobalData&, Butterfly*, Structure*);
+ JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(VM&, size_t oldSize, size_t newSize);
+ void setButterfly(VM&, Butterfly*, Structure*);
void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this.
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*);
+ void setStructureAndReallocateStorageIfNecessary(VM&, unsigned oldCapacity, Structure*);
+ void setStructureAndReallocateStorageIfNecessary(VM&, Structure*);
- void flattenDictionaryObject(JSGlobalData& globalData)
+ void flattenDictionaryObject(VM& vm)
{
- structure()->flattenDictionaryStructure(globalData, this);
+ structure()->flattenDictionaryStructure(vm, this);
}
JSGlobalObject* globalObject() const
@@ -634,7 +610,7 @@ public:
return structure()->globalObject();
}
- void switchToSlowPutArrayStorage(JSGlobalData&);
+ void switchToSlowPutArrayStorage(VM&);
// The receiver is the prototype in this case. The following:
//
@@ -649,46 +625,57 @@ public:
// 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)
+ ContiguousJSValues ensureInt32(VM& vm)
{
if (LIKELY(hasInt32(structure()->indexingType())))
return m_butterfly->contiguousInt32();
- return ensureInt32Slow(globalData);
+ return ensureInt32Slow(vm);
}
// 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)
+ ContiguousDoubles ensureDouble(VM& vm)
{
if (LIKELY(hasDouble(structure()->indexingType())))
return m_butterfly->contiguousDouble();
- return ensureDoubleSlow(globalData);
+ return ensureDoubleSlow(vm);
}
// 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)
+ ContiguousJSValues ensureContiguous(VM& vm)
{
if (LIKELY(hasContiguous(structure()->indexingType())))
return m_butterfly->contiguous();
- return ensureContiguousSlow(globalData);
+ return ensureContiguousSlow(vm);
+ }
+
+ // Same as ensureContiguous(), except that if the indexed storage is in
+ // double mode, then it does a rage conversion to contiguous: it
+ // attempts to convert each double to an int32.
+ ContiguousJSValues rageEnsureContiguous(VM& vm)
+ {
+ if (LIKELY(hasContiguous(structure()->indexingType())))
+ return m_butterfly->contiguous();
+
+ return rageEnsureContiguousSlow(vm);
}
// Ensure that the object is in a mode where it has array storage. Use
// this if you're about to perform actions that would have required the
// object to be converted to have array storage, if it didn't have it
// already.
- ArrayStorage* ensureArrayStorage(JSGlobalData& globalData)
+ ArrayStorage* ensureArrayStorage(VM& vm)
{
if (LIKELY(hasArrayStorage(structure()->indexingType())))
return m_butterfly->arrayStorage();
- return ensureArrayStorageSlow(globalData);
+ return ensureArrayStorageSlow(vm);
}
static size_t offsetOfInlineStorage();
@@ -706,9 +693,9 @@ public:
static JS_EXPORTDATA const ClassInfo s_info;
protected:
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
ASSERT(!structure()->outOfLineCapacity());
ASSERT(structure()->isEmpty());
@@ -717,16 +704,14 @@ protected:
ASSERT(classInfo());
}
- 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);
}
// To instantiate objects you likely want JSFinalObject, below.
// To create derived types you likely want JSNonFinalObject, below.
- JSObject(JSGlobalData&, Structure*, Butterfly* = 0);
-
- void resetInheritorID(JSGlobalData&);
+ JSObject(VM&, Structure*, Butterfly* = 0);
void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize);
void copyButterfly(CopyVisitor&, Butterfly*, size_t storageSize);
@@ -752,41 +737,42 @@ protected:
}
}
- Butterfly* createInitialUndecided(JSGlobalData&, unsigned length);
- WriteBarrier<Unknown>* createInitialInt32(JSGlobalData&, unsigned length);
- double* createInitialDouble(JSGlobalData&, unsigned length);
- WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length);
+ Butterfly* createInitialUndecided(VM&, unsigned length);
+ ContiguousJSValues createInitialInt32(VM&, unsigned length);
+ ContiguousDoubles createInitialDouble(VM&, unsigned length);
+ ContiguousJSValues createInitialContiguous(VM&, unsigned length);
- void convertUndecidedForValue(JSGlobalData&, JSValue);
- void convertInt32ForValue(JSGlobalData&, JSValue);
+ void convertUndecidedForValue(VM&, JSValue);
+ void convertInt32ForValue(VM&, JSValue);
- ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength);
- ArrayStorage* createInitialArrayStorage(JSGlobalData&);
+ ArrayStorage* createArrayStorage(VM&, unsigned length, unsigned vectorLength);
+ ArrayStorage* createInitialArrayStorage(VM&);
- WriteBarrier<Unknown>* convertUndecidedToInt32(JSGlobalData&);
- double* convertUndecidedToDouble(JSGlobalData&);
- WriteBarrier<Unknown>* convertUndecidedToContiguous(JSGlobalData&);
- ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
- ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition);
- ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&);
+ ContiguousJSValues convertUndecidedToInt32(VM&);
+ ContiguousDoubles convertUndecidedToDouble(VM&);
+ ContiguousJSValues convertUndecidedToContiguous(VM&);
+ ArrayStorage* convertUndecidedToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength);
+ ArrayStorage* convertUndecidedToArrayStorage(VM&, NonPropertyTransition);
+ ArrayStorage* convertUndecidedToArrayStorage(VM&);
- 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&);
+ ContiguousDoubles convertInt32ToDouble(VM&);
+ ContiguousJSValues convertInt32ToContiguous(VM&);
+ ArrayStorage* convertInt32ToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength);
+ ArrayStorage* convertInt32ToArrayStorage(VM&, NonPropertyTransition);
+ ArrayStorage* convertInt32ToArrayStorage(VM&);
+
+ ContiguousJSValues convertDoubleToContiguous(VM&);
+ ContiguousJSValues rageConvertDoubleToContiguous(VM&);
+ ArrayStorage* convertDoubleToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength);
+ ArrayStorage* convertDoubleToArrayStorage(VM&, NonPropertyTransition);
+ ArrayStorage* convertDoubleToArrayStorage(VM&);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&);
+ ArrayStorage* convertContiguousToArrayStorage(VM&, NonPropertyTransition, unsigned neededLength);
+ ArrayStorage* convertContiguousToArrayStorage(VM&, NonPropertyTransition);
+ ArrayStorage* convertContiguousToArrayStorage(VM&);
- ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData&);
+ ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(VM&);
bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
@@ -794,24 +780,24 @@ protected:
void putByIndexBeyondVectorLengthWithoutAttributes(ExecState*, unsigned propertyName, JSValue);
void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*);
- bool increaseVectorLength(JSGlobalData&, unsigned newLength);
+ bool increaseVectorLength(VM&, unsigned newLength);
void deallocateSparseIndexMap();
bool defineOwnIndexedProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
- SparseArrayValueMap* allocateSparseIndexMap(JSGlobalData&);
+ SparseArrayValueMap* allocateSparseIndexMap(VM&);
- void notifyPresenceOfIndexedAccessors(JSGlobalData&);
+ void notifyPresenceOfIndexedAccessors(VM&);
bool attemptToInterceptPutByIndexOnHole(ExecState*, unsigned index, JSValue, bool shouldThrow);
// Call this if you want setIndexQuickly to succeed and you're sure that
// the array is contiguous.
- void ensureLength(JSGlobalData& globalData, unsigned length)
+ void ensureLength(VM& vm, unsigned length)
{
ASSERT(length < MAX_ARRAY_INDEX);
ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType()));
if (m_butterfly->vectorLength() < length)
- ensureLengthSlow(globalData, length);
+ ensureLengthSlow(vm, length);
if (m_butterfly->publicLength() < length)
m_butterfly->setPublicLength(length);
@@ -827,7 +813,7 @@ protected:
// 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()
+ ContiguousJSValues indexingData()
{
switch (indexingType) {
case ALL_INT32_INDEXING_TYPES:
@@ -836,15 +822,15 @@ protected:
return m_butterfly->contiguous();
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage()->m_vector;
-
+ return m_butterfly->arrayStorage()->vector();
+
default:
CRASH();
- return 0;
+ return ContiguousJSValues();
}
}
- WriteBarrier<Unknown>* currentIndexingData()
+ ContiguousJSValues currentIndexingData()
{
switch (structure()->indexingType()) {
case ALL_INT32_INDEXING_TYPES:
@@ -852,11 +838,11 @@ protected:
return m_butterfly->contiguous();
case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage()->m_vector;
+ return m_butterfly->arrayStorage()->vector();
default:
CRASH();
- return 0;
+ return ContiguousJSValues();
}
}
@@ -931,18 +917,17 @@ private:
void isObject();
void isString();
- Butterfly* createInitialIndexedStorage(JSGlobalData&, unsigned length, size_t elementSize);
+ Butterfly* createInitialIndexedStorage(VM&, unsigned length, size_t elementSize);
- ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData&, ArrayStorage*);
+ ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(VM&, ArrayStorage*);
template<PutMode>
- bool putDirectInternal(JSGlobalData&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
+ bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, PropertyOffset);
const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const;
- Structure* createInheritorID(JSGlobalData&);
void putIndexedDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
@@ -955,24 +940,29 @@ 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);
+ ArrayStorage* constructConvertedArrayStorageWithoutCopyingElements(VM&, unsigned neededLength);
- void ensureLengthSlow(JSGlobalData&, unsigned length);
+ JS_EXPORT_PRIVATE void setIndexQuicklyToUndecided(VM&, unsigned index, JSValue);
+ JS_EXPORT_PRIVATE void convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(VM&, unsigned index, JSValue);
+ JS_EXPORT_PRIVATE void convertDoubleToContiguousWhilePerformingSetIndex(VM&, unsigned index, JSValue);
- WriteBarrier<Unknown>* ensureInt32Slow(JSGlobalData&);
- double* ensureDoubleSlow(JSGlobalData&);
- WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&);
- ArrayStorage* ensureArrayStorageSlow(JSGlobalData&);
+ void ensureLengthSlow(VM&, unsigned length);
+ ContiguousJSValues ensureInt32Slow(VM&);
+ ContiguousDoubles ensureDoubleSlow(VM&);
+ ContiguousJSValues ensureContiguousSlow(VM&);
+ ContiguousJSValues rageEnsureContiguousSlow(VM&);
+ ArrayStorage* ensureArrayStorageSlow(VM&);
+
+ enum DoubleToContiguousMode { EncodeValueAsDouble, RageConvertDoubleToValue };
+ template<DoubleToContiguousMode mode>
+ ContiguousJSValues genericConvertDoubleToContiguous(VM&);
+ ContiguousJSValues ensureContiguousSlow(VM&, DoubleToContiguousMode);
+
protected:
Butterfly* m_butterfly;
};
-
// JSNonFinalObject is a type of JSObject that has some internal storage,
// but also preserves some space in the collector cell for additional
// data members in derived types.
@@ -982,20 +972,20 @@ class JSNonFinalObject : public JSObject {
public:
typedef JSObject Base;
- 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:
- explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0)
- : JSObject(globalData, structure, butterfly)
+ explicit JSNonFinalObject(VM& vm, Structure* structure, Butterfly* butterfly = 0)
+ : JSObject(vm, structure, butterfly)
{
}
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(!this->structure()->totalStorageCapacity());
ASSERT(classInfo());
}
@@ -1011,10 +1001,22 @@ class JSFinalObject : public JSObject {
public:
typedef JSObject Base;
+ static const unsigned defaultSize = 64;
+ static inline unsigned defaultInlineCapacity()
+ {
+ return (defaultSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>);
+ }
+
+ static const unsigned maxSize = 512;
+ static inline unsigned maxInlineCapacity()
+ {
+ return (maxSize - allocationSize(0)) / sizeof(WriteBarrier<Unknown>);
+ }
+
static JSFinalObject* create(ExecState*, Structure*);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, unsigned inlineCapacity)
{
- return Structure::create(globalData, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info, NonArray, INLINE_STORAGE_CAPACITY);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info, NonArray, inlineCapacity);
}
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
@@ -1024,9 +1026,9 @@ public:
protected:
void visitChildrenCommon(SlotVisitor&);
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(structure()->totalStorageCapacity() == structure()->inlineCapacity());
ASSERT(classInfo());
}
@@ -1034,8 +1036,8 @@ protected:
private:
friend class LLIntOffsetsExtractor;
- explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
- : JSObject(globalData, structure)
+ explicit JSFinalObject(VM& vm, Structure* structure)
+ : JSObject(vm, structure)
{
}
@@ -1050,8 +1052,8 @@ inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structur
*exec->heap(),
allocationSize(structure->inlineCapacity())
)
- ) JSFinalObject(exec->globalData(), structure);
- finalObject->finishCreation(exec->globalData());
+ ) JSFinalObject(exec->vm(), structure);
+ finalObject->finishCreation(exec->vm());
return finalObject;
}
@@ -1080,6 +1082,14 @@ inline bool JSObject::isVariableObject() const
return structure()->typeInfo().type() >= VariableObjectType;
}
+
+inline bool JSObject::isStaticScopeObject() const
+{
+ JSType type = structure()->typeInfo().type();
+ return type == NameScopeObjectType || type == ActivationObjectType;
+}
+
+
inline bool JSObject::isNameScopeObject() const
{
return structure()->typeInfo().type() == NameScopeObjectType;
@@ -1095,11 +1105,11 @@ inline bool JSObject::isErrorInstance() const
return structure()->typeInfo().type() == ErrorInstanceType;
}
-inline void JSObject::setButterfly(JSGlobalData& globalData, Butterfly* butterfly, Structure* structure)
+inline void JSObject::setButterfly(VM& vm, Butterfly* butterfly, Structure* structure)
{
ASSERT(structure);
ASSERT(!butterfly == (!structure->outOfLineCapacity() && !hasIndexingHeader(structure->indexingType())));
- setStructure(globalData, structure);
+ setStructure(vm, structure);
m_butterfly = butterfly;
}
@@ -1108,11 +1118,6 @@ inline void JSObject::setButterflyWithoutChangingStructure(Butterfly* butterfly)
m_butterfly = butterfly;
}
-inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
-{
- return JSFinalObject::create(exec, structure);
-}
-
inline CallType getCallData(JSValue value, CallData& callData)
{
CallType result = value.isCell() ? value.asCell()->methodTable()->getCallData(value.asCell(), callData) : CallTypeNone;
@@ -1127,11 +1132,6 @@ inline ConstructType getConstructData(JSValue value, ConstructData& constructDat
return result;
}
-inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
-{
- return JSFinalObject::createStructure(globalData, globalObject, prototype);
-}
-
inline JSObject* asObject(JSCell* cell)
{
ASSERT(cell->isObject());
@@ -1143,8 +1143,8 @@ inline JSObject* asObject(JSValue value)
return asObject(value.asCell());
}
-inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly)
- : JSCell(globalData, structure)
+inline JSObject::JSObject(VM& vm, Structure* structure, Butterfly* butterfly)
+ : JSCell(vm, structure)
, m_butterfly(butterfly)
{
}
@@ -1154,32 +1154,11 @@ inline JSValue JSObject::prototype() const
return structure()->storedPrototype();
}
-inline const MethodTable* JSCell::methodTable() const
-{
- return &classInfo()->methodTable;
-}
-
-inline bool JSCell::inherits(const ClassInfo* info) const
-{
- return classInfo()->isSubClassOf(info);
-}
-
-// this method is here to be after the inline declaration of JSCell::inherits
-inline bool JSValue::inherits(const ClassInfo* classInfo) const
-{
- return isCell() && asCell()->inherits(classInfo);
-}
-
-inline JSObject* JSValue::toThisObject(ExecState* exec) const
-{
- return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec);
-}
-
ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
- PropertyOffset offset = structure()->get(exec->globalData(), propertyName);
+ PropertyOffset offset = structure()->get(exec->vm(), propertyName);
if (LIKELY(isValidOffset(offset))) {
- JSValue value = getDirectOffset(offset);
+ JSValue value = getDirect(offset);
if (structure()->hasGetterSetterProperties() && value.isGetterSetter())
fillGetterPropertySlot(slot, offset);
else
@@ -1198,29 +1177,6 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, P
return jsCast<JSObject*>(cell)->inlineGetOwnPropertySlot(exec, propertyName, slot);
}
-ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
-{
- if (!structure()->typeInfo().overridesGetOwnPropertySlot())
- return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot);
- return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot);
-}
-
-// Fast call to get a property where we may not yet have converted the string to an
-// identifier. The first time we perform a property access with a given string, try
-// performing the property map lookup without forming an identifier. We detect this
-// case by checking whether the hash has yet been set for this string.
-ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const String& name)
-{
- if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) {
- PropertyOffset offset = name.impl()->hasHash()
- ? structure()->get(exec->globalData(), Identifier(exec, name))
- : structure()->get(exec->globalData(), name);
- if (offset != invalidOffset)
- return asObject(this)->locationForOffset(offset)->get();
- }
- return JSValue();
-}
-
// It may seem crazy to inline a function this large but it makes a big difference
// since this is function very hot in variable lookup
ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
@@ -1268,7 +1224,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
}
template<JSObject::PutMode mode>
-inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction)
+inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction)
{
ASSERT(value);
ASSERT(value.isGetterSetter() == !!(attributes & Accessor));
@@ -1278,16 +1234,16 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
if (structure()->isDictionary()) {
unsigned currentAttributes;
JSCell* currentSpecificFunction;
- PropertyOffset offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
+ PropertyOffset offset = structure()->get(vm, propertyName, currentAttributes, currentSpecificFunction);
if (offset != invalidOffset) {
// If there is currently a specific function, and there now either isn't,
// or the new value is different, then despecify.
if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
- structure()->despecifyDictionaryFunction(globalData, propertyName);
+ structure()->despecifyDictionaryFunction(vm, propertyName);
if ((mode == PutModePut) && currentAttributes & ReadOnly)
return false;
- putDirectOffset(globalData, offset, value);
+ putDirect(vm, offset, value);
// At this point, the objects structure only has a specific value set if previously there
// had been one set, and if the new value being specified is the same (otherwise we would
// have despecified, above). So, if currentSpecificFunction is not set, or if the new
@@ -1304,13 +1260,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
Butterfly* newButterfly = m_butterfly;
if (structure()->putWillGrowOutOfLineStorage())
- newButterfly = growOutOfLineStorage(globalData, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
- offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
- setButterfly(globalData, newButterfly, structure());
+ newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
+ offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, specificFunction);
+ setButterfly(vm, newButterfly, structure());
validateOffset(offset);
ASSERT(structure()->isValidOffset(offset));
- putDirectOffset(globalData, offset, value);
+ putDirect(vm, offset, value);
// See comment on setNewProperty call below.
if (!specificFunction)
slot.setNewProperty(this, offset);
@@ -1324,12 +1280,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
Butterfly* newButterfly = m_butterfly;
if (currentCapacity != structure->outOfLineCapacity())
- newButterfly = growOutOfLineStorage(globalData, currentCapacity, structure->outOfLineCapacity());
+ newButterfly = growOutOfLineStorage(vm, currentCapacity, structure->outOfLineCapacity());
validateOffset(offset);
ASSERT(structure->isValidOffset(offset));
- setButterfly(globalData, newButterfly, structure);
- putDirectOffset(globalData, offset, value);
+ setButterfly(vm, newButterfly, structure);
+ putDirect(vm, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
if (!specificFunction)
@@ -1339,7 +1295,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
unsigned currentAttributes;
JSCell* currentSpecificFunction;
- offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
+ offset = structure()->get(vm, propertyName, currentAttributes, currentSpecificFunction);
if (offset != invalidOffset) {
if ((mode == PutModePut) && currentAttributes & ReadOnly)
return false;
@@ -1356,29 +1312,29 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
if (currentSpecificFunction) {
// case (1) Do the put, then return leaving the slot uncachable.
if (specificFunction == currentSpecificFunction) {
- putDirectOffset(globalData, offset, value);
+ putDirect(vm, offset, value);
return true;
}
// case (2) Despecify, fall through to (3).
- setStructure(globalData, Structure::despecifyFunctionTransition(globalData, structure(), propertyName));
+ setStructure(vm, Structure::despecifyFunctionTransition(vm, structure(), propertyName));
}
// case (3) set the slot, do the put, return.
slot.setExistingProperty(this, offset);
- putDirectOffset(globalData, offset, value);
+ putDirect(vm, offset, value);
return true;
}
if ((mode == PutModePut) && !isExtensible())
return false;
- Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
+ Structure* structure = Structure::addPropertyTransition(vm, this->structure(), propertyName, attributes, specificFunction, offset);
validateOffset(offset);
ASSERT(structure->isValidOffset(offset));
- setStructureAndReallocateStorageIfNecessary(globalData, structure);
+ setStructureAndReallocateStorageIfNecessary(vm, structure);
- putDirectOffset(globalData, offset, value);
+ putDirect(vm, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
if (!specificFunction)
@@ -1388,57 +1344,57 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, PropertyName p
return true;
}
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, unsigned oldCapacity, Structure* newStructure)
+inline void JSObject::setStructureAndReallocateStorageIfNecessary(VM& vm, unsigned oldCapacity, Structure* newStructure)
{
ASSERT(oldCapacity <= newStructure->outOfLineCapacity());
if (oldCapacity == newStructure->outOfLineCapacity()) {
- setStructure(globalData, newStructure);
+ setStructure(vm, newStructure);
return;
}
Butterfly* newButterfly = growOutOfLineStorage(
- globalData, oldCapacity, newStructure->outOfLineCapacity());
- setButterfly(globalData, newButterfly, newStructure);
+ vm, oldCapacity, newStructure->outOfLineCapacity());
+ setButterfly(vm, newButterfly, newStructure);
}
-inline void JSObject::setStructureAndReallocateStorageIfNecessary(JSGlobalData& globalData, Structure* newStructure)
+inline void JSObject::setStructureAndReallocateStorageIfNecessary(VM& vm, Structure* newStructure)
{
setStructureAndReallocateStorageIfNecessary(
- globalData, structure()->outOfLineCapacity(), newStructure);
+ vm, structure()->outOfLineCapacity(), newStructure);
}
-inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+inline bool JSObject::putOwnDataProperty(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(value);
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
ASSERT(!structure()->hasGetterSetterProperties());
- return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getCallableObject(value));
+ return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value));
}
-inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
+inline void JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
PutPropertySlot slot;
- putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getCallableObject(value));
+ putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
}
-inline void JSObject::putDirect(JSGlobalData& globalData, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+inline void JSObject::putDirect(VM& vm, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
ASSERT(!value.isGetterSetter());
- putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getCallableObject(value));
+ putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot, getCallableObject(value));
}
-inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, JSValue value, unsigned attributes)
+inline void JSObject::putDirectWithoutTransition(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes)
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
Butterfly* newButterfly = m_butterfly;
if (structure()->putWillGrowOutOfLineStorage())
- newButterfly = growOutOfLineStorage(globalData, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
- PropertyOffset offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getCallableObject(value));
- setButterfly(globalData, newButterfly, structure());
- putDirectOffset(globalData, offset, value);
+ newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
+ PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, getCallableObject(value));
+ setButterfly(vm, newButterfly, structure());
+ putDirect(vm, offset, value);
}
inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
@@ -1446,74 +1402,6 @@ inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType pre
return methodTable()->defaultValue(this, exec, preferredType);
}
-inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const
-{
- PropertySlot slot(asValue());
- return get(exec, propertyName, slot);
-}
-
-inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
-{
- if (UNLIKELY(!isCell())) {
- JSObject* prototype = synthesizePrototype(exec);
- if (!prototype->getPropertySlot(exec, propertyName, slot))
- return jsUndefined();
- return slot.getValue(exec, propertyName);
- }
- JSCell* cell = asCell();
- while (true) {
- if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
- return slot.getValue(exec, propertyName);
- JSValue prototype = asObject(cell)->prototype();
- if (!prototype.isObject())
- return jsUndefined();
- cell = asObject(prototype);
- }
-}
-
-inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
-{
- PropertySlot slot(asValue());
- return get(exec, propertyName, slot);
-}
-
-inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
-{
- if (UNLIKELY(!isCell())) {
- JSObject* prototype = synthesizePrototype(exec);
- if (!prototype->getPropertySlot(exec, propertyName, slot))
- return jsUndefined();
- return slot.getValue(exec, propertyName);
- }
- JSCell* cell = const_cast<JSCell*>(asCell());
- while (true) {
- if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot))
- return slot.getValue(exec, propertyName);
- JSValue prototype = asObject(cell)->prototype();
- if (!prototype.isObject())
- return jsUndefined();
- cell = prototype.asCell();
- }
-}
-
-inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
-{
- if (UNLIKELY(!isCell())) {
- putToPrimitive(exec, propertyName, value, slot);
- return;
- }
- asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
-}
-
-inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
-{
- if (UNLIKELY(!isCell())) {
- putToPrimitiveByIndex(exec, propertyName, value, shouldThrow);
- return;
- }
- asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
-}
-
ALWAYS_INLINE JSObject* Register::function() const
{
if (!jsValue())
@@ -1533,7 +1421,7 @@ inline size_t offsetInButterfly(PropertyOffset offset)
return offsetInOutOfLineStorage(offset) + Butterfly::indexOfPropertyStorage();
}
-// This is a helper for patching code where you want to emit a load or store and
+// Helpers for patching code where you want to emit a load or store and
// the base is:
// For inline offsets: a pointer to the out-of-line storage pointer.
// For out-of-line offsets: the base of the out-of-line storage.
@@ -1544,6 +1432,17 @@ inline size_t offsetRelativeToPatchedStorage(PropertyOffset offset)
return JSObject::offsetOfInlineStorage() - JSObject::butterflyOffset() + sizeof(EncodedJSValue) * offsetInInlineStorage(offset);
}
+// Returns the maximum offset (away from zero) a load instruction will encode.
+inline size_t maxOffsetRelativeToPatchedStorage(PropertyOffset offset)
+{
+ ptrdiff_t addressOffset = static_cast<ptrdiff_t>(offsetRelativeToPatchedStorage(offset));
+#if USE(JSVALUE32_64)
+ if (addressOffset >= 0)
+ return static_cast<size_t>(addressOffset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag);
+#endif
+ return static_cast<size_t>(addressOffset);
+}
+
inline int indexRelativeToBase(PropertyOffset offset)
{
if (isOutOfLineOffset(offset))
@@ -1561,37 +1460,30 @@ inline int offsetRelativeToBase(PropertyOffset offset)
COMPILE_ASSERT(!(sizeof(JSObject) % sizeof(WriteBarrierBase<Unknown>)), JSObject_inline_storage_has_correct_alignment);
-class JSDestructibleObject : public JSNonFinalObject {
-public:
- typedef JSNonFinalObject Base;
-
- static const bool needsDestruction = true;
-
- const ClassInfo* classInfo() const { return m_classInfo; }
-
-protected:
- JSDestructibleObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0)
- : JSNonFinalObject(globalData, structure, butterfly)
- , m_classInfo(structure->classInfo())
- {
- ASSERT(m_classInfo);
- }
-
-private:
- const ClassInfo* m_classInfo;
-};
+ALWAYS_INLINE Identifier makeIdentifier(ExecState* exec, const char* name)
+{
+ return Identifier(exec, name);
+}
-inline const ClassInfo* JSCell::classInfo() const
+ALWAYS_INLINE Identifier makeIdentifier(ExecState*, const Identifier& name)
{
- if (MarkedBlock::blockFor(this)->destructorType() == MarkedBlock::Normal)
- return static_cast<const JSDestructibleObject*>(this)->classInfo();
-#if ENABLE(GC_VALIDATION)
- return m_structure.unvalidatedGet()->classInfo();
-#else
- return m_structure->classInfo();
-#endif
+ return name;
}
+// Helper for defining native functions, if you're not using a static hash table.
+// Use this macro from within finishCreation() methods in prototypes. This assumes
+// you've defined variables called exec, globalObject, and vm, and they
+// have the expected meanings.
+#define JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, attributes, length, intrinsic) \
+ putDirectNativeFunction(\
+ exec, globalObject, makeIdentifier(exec, (jsName)), (length), cppName, \
+ (intrinsic), (attributes))
+
+// As above, but this assumes that the function you're defining doesn't have an
+// intrinsic.
+#define JSC_NATIVE_FUNCTION(jsName, cppName, attributes, length) \
+ JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, (attributes), (length), NoIntrinsic)
+
} // namespace JSC
#endif // JSObject_h
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index 496799501..78b8aaee9 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -36,7 +36,7 @@ namespace JSC {
const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameIterator) };
inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
- : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get())
+ : JSCell(exec->vm(), exec->vm().propertyNameIteratorStructure.get())
, m_numCacheableSlots(numCacheableSlots)
, m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
, m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize]))
@@ -76,9 +76,9 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
return jsPropertyNameIterator;
}
- jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain);
- jsPropertyNameIterator->setCachedStructure(exec->globalData(), o->structure());
- o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator);
+ jsPropertyNameIterator->setCachedPrototypeChain(exec->vm(), structureChain);
+ jsPropertyNameIterator->setCachedStructure(exec->vm(), o->structure());
+ o->structure()->setEnumerationCache(exec->vm(), jsPropertyNameIterator);
return jsPropertyNameIterator;
}
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
index e59a5c6a4..ba931b131 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -52,9 +52,9 @@ namespace JSC {
static const bool hasImmortalStructure = true;
static void destroy(JSCell*);
- 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(CompoundType, OverridesVisitChildren), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
}
static void visitChildren(JSCell*, SlotVisitor&);
@@ -62,26 +62,26 @@ namespace JSC {
JSValue get(ExecState*, JSObject*, size_t i);
size_t size() { return m_jsStringsSize; }
- void setCachedStructure(JSGlobalData& globalData, Structure* structure)
+ void setCachedStructure(VM& vm, Structure* structure)
{
ASSERT(!m_cachedStructure);
ASSERT(structure);
- m_cachedStructure.set(globalData, this, structure);
+ m_cachedStructure.set(vm, this, structure);
}
Structure* cachedStructure() { return m_cachedStructure.get(); }
- void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); }
+ void setCachedPrototypeChain(VM& vm, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(vm, this, cachedPrototypeChain); }
StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
- static const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
protected:
void finishCreation(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, JSObject* object)
{
- Base::finishCreation(exec->globalData());
+ Base::finishCreation(exec->vm());
PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
for (size_t i = 0; i < m_jsStringsSize; ++i)
- m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].string()));
+ m_jsStrings[i].set(exec->vm(), this, jsOwnedString(exec, propertyNameVector[i].string()));
m_cachedStructureInlineCapacity = object->structure()->inlineCapacity();
}
@@ -98,20 +98,19 @@ namespace JSC {
OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings;
};
- inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache)
+ ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
{
- ASSERT(!isDictionary());
- m_enumerationCache.set(globalData, this, enumerationCache);
+ return jsCast<JSPropertyNameIterator*>(jsValue().asCell());
}
- inline JSPropertyNameIterator* Structure::enumerationCache()
+ inline JSPropertyNameIterator* StructureRareData::enumerationCache()
{
return m_enumerationCache.get();
}
-
- ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
+
+ inline void StructureRareData::setEnumerationCache(VM& vm, const Structure* owner, JSPropertyNameIterator* value)
{
- return jsCast<JSPropertyNameIterator*>(jsValue().asCell());
+ m_enumerationCache.set(vm, owner, value);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSProxy.cpp b/Source/JavaScriptCore/runtime/JSProxy.cpp
index 7108dcfa0..e0f9d69e6 100644
--- a/Source/JavaScriptCore/runtime/JSProxy.cpp
+++ b/Source/JavaScriptCore/runtime/JSProxy.cpp
@@ -27,6 +27,7 @@
#include "JSProxy.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
namespace JSC {
@@ -46,12 +47,21 @@ void JSProxy::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitor.append(&thisObject->m_target);
}
-void JSProxy::setTarget(JSGlobalData& globalData, JSGlobalObject* globalObject)
+void JSProxy::setTarget(VM& vm, JSGlobalObject* globalObject)
{
ASSERT_ARG(globalObject, globalObject);
- m_target.set(globalData, this, globalObject);
- setPrototype(globalData, globalObject->prototype());
- resetInheritorID(globalData);
+ m_target.set(vm, this, globalObject);
+ setPrototype(vm, globalObject->prototype());
+
+ PrototypeMap& prototypeMap = vm.prototypeMap;
+ if (!prototypeMap.isPrototype(this))
+ return;
+
+ // This is slow but constant time. We think it's very rare for a proxy
+ // to be a prototype, and reasonably rare to retarget a proxy,
+ // so slow constant time is OK.
+ for (size_t i = 0; i <= JSFinalObject::maxInlineCapacity(); ++i)
+ prototypeMap.clearEmptyObjectStructureForPrototype(this, i);
}
String JSProxy::className(const JSObject* object)
diff --git a/Source/JavaScriptCore/runtime/JSProxy.h b/Source/JavaScriptCore/runtime/JSProxy.h
index 144085a79..9b6bed52e 100644
--- a/Source/JavaScriptCore/runtime/JSProxy.h
+++ b/Source/JavaScriptCore/runtime/JSProxy.h
@@ -34,16 +34,16 @@ class JSProxy : public JSDestructibleObject {
public:
typedef JSDestructibleObject Base;
- static JSProxy* create(JSGlobalData& globalData, Structure* structure, JSObject* target)
+ static JSProxy* create(VM& vm, Structure* structure, JSObject* target)
{
- JSProxy* proxy = new (NotNull, allocateCell<JSProxy>(globalData.heap)) JSProxy(globalData, structure);
- proxy->finishCreation(globalData, target);
+ JSProxy* proxy = new (NotNull, allocateCell<JSProxy>(vm.heap)) JSProxy(vm, structure);
+ proxy->finishCreation(vm, target);
return proxy;
}
- 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(ProxyType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ProxyType, StructureFlags), &s_info);
}
static JS_EXPORTDATA const ClassInfo s_info;
@@ -51,27 +51,27 @@ public:
JSObject* target() const { return m_target.get(); }
protected:
- JSProxy(JSGlobalData& globalData, Structure* structure)
- : JSDestructibleObject(globalData, structure)
+ JSProxy(VM& vm, Structure* structure)
+ : JSDestructibleObject(vm, structure)
{
}
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
}
- void finishCreation(JSGlobalData& globalData, JSObject* target)
+ void finishCreation(VM& vm, JSObject* target)
{
- Base::finishCreation(globalData);
- m_target.set(globalData, this, target);
+ Base::finishCreation(vm);
+ m_target.set(vm, this, target);
}
- static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags;
+ static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | Base::StructureFlags;
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- JS_EXPORT_PRIVATE void setTarget(JSGlobalData&, JSGlobalObject*);
+ JS_EXPORT_PRIVATE void setTarget(VM&, JSGlobalObject*);
JS_EXPORT_PRIVATE static String className(const JSObject*);
JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp
index 8651a76ba..69ff1e478 100644
--- a/Source/JavaScriptCore/runtime/JSScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSScope.cpp
@@ -30,6 +30,7 @@
#include "JSGlobalObject.h"
#include "JSNameScope.h"
#include "JSWithScope.h"
+#include "Operations.h"
namespace JSC {
@@ -56,7 +57,7 @@ bool JSScope::isDynamicScope(bool& requiresDynamicChecks) const
case NameScopeObjectType:
return static_cast<const JSNameScope*>(this)->isDynamicScope(requiresDynamicChecks);
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
break;
}
@@ -166,7 +167,7 @@ static bool executeResolveOperations(CallFrame* callFrame, JSScope* scope, const
case ResolveOperation::GetAndReturnGlobalProperty: {
JSGlobalObject* globalObject = scope->globalObject();
if (globalObject->structure() == pc->m_structure.get()) {
- result.setValue(globalObject->getDirectOffset(pc->m_offset));
+ result.setValue(globalObject->getDirect(pc->m_offset));
return true;
}
@@ -186,7 +187,7 @@ static bool executeResolveOperations(CallFrame* callFrame, JSScope* scope, const
return true;
}
- pc->m_structure.set(callFrame->globalData(), callFrame->codeBlock()->ownerExecutable(), structure);
+ pc->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), structure);
pc->m_offset = slot.cachedOffset();
result.setValue(value);
return true;
@@ -302,7 +303,7 @@ template <JSScope::LookupMode mode, JSScope::ReturnValues returnValues> JSObject
if (putToBaseOperation) {
putToBaseOperation->m_isDynamic = requiresDynamicChecks;
putToBaseOperation->m_kind = PutToBaseOperation::GlobalPropertyPut;
- putToBaseOperation->m_structure.set(callFrame->globalData(), callFrame->codeBlock()->ownerExecutable(), globalObject->structure());
+ putToBaseOperation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), globalObject->structure());
setPutPropertyAccessOffset(putToBaseOperation, slot.cachedOffset());
}
switch (returnValues) {
@@ -345,7 +346,7 @@ template <JSScope::LookupMode mode, JSScope::ReturnValues returnValues> JSObject
if (putToBaseOperation) {
putToBaseOperation->m_kind = entry.isReadOnly() ? PutToBaseOperation::Readonly : PutToBaseOperation::VariablePut;
- putToBaseOperation->m_structure.set(callFrame->globalData(), callFrame->codeBlock()->ownerExecutable(), callFrame->lexicalGlobalObject()->activationStructure());
+ putToBaseOperation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), callFrame->lexicalGlobalObject()->activationStructure());
putToBaseOperation->m_offset = entry.getIndex();
putToBaseOperation->m_scopeDepth = (skipTopScopeNode ? 1 : 0) + scopeCount;
}
@@ -498,7 +499,7 @@ JSValue JSScope::resolveWithBase(CallFrame* callFrame, const Identifier& identif
if (JSObject* propertyBase = JSScope::resolveContainingScope<ReturnBaseAndValue>(callFrame, identifier, slot, operations, putToBaseOperations, false)) {
ASSERT(operations->size());
JSValue value = slot.getValue(callFrame, identifier);
- if (callFrame->globalData().exception)
+ if (callFrame->vm().exception)
return JSValue();
*base = propertyBase;
@@ -528,7 +529,7 @@ JSValue JSScope::resolveWithThis(CallFrame* callFrame, const Identifier& identif
if (JSObject* propertyBase = JSScope::resolveContainingScope<ReturnThisAndValue>(callFrame, identifier, slot, operations, 0, false)) {
ASSERT(operations->size());
JSValue value = slot.getValue(callFrame, identifier);
- if (callFrame->globalData().exception)
+ if (callFrame->vm().exception)
return JSValue();
ASSERT(value);
*base = propertyBase->structure()->typeInfo().isEnvironmentRecord() ? jsUndefined() : JSValue(propertyBase);
@@ -563,7 +564,7 @@ void JSScope::resolvePut(CallFrame* callFrame, JSValue base, const Identifier& p
goto genericHandler;
}
}
- operation->m_registerAddress->set(callFrame->globalData(), base.asCell(), value);
+ operation->m_registerAddress->set(callFrame->vm(), base.asCell(), value);
return;
case PutToBaseOperation::VariablePut: {
@@ -573,7 +574,7 @@ void JSScope::resolvePut(CallFrame* callFrame, JSValue base, const Identifier& p
goto genericHandler;
}
JSVariableObject* variableObject = jsCast<JSVariableObject*>(base);
- variableObject->registerAt(operation->m_offset).set(callFrame->globalData(), variableObject, value);
+ variableObject->registerAt(operation->m_offset).set(callFrame->vm(), variableObject, value);
return;
}
@@ -581,7 +582,7 @@ void JSScope::resolvePut(CallFrame* callFrame, JSValue base, const Identifier& p
JSObject* object = jsCast<JSObject*>(base);
if (operation->m_structure.get() != object->structure())
break;
- object->putDirectOffset(callFrame->globalData(), operation->m_offset, value);
+ object->putDirect(callFrame->vm(), operation->m_offset, value);
return;
}
@@ -606,7 +607,7 @@ void JSScope::resolvePut(CallFrame* callFrame, JSValue base, const Identifier& p
if (slot.base() != baseObject)
return;
ASSERT(!baseObject->hasInlineStorage());
- operation->m_structure.set(callFrame->globalData(), callFrame->codeBlock()->ownerExecutable(), baseObject->structure());
+ operation->m_structure.set(callFrame->vm(), callFrame->codeBlock()->ownerExecutable(), baseObject->structure());
setPutPropertyAccessOffset(operation, slot.cachedOffset());
return;
}
diff --git a/Source/JavaScriptCore/runtime/JSScope.h b/Source/JavaScriptCore/runtime/JSScope.h
index a9a9dd8d8..95db8ad56 100644
--- a/Source/JavaScriptCore/runtime/JSScope.h
+++ b/Source/JavaScriptCore/runtime/JSScope.h
@@ -59,11 +59,11 @@ public:
int localDepth();
JSGlobalObject* globalObject();
- JSGlobalData* globalData();
+ VM* vm();
JSObject* globalThis();
protected:
- JSScope(JSGlobalData&, Structure*, JSScope* next);
+ JSScope(VM&, Structure*, JSScope* next);
static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
private:
@@ -80,9 +80,9 @@ private:
template <ReturnValues> static JSObject* resolveContainingScope(CallFrame*, const Identifier&, PropertySlot&, ResolveOperations*, PutToBaseOperation*, bool isStrict);
};
-inline JSScope::JSScope(JSGlobalData& globalData, Structure* structure, JSScope* next)
- : Base(globalData, structure)
- , m_next(globalData, this, next, WriteBarrier<JSScope>::MayBeNull)
+inline JSScope::JSScope(VM& vm, Structure* structure, JSScope* next)
+ : Base(vm, structure)
+ , m_next(vm, this, next, WriteBarrier<JSScope>::MayBeNull)
{
}
@@ -127,9 +127,9 @@ inline JSGlobalObject* JSScope::globalObject()
return structure()->globalObject();
}
-inline JSGlobalData* JSScope::globalData()
+inline VM* JSScope::vm()
{
- return Heap::heap(this)->globalData();
+ return Heap::heap(this)->vm();
}
inline Register& Register::operator=(JSScope* scope)
@@ -143,10 +143,10 @@ inline JSScope* Register::scope() const
return jsCast<JSScope*>(jsValue());
}
-inline JSGlobalData& ExecState::globalData() const
+inline VM& ExecState::vm() const
{
- ASSERT(scope()->globalData());
- return *scope()->globalData();
+ ASSERT(scope()->vm());
+ return *scope()->vm();
}
inline JSGlobalObject* ExecState::lexicalGlobalObject() const
diff --git a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
index c65d2b1b9..01c070451 100644
--- a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp
@@ -29,6 +29,8 @@
#include "config.h"
#include "JSSegmentedVariableObject.h"
+#include "Operations.h"
+
namespace JSC {
int JSSegmentedVariableObject::findRegisterIndex(void* registerAddress)
diff --git a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h
index 1fd96c17a..3a6f625ce 100644
--- a/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h
@@ -35,7 +35,6 @@
#include "SymbolTable.h"
#include <wtf/OwnArrayPtr.h>
#include <wtf/SegmentedVector.h>
-#include <wtf/UnusedParam.h>
namespace JSC {
@@ -82,14 +81,14 @@ public:
protected:
static const unsigned StructureFlags = OverridesVisitChildren | JSSymbolTableObject::StructureFlags;
- JSSegmentedVariableObject(JSGlobalData& globalData, Structure* structure, JSScope* scope)
- : JSSymbolTableObject(globalData, structure, scope)
+ JSSegmentedVariableObject(VM& vm, Structure* structure, JSScope* scope)
+ : JSSymbolTableObject(vm, structure, scope)
{
}
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
}
SegmentedVector<WriteBarrier<Unknown>, 16> m_registers;
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index f0e796d89..86704d715 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -40,7 +40,7 @@ void JSRopeString::RopeBuilder::expand()
{
ASSERT(m_index == JSRopeString::s_maxInternalRopeLength);
JSString* jsString = m_jsString;
- m_jsString = jsStringBuilder(&m_globalData);
+ m_jsString = jsStringBuilder(&m_vm);
m_index = 0;
append(jsString);
}
@@ -154,7 +154,7 @@ void JSRopeString::resolveRope(ExecState* exec) const
void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
{
LChar* position = buffer + m_length; // We will be working backwards over the rope.
- Vector<JSString*, 32> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
+ Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
workQueue.append(m_fibers[i].get());
@@ -186,7 +186,7 @@ void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
void JSRopeString::resolveRopeSlowCase(UChar* buffer) const
{
UChar* position = buffer + m_length; // We will be working backwards over the rope.
- Vector<JSString*, 32> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
+ Vector<JSString*, 32, UnsafeVectorOverflow> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
workQueue.append(m_fibers[i].get());
@@ -233,7 +233,7 @@ JSString* JSRopeString::getIndexSlowCase(ExecState* exec, unsigned i)
if (exec->exception())
return jsEmptyString(exec);
ASSERT(!isRope());
- ASSERT(i < m_value.length());
+ RELEASE_ASSERT(i < m_value.length());
return jsSingleCharacterSubstring(exec, m_value, i);
}
@@ -261,8 +261,8 @@ double JSString::toNumber(ExecState* exec) const
inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
{
- StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), globalObject->stringObjectStructure());
- object->finishCreation(exec->globalData(), string);
+ StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->vm(), globalObject->stringObjectStructure());
+ object->finishCreation(exec->vm(), string);
return object;
}
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 245c48a51..855de974d 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -31,525 +31,523 @@
namespace JSC {
- class JSString;
- class JSRopeString;
- class LLIntOffsetsExtractor;
-
- JSString* jsEmptyString(JSGlobalData*);
- JSString* jsEmptyString(ExecState*);
- JSString* jsString(JSGlobalData*, const String&); // returns empty string if passed null string
- JSString* jsString(ExecState*, const String&); // returns empty string if passed null string
-
- JSString* jsSingleCharacterString(JSGlobalData*, UChar);
- JSString* jsSingleCharacterString(ExecState*, UChar);
- JSString* jsSingleCharacterSubstring(ExecState*, const String&, unsigned offset);
- JSString* jsSubstring(JSGlobalData*, const String&, unsigned offset, unsigned length);
- JSString* jsSubstring(ExecState*, const String&, unsigned offset, unsigned length);
-
- // Non-trivial strings are two or more characters long.
- // These functions are faster than just calling jsString.
- JSString* jsNontrivialString(JSGlobalData*, const String&);
- JSString* jsNontrivialString(ExecState*, const String&);
-
- // Should be used for strings that are owned by an object that will
- // likely outlive the JSValue this makes, such as the parse tree or a
- // DOM object that contains a String
- JSString* jsOwnedString(JSGlobalData*, const String&);
- JSString* jsOwnedString(ExecState*, const String&);
-
- JSRopeString* jsStringBuilder(JSGlobalData*);
-
- class JSString : public JSCell {
- public:
- friend class JIT;
- friend class JSGlobalData;
- friend class SpecializedThunkJIT;
- friend class JSRopeString;
- friend class MarkStack;
- friend class SlotVisitor;
- friend struct ThunkHelpers;
-
- typedef JSCell Base;
-
- static const bool needsDestruction = true;
- static const bool hasImmortalStructure = true;
- static void destroy(JSCell*);
-
- private:
- JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
- : JSCell(globalData, globalData.stringStructure.get())
- , m_flags(0)
- , m_value(value)
- {
- }
+class JSString;
+class JSRopeString;
+class LLIntOffsetsExtractor;
+
+JSString* jsEmptyString(VM*);
+JSString* jsEmptyString(ExecState*);
+JSString* jsString(VM*, const String&); // returns empty string if passed null string
+JSString* jsString(ExecState*, const String&); // returns empty string if passed null string
+
+JSString* jsSingleCharacterString(VM*, UChar);
+JSString* jsSingleCharacterString(ExecState*, UChar);
+JSString* jsSingleCharacterSubstring(ExecState*, const String&, unsigned offset);
+JSString* jsSubstring(VM*, const String&, unsigned offset, unsigned length);
+JSString* jsSubstring(ExecState*, const String&, unsigned offset, unsigned length);
+
+// Non-trivial strings are two or more characters long.
+// These functions are faster than just calling jsString.
+JSString* jsNontrivialString(VM*, const String&);
+JSString* jsNontrivialString(ExecState*, const String&);
+
+// Should be used for strings that are owned by an object that will
+// likely outlive the JSValue this makes, such as the parse tree or a
+// DOM object that contains a String
+JSString* jsOwnedString(VM*, const String&);
+JSString* jsOwnedString(ExecState*, const String&);
+
+JSRopeString* jsStringBuilder(VM*);
+
+class JSString : public JSCell {
+public:
+ friend class JIT;
+ friend class VM;
+ friend class SpecializedThunkJIT;
+ friend class JSRopeString;
+ friend class MarkStack;
+ friend class SlotVisitor;
+ friend struct ThunkHelpers;
+
+ typedef JSCell Base;
+
+ static const bool needsDestruction = true;
+ static const bool hasImmortalStructure = true;
+ static void destroy(JSCell*);
+
+private:
+ JSString(VM& vm, PassRefPtr<StringImpl> value)
+ : JSCell(vm, vm.stringStructure.get())
+ , m_flags(0)
+ , m_value(value)
+ {
+ }
- JSString(JSGlobalData& globalData)
- : JSCell(globalData, globalData.stringStructure.get())
- , m_flags(0)
- {
- }
+ JSString(VM& vm)
+ : JSCell(vm, vm.stringStructure.get())
+ , m_flags(0)
+ {
+ }
- void finishCreation(JSGlobalData& globalData, size_t length)
- {
- ASSERT(!m_value.isNull());
- Base::finishCreation(globalData);
- m_length = length;
- setIs8Bit(m_value.impl()->is8Bit());
- globalData.m_newStringsSinceLastHashConst++;
- }
+ void finishCreation(VM& vm, size_t length)
+ {
+ ASSERT(!m_value.isNull());
+ Base::finishCreation(vm);
+ m_length = length;
+ setIs8Bit(m_value.impl()->is8Bit());
+ vm.m_newStringsSinceLastHashCons++;
+ }
- void finishCreation(JSGlobalData& globalData, size_t length, size_t cost)
- {
- ASSERT(!m_value.isNull());
- Base::finishCreation(globalData);
- m_length = length;
- setIs8Bit(m_value.impl()->is8Bit());
- Heap::heap(this)->reportExtraMemoryCost(cost);
- globalData.m_newStringsSinceLastHashConst++;
- }
+ void finishCreation(VM& vm, size_t length, size_t cost)
+ {
+ ASSERT(!m_value.isNull());
+ Base::finishCreation(vm);
+ m_length = length;
+ setIs8Bit(m_value.impl()->is8Bit());
+ Heap::heap(this)->reportExtraMemoryCost(cost);
+ vm.m_newStringsSinceLastHashCons++;
+ }
- protected:
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- m_length = 0;
- setIs8Bit(true);
- globalData.m_newStringsSinceLastHashConst++;
- }
+protected:
+ void finishCreation(VM& vm)
+ {
+ Base::finishCreation(vm);
+ m_length = 0;
+ setIs8Bit(true);
+ vm.m_newStringsSinceLastHashCons++;
+ }
- public:
- static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
- {
- ASSERT(value);
- size_t length = value->length();
- size_t cost = value->cost();
- JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData, value);
- newString->finishCreation(globalData, length, cost);
- return newString;
- }
- static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
- {
- ASSERT(value);
- size_t length = value->length();
- JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData, value);
- newString->finishCreation(globalData, length);
- return newString;
- }
+public:
+ static JSString* create(VM& vm, PassRefPtr<StringImpl> value)
+ {
+ ASSERT(value);
+ size_t length = value->length();
+ size_t cost = value->cost();
+ JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
+ newString->finishCreation(vm, length, cost);
+ return newString;
+ }
+ static JSString* createHasOtherOwner(VM& vm, PassRefPtr<StringImpl> value)
+ {
+ ASSERT(value);
+ size_t length = value->length();
+ JSString* newString = new (NotNull, allocateCell<JSString>(vm.heap)) JSString(vm, value);
+ newString->finishCreation(vm, length);
+ return newString;
+ }
- const String& value(ExecState*) const;
- const String& tryGetValue() const;
- unsigned length() { return m_length; }
+ const String& value(ExecState*) const;
+ const String& tryGetValue() const;
+ unsigned length() { return m_length; }
- JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- JS_EXPORT_PRIVATE bool toBoolean() const;
- bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
- JSObject* toObject(ExecState*, JSGlobalObject*) const;
- double toNumber(ExecState*) const;
+ JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ JS_EXPORT_PRIVATE bool toBoolean() const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+ JSObject* toObject(ExecState*, JSGlobalObject*) const;
+ double toNumber(ExecState*) const;
- bool getStringPropertySlot(ExecState*, PropertyName, PropertySlot&);
- bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- bool getStringPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
+ bool getStringPropertySlot(ExecState*, PropertyName, PropertySlot&);
+ bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ bool getStringPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
- bool canGetIndex(unsigned i) { return i < m_length; }
- JSString* getIndex(ExecState*, unsigned);
+ bool canGetIndex(unsigned i) { return i < m_length; }
+ JSString* getIndex(ExecState*, unsigned);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
- {
- return Structure::create(globalData, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero), &s_info);
- }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
+ {
+ return Structure::create(vm, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero), &s_info);
+ }
- static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
- static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
+ static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); }
+ static size_t offsetOfFlags() { return OBJECT_OFFSETOF(JSString, m_flags); }
+ static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); }
- static JS_EXPORTDATA const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
- static void visitChildren(JSCell*, SlotVisitor&);
+ static void visitChildren(JSCell*, SlotVisitor&);
- protected:
- bool isRope() const { return m_value.isNull(); }
- bool is8Bit() const { return m_flags & Is8Bit; }
- void setIs8Bit(bool flag)
- {
- if (flag)
- m_flags |= Is8Bit;
- else
- m_flags &= ~Is8Bit;
- }
- bool shouldTryHashConst();
- bool isHashConstSingleton() const { return m_flags & IsHashConstSingleton; }
- void clearHashConstSingleton() { m_flags &= ~IsHashConstSingleton; }
- void setHashConstSingleton() { m_flags |= IsHashConstSingleton; }
- bool tryHashConstLock();
- void releaseHashConstLock();
-
- unsigned m_flags;
-
- enum {
- HashConstLock = 1u << 2,
- IsHashConstSingleton = 1u << 1,
- Is8Bit = 1u
- };
+ enum {
+ HashConsLock = 1u << 2,
+ IsHashConsSingleton = 1u << 1,
+ Is8Bit = 1u
+ };
- // A string is represented either by a String or a rope of fibers.
- unsigned m_length;
- mutable String m_value;
+protected:
+ friend class JSValue;
+
+ bool isRope() const { return m_value.isNull(); }
+ bool is8Bit() const { return m_flags & Is8Bit; }
+ void setIs8Bit(bool flag)
+ {
+ if (flag)
+ m_flags |= Is8Bit;
+ else
+ m_flags &= ~Is8Bit;
+ }
+ bool shouldTryHashCons();
+ bool isHashConsSingleton() const { return m_flags & IsHashConsSingleton; }
+ void clearHashConsSingleton() { m_flags &= ~IsHashConsSingleton; }
+ void setHashConsSingleton() { m_flags |= IsHashConsSingleton; }
+ bool tryHashConsLock();
+ void releaseHashConsLock();
+
+ unsigned m_flags;
+
+ // A string is represented either by a String or a rope of fibers.
+ unsigned m_length;
+ mutable String m_value;
- private:
- friend class LLIntOffsetsExtractor;
+private:
+ friend class LLIntOffsetsExtractor;
- static JSObject* toThisObject(JSCell*, ExecState*);
+ static JSObject* toThisObject(JSCell*, ExecState*);
- // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+ // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
+ static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
+ static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
- String& string() { ASSERT(!isRope()); return m_value; }
+ String& string() { ASSERT(!isRope()); return m_value; }
- friend JSValue jsString(ExecState*, JSString*, JSString*);
- friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
- };
+ friend JSValue jsString(ExecState*, JSString*, JSString*);
+ friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
+};
- class JSRopeString : public JSString {
- friend class JSString;
+class JSRopeString : public JSString {
+ friend class JSString;
- friend JSRopeString* jsStringBuilder(JSGlobalData*);
+ friend JSRopeString* jsStringBuilder(VM*);
- class RopeBuilder {
- public:
- RopeBuilder(JSGlobalData& globalData)
- : m_globalData(globalData)
- , m_jsString(jsStringBuilder(&globalData))
+ class RopeBuilder {
+ public:
+ RopeBuilder(VM& vm)
+ : m_vm(vm)
+ , m_jsString(jsStringBuilder(&vm))
, m_index(0)
- {
- }
-
- void append(JSString* jsString)
- {
- if (m_index == JSRopeString::s_maxInternalRopeLength)
- expand();
- m_jsString->append(m_globalData, m_index++, jsString);
- }
-
- JSRopeString* release()
- {
- JSRopeString* tmp = m_jsString;
- m_jsString = 0;
- return tmp;
- }
-
- unsigned length() { return m_jsString->m_length; }
-
- private:
- void expand();
-
- JSGlobalData& m_globalData;
- JSRopeString* m_jsString;
- size_t m_index;
- };
-
- private:
- JSRopeString(JSGlobalData& globalData)
- : JSString(globalData)
- {
- }
-
- void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2)
- {
- Base::finishCreation(globalData);
- m_length = s1->length() + s2->length();
- setIs8Bit(s1->is8Bit() && s2->is8Bit());
- m_fibers[0].set(globalData, this, s1);
- m_fibers[1].set(globalData, this, s2);
- }
-
- void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
{
- Base::finishCreation(globalData);
- m_length = s1->length() + s2->length() + s3->length();
- setIs8Bit(s1->is8Bit() && s2->is8Bit() && s3->is8Bit());
- m_fibers[0].set(globalData, this, s1);
- m_fibers[1].set(globalData, this, s2);
- m_fibers[2].set(globalData, this, s3);
}
- void finishCreation(JSGlobalData& globalData)
+ void append(JSString* jsString)
{
- JSString::finishCreation(globalData);
+ if (m_index == JSRopeString::s_maxInternalRopeLength)
+ expand();
+ m_jsString->append(m_vm, m_index++, jsString);
}
- void append(JSGlobalData& globalData, size_t index, JSString* jsString)
- {
- m_fibers[index].set(globalData, this, jsString);
- m_length += jsString->m_length;
- setIs8Bit(is8Bit() && jsString->is8Bit());
- }
-
- static JSRopeString* createNull(JSGlobalData& globalData)
- {
- JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
- newString->finishCreation(globalData);
- return newString;
- }
-
- public:
- static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2)
- {
- JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
- newString->finishCreation(globalData, s1, s2);
- return newString;
- }
- static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
+ JSRopeString* release()
{
- JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
- newString->finishCreation(globalData, s1, s2, s3);
- return newString;
+ JSRopeString* tmp = m_jsString;
+ m_jsString = 0;
+ return tmp;
}
- void visitFibers(SlotVisitor&);
+ unsigned length() { return m_jsString->m_length; }
private:
- friend JSValue jsString(ExecState*, Register*, unsigned);
- friend JSValue jsStringFromArguments(ExecState*, JSValue);
-
- JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
- void resolveRopeSlowCase8(LChar*) const;
- void resolveRopeSlowCase(UChar*) const;
- void outOfMemory(ExecState*) const;
-
- JSString* getIndexSlowCase(ExecState*, unsigned);
-
- static const unsigned s_maxInternalRopeLength = 3;
-
- mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
+ void expand();
+
+ VM& m_vm;
+ JSRopeString* m_jsString;
+ size_t m_index;
};
-
- JSString* asString(JSValue);
-
- inline JSString* asString(JSValue value)
+
+private:
+ JSRopeString(VM& vm)
+ : JSString(vm)
{
- ASSERT(value.asCell()->isString());
- return jsCast<JSString*>(value.asCell());
}
- inline JSString* jsEmptyString(JSGlobalData* globalData)
+ void finishCreation(VM& vm, JSString* s1, JSString* s2)
{
- return globalData->smallStrings.emptyString(globalData);
+ Base::finishCreation(vm);
+ m_length = s1->length() + s2->length();
+ setIs8Bit(s1->is8Bit() && s2->is8Bit());
+ m_fibers[0].set(vm, this, s1);
+ m_fibers[1].set(vm, this, s2);
}
-
- ALWAYS_INLINE JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
+
+ void finishCreation(VM& vm, JSString* s1, JSString* s2, JSString* s3)
{
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- return JSString::create(*globalData, String(&c, 1).impl());
+ Base::finishCreation(vm);
+ m_length = s1->length() + s2->length() + s3->length();
+ setIs8Bit(s1->is8Bit() && s2->is8Bit() && s3->is8Bit());
+ m_fibers[0].set(vm, this, s1);
+ m_fibers[1].set(vm, this, s2);
+ m_fibers[2].set(vm, this, s3);
}
- ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const String& s, unsigned offset)
+ void finishCreation(VM& vm)
{
- JSGlobalData* globalData = &exec->globalData();
- ASSERT(offset < static_cast<unsigned>(s.length()));
- UChar c = s.characterAt(offset);
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- return JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1));
+ JSString::finishCreation(vm);
}
- inline JSString* jsNontrivialString(JSGlobalData* globalData, const String& s)
+ void append(VM& vm, size_t index, JSString* jsString)
{
- ASSERT(s.length() > 1);
- return JSString::create(*globalData, s.impl());
+ m_fibers[index].set(vm, this, jsString);
+ m_length += jsString->m_length;
+ setIs8Bit(is8Bit() && jsString->is8Bit());
}
- inline const String& JSString::value(ExecState* exec) const
+ static JSRopeString* createNull(VM& vm)
{
- if (isRope())
- static_cast<const JSRopeString*>(this)->resolveRope(exec);
- return m_value;
+ JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
+ newString->finishCreation(vm);
+ return newString;
}
- inline const String& JSString::tryGetValue() const
+public:
+ static JSString* create(VM& vm, JSString* s1, JSString* s2)
{
- if (isRope())
- static_cast<const JSRopeString*>(this)->resolveRope(0);
- return m_value;
+ JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
+ newString->finishCreation(vm, s1, s2);
+ return newString;
}
-
- inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
+ static JSString* create(VM& vm, JSString* s1, JSString* s2, JSString* s3)
{
- ASSERT(canGetIndex(i));
- if (isRope())
- return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
- ASSERT(i < m_value.length());
- return jsSingleCharacterSubstring(exec, m_value, i);
+ JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(vm.heap)) JSRopeString(vm);
+ newString->finishCreation(vm, s1, s2, s3);
+ return newString;
}
- inline JSString* jsString(JSGlobalData* globalData, const String& s)
- {
- int size = s.length();
- if (!size)
- return globalData->smallStrings.emptyString(globalData);
- if (size == 1) {
- UChar c = s.characterAt(0);
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return JSString::create(*globalData, s.impl());
- }
+ void visitFibers(SlotVisitor&);
+
+ static ptrdiff_t offsetOfFibers() { return OBJECT_OFFSETOF(JSRopeString, m_fibers); }
- inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
- {
- ASSERT(offset <= static_cast<unsigned>(s->length()));
- ASSERT(length <= static_cast<unsigned>(s->length()));
- ASSERT(offset + length <= static_cast<unsigned>(s->length()));
- JSGlobalData* globalData = &exec->globalData();
- if (!length)
- return globalData->smallStrings.emptyString(globalData);
- return jsSubstring(globalData, s->value(exec), offset, length);
+ static const unsigned s_maxInternalRopeLength = 3;
+
+private:
+ friend JSValue jsString(ExecState*, Register*, unsigned);
+ friend JSValue jsStringFromArguments(ExecState*, JSValue);
+
+ JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
+ void resolveRopeSlowCase8(LChar*) const;
+ void resolveRopeSlowCase(UChar*) const;
+ void outOfMemory(ExecState*) const;
+
+ JSString* getIndexSlowCase(ExecState*, unsigned);
+
+ mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
+};
+
+JSString* asString(JSValue);
+
+inline JSString* asString(JSValue value)
+{
+ ASSERT(value.asCell()->isString());
+ return jsCast<JSString*>(value.asCell());
+}
+
+inline JSString* jsEmptyString(VM* vm)
+{
+ return vm->smallStrings.emptyString();
+}
+
+ALWAYS_INLINE JSString* jsSingleCharacterString(VM* vm, UChar c)
+{
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
+ return JSString::create(*vm, String(&c, 1).impl());
+}
+
+ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const String& s, unsigned offset)
+{
+ VM* vm = &exec->vm();
+ ASSERT(offset < static_cast<unsigned>(s.length()));
+ UChar c = s.characterAt(offset);
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
+ return JSString::create(*vm, StringImpl::create(s.impl(), offset, 1));
+}
+
+inline JSString* jsNontrivialString(VM* vm, const String& s)
+{
+ ASSERT(s.length() > 1);
+ return JSString::create(*vm, s.impl());
+}
+
+inline const String& JSString::value(ExecState* exec) const
+{
+ if (isRope())
+ static_cast<const JSRopeString*>(this)->resolveRope(exec);
+ return m_value;
+}
+
+inline const String& JSString::tryGetValue() const
+{
+ if (isRope())
+ static_cast<const JSRopeString*>(this)->resolveRope(0);
+ return m_value;
+}
+
+inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
+{
+ ASSERT(canGetIndex(i));
+ if (isRope())
+ return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
+ ASSERT(i < m_value.length());
+ return jsSingleCharacterSubstring(exec, m_value, i);
+}
+
+inline JSString* jsString(VM* vm, const String& s)
+{
+ int size = s.length();
+ if (!size)
+ return vm->smallStrings.emptyString();
+ if (size == 1) {
+ UChar c = s.characterAt(0);
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
}
-
- inline JSString* jsSubstring8(JSGlobalData* globalData, const String& s, unsigned offset, unsigned length)
- {
- ASSERT(offset <= static_cast<unsigned>(s.length()));
- ASSERT(length <= static_cast<unsigned>(s.length()));
- ASSERT(offset + length <= static_cast<unsigned>(s.length()));
- if (!length)
- return globalData->smallStrings.emptyString(globalData);
- if (length == 1) {
- UChar c = s.characterAt(offset);
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length));
+ return JSString::create(*vm, s.impl());
+}
+
+inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
+{
+ ASSERT(offset <= static_cast<unsigned>(s->length()));
+ ASSERT(length <= static_cast<unsigned>(s->length()));
+ ASSERT(offset + length <= static_cast<unsigned>(s->length()));
+ VM* vm = &exec->vm();
+ if (!length)
+ return vm->smallStrings.emptyString();
+ return jsSubstring(vm, s->value(exec), offset, length);
+}
+
+inline JSString* jsSubstring8(VM* vm, const String& s, unsigned offset, unsigned length)
+{
+ ASSERT(offset <= static_cast<unsigned>(s.length()));
+ ASSERT(length <= static_cast<unsigned>(s.length()));
+ ASSERT(offset + length <= static_cast<unsigned>(s.length()));
+ if (!length)
+ return vm->smallStrings.emptyString();
+ if (length == 1) {
+ UChar c = s.characterAt(offset);
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
}
-
- inline JSString* jsSubstring(JSGlobalData* globalData, const String& s, unsigned offset, unsigned length)
- {
- ASSERT(offset <= static_cast<unsigned>(s.length()));
- ASSERT(length <= static_cast<unsigned>(s.length()));
- ASSERT(offset + length <= static_cast<unsigned>(s.length()));
- if (!length)
- return globalData->smallStrings.emptyString(globalData);
- if (length == 1) {
- UChar c = s.characterAt(offset);
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length));
+ return JSString::createHasOtherOwner(*vm, StringImpl::create8(s.impl(), offset, length));
+}
+
+inline JSString* jsSubstring(VM* vm, const String& s, unsigned offset, unsigned length)
+{
+ ASSERT(offset <= static_cast<unsigned>(s.length()));
+ ASSERT(length <= static_cast<unsigned>(s.length()));
+ ASSERT(offset + length <= static_cast<unsigned>(s.length()));
+ if (!length)
+ return vm->smallStrings.emptyString();
+ if (length == 1) {
+ UChar c = s.characterAt(offset);
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
}
-
- inline JSString* jsOwnedString(JSGlobalData* globalData, const String& s)
- {
- int size = s.length();
- if (!size)
- return globalData->smallStrings.emptyString(globalData);
- if (size == 1) {
- UChar c = s.characterAt(0);
- if (c <= maxSingleCharacterString)
- return globalData->smallStrings.singleCharacterString(globalData, c);
- }
- return JSString::createHasOtherOwner(*globalData, s.impl());
+ return JSString::createHasOtherOwner(*vm, StringImpl::create(s.impl(), offset, length));
+}
+
+inline JSString* jsOwnedString(VM* vm, const String& s)
+{
+ int size = s.length();
+ if (!size)
+ return vm->smallStrings.emptyString();
+ if (size == 1) {
+ UChar c = s.characterAt(0);
+ if (c <= maxSingleCharacterString)
+ return vm->smallStrings.singleCharacterString(vm, c);
}
-
- inline JSRopeString* jsStringBuilder(JSGlobalData* globalData)
- {
- return JSRopeString::createNull(*globalData);
+ return JSString::createHasOtherOwner(*vm, s.impl());
+}
+
+inline JSRopeString* jsStringBuilder(VM* vm)
+{
+ return JSRopeString::createNull(*vm);
+}
+
+inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->vm()); }
+inline JSString* jsString(ExecState* exec, const String& s) { return jsString(&exec->vm(), s); }
+inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->vm(), c); }
+inline JSString* jsSubstring8(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->vm(), s, offset, length); }
+inline JSString* jsSubstring(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring(&exec->vm(), s, offset, length); }
+inline JSString* jsNontrivialString(ExecState* exec, const String& s) { return jsNontrivialString(&exec->vm(), s); }
+inline JSString* jsOwnedString(ExecState* exec, const String& s) { return jsOwnedString(&exec->vm(), s); }
+
+ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ if (propertyName == exec->propertyNames().length) {
+ slot.setValue(jsNumber(m_length));
+ return true;
}
- inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
- inline JSString* jsString(ExecState* exec, const String& s) { return jsString(&exec->globalData(), s); }
- inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
- inline JSString* jsSubstring8(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->globalData(), s, offset, length); }
- inline JSString* jsSubstring(ExecState* exec, const String& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
- inline JSString* jsNontrivialString(ExecState* exec, const String& s) { return jsNontrivialString(&exec->globalData(), s); }
- inline JSString* jsOwnedString(ExecState* exec, const String& s) { return jsOwnedString(&exec->globalData(), s); }
-
- ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
- {
- if (propertyName == exec->propertyNames().length) {
- slot.setValue(jsNumber(m_length));
- return true;
- }
-
- unsigned i = propertyName.asIndex();
- if (i < m_length) {
- ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
- slot.setValue(getIndex(exec, i));
- return true;
- }
-
- return false;
+ unsigned i = propertyName.asIndex();
+ if (i < m_length) {
+ ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
+ slot.setValue(getIndex(exec, i));
+ return true;
}
-
- ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
- {
- if (propertyName < m_length) {
- slot.setValue(getIndex(exec, propertyName));
- return true;
- }
- return false;
+ return false;
+}
+
+ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ if (propertyName < m_length) {
+ slot.setValue(getIndex(exec, propertyName));
+ return true;
}
- inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
+ return false;
+}
- inline bool JSCell::toBoolean(ExecState* exec) const
- {
- if (isString())
- return static_cast<const JSString*>(this)->toBoolean();
- return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
- }
+inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
- // --- JSValue inlines ----------------------------
+// --- JSValue inlines ----------------------------
- inline bool JSValue::toBoolean(ExecState* exec) const
- {
- if (isInt32())
- return asInt32();
- if (isDouble())
- return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
- if (isCell())
- return asCell()->toBoolean(exec);
- return isTrue(); // false, null, and undefined all convert to false.
- }
-
- inline JSString* JSValue::toString(ExecState* exec) const
- {
- if (isString())
- return jsCast<JSString*>(asCell());
- return toStringSlowCase(exec);
- }
-
- inline String JSValue::toWTFString(ExecState* exec) const
- {
- if (isString())
- return static_cast<JSString*>(asCell())->value(exec);
- return toWTFStringSlowCase(exec);
- }
-
- ALWAYS_INLINE String inlineJSValueNotStringtoString(const JSValue& value, ExecState* exec)
- {
- JSGlobalData& globalData = exec->globalData();
- if (value.isInt32())
- return globalData.numericStrings.add(value.asInt32());
- if (value.isDouble())
- return globalData.numericStrings.add(value.asDouble());
- if (value.isTrue())
- return globalData.propertyNames->trueKeyword.string();
- if (value.isFalse())
- return globalData.propertyNames->falseKeyword.string();
- if (value.isNull())
- return globalData.propertyNames->nullKeyword.string();
- if (value.isUndefined())
- return globalData.propertyNames->undefinedKeyword.string();
- return value.toString(exec)->value(exec);
- }
-
- ALWAYS_INLINE String JSValue::toWTFStringInline(ExecState* exec) const
- {
- if (isString())
- return static_cast<JSString*>(asCell())->value(exec);
-
- return inlineJSValueNotStringtoString(*this, exec);
- }
+inline bool JSValue::toBoolean(ExecState* exec) const
+{
+ if (isInt32())
+ return asInt32();
+ if (isDouble())
+ return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
+ if (isCell())
+ return asCell()->toBoolean(exec);
+ return isTrue(); // false, null, and undefined all convert to false.
+}
+
+inline JSString* JSValue::toString(ExecState* exec) const
+{
+ if (isString())
+ return jsCast<JSString*>(asCell());
+ return toStringSlowCase(exec);
+}
+
+inline String JSValue::toWTFString(ExecState* exec) const
+{
+ if (isString())
+ return static_cast<JSString*>(asCell())->value(exec);
+ return toWTFStringSlowCase(exec);
+}
+
+ALWAYS_INLINE String inlineJSValueNotStringtoString(const JSValue& value, ExecState* exec)
+{
+ VM& vm = exec->vm();
+ if (value.isInt32())
+ return vm.numericStrings.add(value.asInt32());
+ if (value.isDouble())
+ return vm.numericStrings.add(value.asDouble());
+ if (value.isTrue())
+ return vm.propertyNames->trueKeyword.string();
+ if (value.isFalse())
+ return vm.propertyNames->falseKeyword.string();
+ if (value.isNull())
+ return vm.propertyNames->nullKeyword.string();
+ if (value.isUndefined())
+ return vm.propertyNames->undefinedKeyword.string();
+ return value.toString(exec)->value(exec);
+}
+
+ALWAYS_INLINE String JSValue::toWTFStringInline(ExecState* exec) const
+{
+ if (isString())
+ return static_cast<JSString*>(asCell())->value(exec);
+
+ return inlineJSValueNotStringtoString(*this, exec);
+}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSStringBuilder.h b/Source/JavaScriptCore/runtime/JSStringBuilder.h
index e7778e4fb..5d4960e89 100644
--- a/Source/JavaScriptCore/runtime/JSStringBuilder.h
+++ b/Source/JavaScriptCore/runtime/JSStringBuilder.h
@@ -137,8 +137,8 @@ public:
}
protected:
- Vector<LChar, 64> buffer8;
- Vector<UChar, 64> buffer16;
+ Vector<LChar, 64, UnsafeVectorOverflow> buffer8;
+ Vector<UChar, 64, UnsafeVectorOverflow> buffer16;
bool m_okay;
bool m_is8Bit;
};
diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
index cbf9ba48b..7e20d2195 100644
--- a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
+++ b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp
@@ -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
@@ -29,9 +29,9 @@
#include "ExceptionHelpers.h"
#include "JSScope.h"
#include "JSString.h"
+#include "Operations.h"
#include <wtf/text/StringImpl.h>
-
namespace JSC {
// The destination is 16bits, at least one string is 16 bits.
@@ -94,7 +94,7 @@ static inline PassRefPtr<StringImpl> joinStrings(const Vector<String>& strings,
return outputStringImpl.release();
}
-JSValue JSStringJoiner::build(ExecState* exec)
+JSValue JSStringJoiner::join(ExecState* exec)
{
if (!m_isValid)
return throwOutOfMemoryError(exec);
@@ -102,25 +102,29 @@ JSValue JSStringJoiner::build(ExecState* exec)
if (!m_strings.size())
return jsEmptyString(exec);
- size_t separatorLength = m_separator.length();
+ Checked<size_t, RecordOverflow> separatorLength = m_separator.length();
// FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1).
ASSERT(m_strings.size() > 0);
- size_t totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
- size_t outputStringSize = totalSeparactorsLength + m_cumulatedStringsLength;
+ Checked<size_t, RecordOverflow> totalSeparactorsLength = separatorLength * (m_strings.size() - 1);
+ Checked<size_t, RecordOverflow> outputStringSize = totalSeparactorsLength + m_accumulatedStringsLength;
+ size_t finalSize;
+ if (outputStringSize.safeGet(finalSize) == CheckedState::DidOverflow)
+ return throwOutOfMemoryError(exec);
+
if (!outputStringSize)
return jsEmptyString(exec);
RefPtr<StringImpl> outputStringImpl;
if (m_is8Bits)
- outputStringImpl = joinStrings<LChar>(m_strings, m_separator, outputStringSize);
+ outputStringImpl = joinStrings<LChar>(m_strings, m_separator, finalSize);
else
- outputStringImpl = joinStrings<UChar>(m_strings, m_separator, outputStringSize);
+ outputStringImpl = joinStrings<UChar>(m_strings, m_separator, finalSize);
if (!outputStringImpl)
return throwOutOfMemoryError(exec);
- return JSString::create(exec->globalData(), outputStringImpl.release());
+ return JSString::create(exec->vm(), outputStringImpl.release());
}
}
diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.h b/Source/JavaScriptCore/runtime/JSStringJoiner.h
index 5cb841a80..73950c6d7 100644
--- a/Source/JavaScriptCore/runtime/JSStringJoiner.h
+++ b/Source/JavaScriptCore/runtime/JSStringJoiner.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
@@ -26,7 +26,7 @@
#ifndef JSStringJoiner_h
#define JSStringJoiner_h
-#include "JSValue.h"
+#include "JSCJSValue.h"
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
@@ -40,20 +40,19 @@ public:
JSStringJoiner(const String& separator, size_t stringCount);
void append(const String&);
- JSValue build(ExecState*);
+ JSValue join(ExecState*);
private:
String m_separator;
Vector<String> m_strings;
- unsigned m_cumulatedStringsLength;
+ Checked<unsigned, RecordOverflow> m_accumulatedStringsLength;
bool m_isValid;
bool m_is8Bits;
};
inline JSStringJoiner::JSStringJoiner(const String& separator, size_t stringCount)
: m_separator(separator)
- , m_cumulatedStringsLength(0)
, m_isValid(true)
, m_is8Bits(m_separator.is8Bit())
{
@@ -66,9 +65,9 @@ inline void JSStringJoiner::append(const String& str)
if (!m_isValid)
return;
- m_strings.uncheckedAppend(str);
+ m_strings.append(str);
if (!str.isNull()) {
- m_cumulatedStringsLength += str.length();
+ m_accumulatedStringsLength += str.length();
m_is8Bits = m_is8Bits && str.is8Bit();
}
}
diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp b/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
index 7dcde4700..16b20d9db 100644
--- a/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
@@ -32,6 +32,7 @@
#include "JSActivation.h"
#include "JSGlobalObject.h"
#include "JSNameScope.h"
+#include "Operations.h"
#include "PropertyNameArray.h"
namespace JSC {
@@ -70,7 +71,7 @@ void JSSymbolTableObject::getOwnNonIndexPropertyNames(JSObject* object, ExecStat
void JSSymbolTableObject::putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned)
{
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
index 913679f80..6db2b88ab 100644
--- a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
@@ -41,7 +41,7 @@ public:
SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
- static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+ static NO_RETURN_DUE_TO_CRASH void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
@@ -49,18 +49,18 @@ public:
protected:
static const unsigned StructureFlags = IsEnvironmentRecord | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
- JSSymbolTableObject(JSGlobalData& globalData, Structure* structure, JSScope* scope, SharedSymbolTable* symbolTable = 0)
- : Base(globalData, structure, scope)
+ JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SharedSymbolTable* symbolTable = 0)
+ : Base(vm, structure, scope)
{
if (symbolTable)
- m_symbolTable.set(globalData, this, symbolTable);
+ m_symbolTable.set(vm, this, symbolTable);
}
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
if (!m_symbolTable)
- m_symbolTable.set(globalData, this, SharedSymbolTable::create(globalData));
+ m_symbolTable.set(vm, this, SharedSymbolTable::create(vm));
}
static void visitChildren(JSCell*, SlotVisitor&);
@@ -118,7 +118,7 @@ inline bool symbolTablePut(
SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
bool shouldThrow)
{
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
SymbolTable& symbolTable = *object->symbolTable();
@@ -135,13 +135,13 @@ inline bool symbolTablePut(
}
if (UNLIKELY(wasFat))
iter->value.notifyWrite();
- object->registerAt(fastEntry.getIndex()).set(globalData, object, value);
+ object->registerAt(fastEntry.getIndex()).set(vm, object, value);
return true;
}
template<typename SymbolTableObjectType>
inline bool symbolTablePutWithAttributes(
- SymbolTableObjectType* object, JSGlobalData& globalData, PropertyName propertyName,
+ SymbolTableObjectType* object, VM& vm, PropertyName propertyName,
JSValue value, unsigned attributes)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
@@ -153,7 +153,7 @@ inline bool symbolTablePutWithAttributes(
ASSERT(!entry.isNull());
entry.notifyWrite();
entry.setAttributes(attributes);
- object->registerAt(entry.getIndex()).set(globalData, object, value);
+ object->registerAt(entry.getIndex()).set(vm, object, value);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h
index 97fc64c1c..109a032bd 100644
--- a/Source/JavaScriptCore/runtime/JSTypeInfo.h
+++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h
@@ -47,6 +47,7 @@ namespace JSC {
static const unsigned OverridesGetPropertyNames = 1 << 8;
static const unsigned ProhibitsPropertyCaching = 1 << 9;
static const unsigned HasImpureGetOwnPropertySlot = 1 << 10;
+ static const unsigned StructureHasRareData = 1 << 11;
class TypeInfo {
public:
@@ -70,6 +71,7 @@ namespace JSC {
bool isNumberObject() const { return type() == NumberObjectType; }
bool isName() const { return type() == NameInstanceType; }
+ unsigned flags() const { return (static_cast<unsigned>(m_flags2) << 8) | static_cast<unsigned>(m_flags); }
bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); }
bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); }
bool isEnvironmentRecord() const { return isSetOnFlags1(IsEnvironmentRecord); }
@@ -81,6 +83,7 @@ namespace JSC {
bool overridesGetPropertyNames() const { return isSetOnFlags2(OverridesGetPropertyNames); }
bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
bool hasImpureGetOwnPropertySlot() const { return isSetOnFlags2(HasImpureGetOwnPropertySlot); }
+ bool structureHasRareData() const { return isSetOnFlags2(StructureHasRareData); }
static ptrdiff_t flagsOffset()
{
diff --git a/Source/JavaScriptCore/runtime/JSValueInlines.h b/Source/JavaScriptCore/runtime/JSValueInlines.h
deleted file mode 100644
index c5a42f67f..000000000
--- a/Source/JavaScriptCore/runtime/JSValueInlines.h
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSValueInlines_h
-#define JSValueInlines_h
-
-#include "JSValue.h"
-
-namespace JSC {
-
- ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
- {
- if (isInt32())
- return asInt32();
- return JSC::toInt32(toNumber(exec));
- }
-
- inline uint32_t JSValue::toUInt32(ExecState* exec) const
- {
- // See comment on JSC::toUInt32, above.
- return toInt32(exec);
- }
-
- inline bool JSValue::isUInt32() const
- {
- return isInt32() && asInt32() >= 0;
- }
-
- inline uint32_t JSValue::asUInt32() const
- {
- ASSERT(isUInt32());
- return asInt32();
- }
-
- inline double JSValue::asNumber() const
- {
- ASSERT(isNumber());
- return isInt32() ? asInt32() : asDouble();
- }
-
- inline JSValue jsNaN()
- {
- return JSValue(QNaN);
- }
-
- inline JSValue::JSValue(char i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned char i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(short i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned short i)
- {
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned i)
- {
- if (static_cast<int32_t>(i) < 0) {
- *this = JSValue(EncodeAsDouble, static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(EncodeAsDouble, static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(EncodeAsDouble, static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<uint32_t>(i));
- }
-
- inline JSValue::JSValue(long long i)
- {
- if (static_cast<int32_t>(i) != i) {
- *this = JSValue(EncodeAsDouble, static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<int32_t>(i));
- }
-
- inline JSValue::JSValue(unsigned long long i)
- {
- if (static_cast<uint32_t>(i) != i) {
- *this = JSValue(EncodeAsDouble, static_cast<double>(i));
- return;
- }
- *this = JSValue(static_cast<uint32_t>(i));
- }
-
- inline JSValue::JSValue(double d)
- {
- const int32_t asInt32 = static_cast<int32_t>(d);
- if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
- *this = JSValue(EncodeAsDouble, d);
- return;
- }
- *this = JSValue(static_cast<int32_t>(d));
- }
-
- inline EncodedJSValue JSValue::encode(JSValue value)
- {
- return value.u.asInt64;
- }
-
- inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
- {
- JSValue v;
- v.u.asInt64 = encodedJSValue;
- return v;
- }
-
-#if USE(JSVALUE32_64)
- inline JSValue::JSValue()
- {
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSNullTag)
- {
- u.asBits.tag = NullTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSUndefinedTag)
- {
- u.asBits.tag = UndefinedTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSTrueTag)
- {
- u.asBits.tag = BooleanTag;
- u.asBits.payload = 1;
- }
-
- inline JSValue::JSValue(JSFalseTag)
- {
- u.asBits.tag = BooleanTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(HashTableDeletedValueTag)
- {
- u.asBits.tag = DeletedValueTag;
- u.asBits.payload = 0;
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- {
- if (ptr)
- u.asBits.tag = CellTag;
- else
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = reinterpret_cast<int32_t>(ptr);
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- {
- if (ptr)
- u.asBits.tag = CellTag;
- else
- u.asBits.tag = EmptyValueTag;
- u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
- }
-
- inline JSValue::operator bool() const
- {
- ASSERT(tag() != DeletedValueTag);
- return tag() != EmptyValueTag;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return u.asInt64 == other.u.asInt64;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return u.asInt64 != other.u.asInt64;
- }
-
- inline bool JSValue::isEmpty() const
- {
- return tag() == EmptyValueTag;
- }
-
- inline bool JSValue::isUndefined() const
- {
- return tag() == UndefinedTag;
- }
-
- inline bool JSValue::isNull() const
- {
- return tag() == NullTag;
- }
-
- inline bool JSValue::isUndefinedOrNull() const
- {
- return isUndefined() || isNull();
- }
-
- inline bool JSValue::isCell() const
- {
- return tag() == CellTag;
- }
-
- inline bool JSValue::isInt32() const
- {
- return tag() == Int32Tag;
- }
-
- inline bool JSValue::isDouble() const
- {
- return tag() < LowestTag;
- }
-
- inline bool JSValue::isTrue() const
- {
- return tag() == BooleanTag && payload();
- }
-
- inline bool JSValue::isFalse() const
- {
- return tag() == BooleanTag && !payload();
- }
-
- inline uint32_t JSValue::tag() const
- {
- return u.asBits.tag;
- }
-
- inline int32_t JSValue::payload() const
- {
- return u.asBits.payload;
- }
-
- inline int32_t JSValue::asInt32() const
- {
- ASSERT(isInt32());
- return u.asBits.payload;
- }
-
- inline double JSValue::asDouble() const
- {
- ASSERT(isDouble());
- return u.asDouble;
- }
-
- ALWAYS_INLINE JSCell* JSValue::asCell() const
- {
- ASSERT(isCell());
- return reinterpret_cast<JSCell*>(u.asBits.payload);
- }
-
- ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
- {
- u.asDouble = d;
- }
-
- inline JSValue::JSValue(int i)
- {
- u.asBits.tag = Int32Tag;
- u.asBits.payload = i;
- }
-
-#if ENABLE(LLINT_C_LOOP)
- inline JSValue::JSValue(int32_t tag, int32_t payload)
- {
- u.asBits.tag = tag;
- u.asBits.payload = payload;
- }
-#endif
-
- inline bool JSValue::isNumber() const
- {
- return isInt32() || isDouble();
- }
-
- inline bool JSValue::isBoolean() const
- {
- return isTrue() || isFalse();
- }
-
- inline bool JSValue::asBoolean() const
- {
- ASSERT(isBoolean());
- return payload();
- }
-
-#else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
-
- // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
- inline JSValue::JSValue()
- {
- u.asInt64 = ValueEmpty;
- }
-
- // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
- inline JSValue::JSValue(HashTableDeletedValueTag)
- {
- u.asInt64 = ValueDeleted;
- }
-
- inline JSValue::JSValue(JSCell* ptr)
- {
- u.asInt64 = reinterpret_cast<uintptr_t>(ptr);
- }
-
- inline JSValue::JSValue(const JSCell* ptr)
- {
- u.asInt64 = reinterpret_cast<uintptr_t>(const_cast<JSCell*>(ptr));
- }
-
- inline JSValue::operator bool() const
- {
- return u.asInt64;
- }
-
- inline bool JSValue::operator==(const JSValue& other) const
- {
- return u.asInt64 == other.u.asInt64;
- }
-
- inline bool JSValue::operator!=(const JSValue& other) const
- {
- return u.asInt64 != other.u.asInt64;
- }
-
- inline bool JSValue::isEmpty() const
- {
- return u.asInt64 == ValueEmpty;
- }
-
- inline bool JSValue::isUndefined() const
- {
- return asValue() == JSValue(JSUndefined);
- }
-
- inline bool JSValue::isNull() const
- {
- return asValue() == JSValue(JSNull);
- }
-
- inline bool JSValue::isTrue() const
- {
- return asValue() == JSValue(JSTrue);
- }
-
- inline bool JSValue::isFalse() const
- {
- return asValue() == JSValue(JSFalse);
- }
-
- inline bool JSValue::asBoolean() const
- {
- ASSERT(isBoolean());
- return asValue() == JSValue(JSTrue);
- }
-
- inline int32_t JSValue::asInt32() const
- {
- ASSERT(isInt32());
- return static_cast<int32_t>(u.asInt64);
- }
-
- inline bool JSValue::isDouble() const
- {
- return isNumber() && !isInt32();
- }
-
- inline JSValue::JSValue(JSNullTag)
- {
- u.asInt64 = ValueNull;
- }
-
- inline JSValue::JSValue(JSUndefinedTag)
- {
- u.asInt64 = ValueUndefined;
- }
-
- inline JSValue::JSValue(JSTrueTag)
- {
- u.asInt64 = ValueTrue;
- }
-
- inline JSValue::JSValue(JSFalseTag)
- {
- u.asInt64 = ValueFalse;
- }
-
- inline bool JSValue::isUndefinedOrNull() const
- {
- // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
- return (u.asInt64 & ~TagBitUndefined) == ValueNull;
- }
-
- inline bool JSValue::isBoolean() const
- {
- return (u.asInt64 & ~1) == ValueFalse;
- }
-
- inline bool JSValue::isCell() const
- {
- return !(u.asInt64 & TagMask);
- }
-
- inline bool JSValue::isInt32() const
- {
- return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
- }
-
- inline int64_t reinterpretDoubleToInt64(double value)
- {
- return bitwise_cast<int64_t>(value);
- }
- inline double reinterpretInt64ToDouble(int64_t value)
- {
- return bitwise_cast<double>(value);
- }
-
- ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
- {
- u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
- }
-
- inline JSValue::JSValue(int i)
- {
- u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
- }
-
- inline double JSValue::asDouble() const
- {
- ASSERT(isDouble());
- return reinterpretInt64ToDouble(u.asInt64 - DoubleEncodeOffset);
- }
-
- inline bool JSValue::isNumber() const
- {
- return u.asInt64 & TagTypeNumber;
- }
-
- ALWAYS_INLINE JSCell* JSValue::asCell() const
- {
- ASSERT(isCell());
- return u.ptr;
- }
-
-#endif // USE(JSVALUE64)
-
-} // namespace JSC
-
-#endif // JSValueInlines_h
-
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index 9b03a2c64..fc262f5d8 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -29,6 +29,8 @@
#include "config.h"
#include "JSVariableObject.h"
+#include "Operations.h"
+
namespace JSC {
const ClassInfo JSVariableObject::s_info = { "VariableObject", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSVariableObject) };
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index 3ff7aa841..615aa331f 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -33,7 +33,6 @@
#include "JSSymbolTableObject.h"
#include "Register.h"
#include "SymbolTable.h"
-#include <wtf/UnusedParam.h>
#include <wtf/OwnArrayPtr.h>
namespace JSC {
@@ -59,13 +58,13 @@ namespace JSC {
static const unsigned StructureFlags = Base::StructureFlags;
JSVariableObject(
- JSGlobalData& globalData,
+ VM& vm,
Structure* structure,
Register* registers,
JSScope* scope,
SharedSymbolTable* symbolTable = 0
)
- : Base(globalData, structure, scope, symbolTable)
+ : Base(vm, structure, scope, symbolTable)
, m_registers(reinterpret_cast<WriteBarrierBase<Unknown>*>(registers))
{
}
diff --git a/Source/JavaScriptCore/runtime/JSWithScope.cpp b/Source/JavaScriptCore/runtime/JSWithScope.cpp
index 7d74e63c3..c0c6c1f7b 100644
--- a/Source/JavaScriptCore/runtime/JSWithScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSWithScope.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "JSWithScope.h"
+#include "Operations.h"
+
namespace JSC {
const ClassInfo JSWithScope::s_info = { "WithScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSWithScope) };
diff --git a/Source/JavaScriptCore/runtime/JSWithScope.h b/Source/JavaScriptCore/runtime/JSWithScope.h
index ba2b793a9..ea879cb54 100644
--- a/Source/JavaScriptCore/runtime/JSWithScope.h
+++ b/Source/JavaScriptCore/runtime/JSWithScope.h
@@ -37,14 +37,14 @@ public:
static JSWithScope* create(ExecState* exec, JSObject* object)
{
JSWithScope* withScope = new (NotNull, allocateCell<JSWithScope>(*exec->heap())) JSWithScope(exec, object);
- withScope->finishCreation(exec->globalData());
+ withScope->finishCreation(exec->vm());
return withScope;
}
static JSWithScope* create(ExecState* exec, JSObject* object, JSScope* next)
{
JSWithScope* withScope = new (NotNull, allocateCell<JSWithScope>(*exec->heap())) JSWithScope(exec, object, next);
- withScope->finishCreation(exec->globalData());
+ withScope->finishCreation(exec->vm());
return withScope;
}
@@ -52,9 +52,9 @@ public:
static void visitChildren(JSCell*, SlotVisitor&);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(WithScopeType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(WithScopeType, StructureFlags), &s_info);
}
static JS_EXPORTDATA const ClassInfo s_info;
@@ -65,21 +65,21 @@ protected:
private:
JSWithScope(ExecState* exec, JSObject* object)
: Base(
- exec->globalData(),
+ exec->vm(),
exec->lexicalGlobalObject()->withScopeStructure(),
exec->scope()
)
- , m_object(exec->globalData(), this, object)
+ , m_object(exec->vm(), this, object)
{
}
JSWithScope(ExecState* exec, JSObject* object, JSScope* next)
: Base(
- exec->globalData(),
+ exec->vm(),
exec->lexicalGlobalObject()->withScopeStructure(),
next
)
- , m_object(exec->globalData(), this, object)
+ , m_object(exec->vm(), this, object)
{
}
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
index ff80c1e20..01961a984 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006 Maks Orlovich
- * Copyright (C) 2006, 2009 Apple, Inc.
+ * Copyright (C) 2006, 2009, 2012 Apple, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,6 +22,8 @@
#include "config.h"
#include "JSWrapperObject.h"
+#include "Operations.h"
+
namespace JSC {
ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSWrapperObject);
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h
index 72bc1874c..f1b6d3286 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h
@@ -32,16 +32,32 @@ namespace JSC {
public:
typedef JSDestructibleObject Base;
+ static size_t allocationSize(size_t inlineCapacity)
+ {
+ ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
+ return sizeof(JSWrapperObject);
+ }
+
JSValue internalValue() const;
- void setInternalValue(JSGlobalData&, JSValue);
+ void setInternalValue(VM&, JSValue);
- 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);
+ }
+
+ static ptrdiff_t internalValueOffset() { return OBJECT_OFFSETOF(JSWrapperObject, m_internalValue); }
+ static ptrdiff_t internalValueCellOffset()
+ {
+#if USE(JSVALUE64)
+ return internalValueOffset();
+#else
+ return internalValueOffset() + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload);
+#endif
}
protected:
- explicit JSWrapperObject(JSGlobalData&, Structure*);
+ explicit JSWrapperObject(VM&, Structure*);
static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
static void visitChildren(JSCell*, SlotVisitor&);
@@ -50,8 +66,8 @@ namespace JSC {
WriteBarrier<Unknown> m_internalValue;
};
- inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure)
- : JSDestructibleObject(globalData, structure)
+ inline JSWrapperObject::JSWrapperObject(VM& vm, Structure* structure)
+ : JSDestructibleObject(vm, structure)
{
}
@@ -60,11 +76,11 @@ namespace JSC {
return m_internalValue.get();
}
- inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value)
+ inline void JSWrapperObject::setInternalValue(VM& vm, JSValue value)
{
ASSERT(value);
ASSERT(!value.isObject());
- m_internalValue.set(globalData, this, value);
+ m_internalValue.set(vm, this, value);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp
index bf27327bf..f594518b6 100644
--- a/Source/JavaScriptCore/runtime/LiteralParser.cpp
+++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp
@@ -32,6 +32,8 @@
#include "JSArray.h"
#include "JSString.h"
#include "Lexer.h"
+#include "ObjectConstructor.h"
+#include "Operations.h"
#include "StrongInlines.h"
#include <wtf/ASCIICType.h>
#include <wtf/dtoa.h>
@@ -55,22 +57,24 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
do {
Vector<JSONPPathEntry> path;
// Unguarded next to start off the lexer
- Identifier name = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ Identifier name = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
JSONPPathEntry entry;
- if (name == m_exec->globalData().propertyNames->varKeyword) {
+ if (name == m_exec->vm().propertyNames->varKeyword) {
if (m_lexer.next() != TokIdentifier)
return false;
entry.m_type = JSONPPathEntryTypeDeclare;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
path.append(entry);
} else {
entry.m_type = JSONPPathEntryTypeDot;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
path.append(entry);
}
- if (m_exec->globalData().keywords->isKeyword(entry.m_pathEntryName))
+ if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName))
return false;
TokenType tokenType = m_lexer.next();
+ if (entry.m_type == JSONPPathEntryTypeDeclare && tokenType != TokAssign)
+ return false;
while (tokenType != TokAssign) {
switch (tokenType) {
case TokLBracket: {
@@ -90,7 +94,7 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
entry.m_type = JSONPPathEntryTypeDot;
if (m_lexer.next() != TokIdentifier)
return false;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
break;
}
case TokLParen: {
@@ -109,7 +113,7 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
startJSON:
m_lexer.next();
results.append(JSONPData());
- results.last().m_value.set(m_exec->globalData(), parse(StartParseExpression));
+ results.last().m_value.set(m_exec->vm(), parse(StartParseExpression));
if (!results.last().m_value)
return false;
results.last().m_path.swap(path);
@@ -129,19 +133,19 @@ template <typename CharType>
ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
{
if (!length)
- return m_exec->globalData().propertyNames->emptyIdentifier;
+ return m_exec->vm().propertyNames->emptyIdentifier;
if (characters[0] >= MaximumCachableCharacter)
- return Identifier(&m_exec->globalData(), characters, length);
+ return Identifier(&m_exec->vm(), characters, length);
if (length == 1) {
if (!m_shortIdentifiers[characters[0]].isNull())
return m_shortIdentifiers[characters[0]];
- m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_shortIdentifiers[characters[0]];
}
if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
return m_recentIdentifiers[characters[0]];
- m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_recentIdentifiers[characters[0]];
}
@@ -149,19 +153,19 @@ template <typename CharType>
ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length)
{
if (!length)
- return m_exec->globalData().propertyNames->emptyIdentifier;
+ return m_exec->vm().propertyNames->emptyIdentifier;
if (characters[0] >= MaximumCachableCharacter)
- return Identifier(&m_exec->globalData(), characters, length);
+ return Identifier(&m_exec->vm(), characters, length);
if (length == 1) {
if (!m_shortIdentifiers[characters[0]].isNull())
return m_shortIdentifiers[characters[0]];
- m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_shortIdentifiers[characters[0]];
}
if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
return m_recentIdentifiers[characters[0]];
- m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_recentIdentifiers[characters[0]];
}
@@ -542,8 +546,8 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
ParserState state = initialState;
MarkedArgumentBuffer objectStack;
JSValue lastValue;
- Vector<ParserState, 16> stateStack;
- Vector<Identifier, 16> identifierStack;
+ Vector<ParserState, 16, UnsafeVectorOverflow> stateStack;
+ Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack;
while (1) {
switch(state) {
startParseArray:
@@ -649,7 +653,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
if (i != PropertyName::NotAnIndex)
object->putDirectIndex(m_exec, i, lastValue);
else
- object->putDirect(m_exec->globalData(), ident, lastValue);
+ object->putDirect(m_exec->vm(), ident, lastValue);
identifierStack.removeLast();
if (m_lexer.currentToken().type == TokComma)
goto doParseObjectStartExpression;
@@ -814,7 +818,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
return JSValue();
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
if (stateStack.isEmpty())
return lastValue;
diff --git a/Source/JavaScriptCore/runtime/LiteralParser.h b/Source/JavaScriptCore/runtime/LiteralParser.h
index c0f308ee5..fac97571c 100644
--- a/Source/JavaScriptCore/runtime/LiteralParser.h
+++ b/Source/JavaScriptCore/runtime/LiteralParser.h
@@ -27,8 +27,8 @@
#define LiteralParser_h
#include "Identifier.h"
+#include "JSCJSValue.h"
#include "JSGlobalObjectFunctions.h"
-#include "JSValue.h"
#include <wtf/text/WTFString.h>
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp
index a6a349974..030aef5a5 100644
--- a/Source/JavaScriptCore/runtime/Lookup.cpp
+++ b/Source/JavaScriptCore/runtime/Lookup.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,10 +22,11 @@
#include "Executable.h"
#include "JSFunction.h"
+#include "Operations.h"
namespace JSC {
-void HashTable::createTable(JSGlobalData* globalData) const
+void HashTable::createTable(VM* vm) const
{
ASSERT(!table);
int linkIndex = compactHashSizeMask + 1;
@@ -33,7 +34,7 @@ void HashTable::createTable(JSGlobalData* globalData) const
for (int i = 0; i < compactSize; ++i)
entries[i].setKey(0);
for (int i = 0; values[i].key; ++i) {
- StringImpl* identifier = Identifier::add(globalData, values[i].key).leakRef();
+ StringImpl* identifier = Identifier::add(vm, values[i].key).leakRef();
int hashIndex = identifier->existingHash() & compactHashSizeMask;
HashEntry* entry = &entries[hashIndex];
@@ -68,23 +69,22 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
{
ASSERT(thisObj->globalObject());
ASSERT(entry->attributes() & Function);
- WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
+ PropertyOffset offset = thisObj->getDirectOffset(exec->vm(), propertyName);
- if (!location) {
+ if (!isValidOffset(offset)) {
// If a property is ever deleted from an object with a static table, then we reify
// all static functions at that time - after this we shouldn't be re-adding anything.
if (thisObj->staticFunctionsReified())
return false;
- StringImpl* name = propertyName.publicName();
- ASSERT(name);
-
- JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), name, entry->function(), entry->intrinsic());
- thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes());
- location = thisObj->getDirectLocation(exec->globalData(), propertyName);
+ thisObj->putDirectNativeFunction(
+ exec, thisObj->globalObject(), propertyName, entry->functionLength(),
+ entry->function(), entry->intrinsic(), entry->attributes());
+ offset = thisObj->getDirectOffset(exec->vm(), propertyName);
+ ASSERT(isValidOffset(offset));
}
- slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location));
+ slot.setValue(thisObj, thisObj->getDirect(offset), offset);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h
index ccb08128d..c90ceae7c 100644
--- a/Source/JavaScriptCore/runtime/Lookup.h
+++ b/Source/JavaScriptCore/runtime/Lookup.h
@@ -53,7 +53,7 @@ namespace JSC {
m_attributes = attributes;
m_u.store.value1 = v1;
m_u.store.value2 = v2;
- m_u.function.intrinsic = intrinsic;
+ m_intrinsic = intrinsic;
m_next = 0;
}
@@ -65,7 +65,7 @@ namespace JSC {
Intrinsic intrinsic() const
{
ASSERT(m_attributes & Function);
- return m_u.function.intrinsic;
+ return m_intrinsic;
}
NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
@@ -82,6 +82,7 @@ namespace JSC {
private:
StringImpl* m_key;
unsigned char m_attributes; // JSObject attributes
+ Intrinsic m_intrinsic;
union {
struct {
@@ -91,7 +92,6 @@ namespace JSC {
struct {
NativeFunction functionValue;
intptr_t length; // number of arguments for function
- Intrinsic intrinsic;
} function;
struct {
GetFunction get;
@@ -121,24 +121,24 @@ namespace JSC {
return result;
}
- ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const
+ ALWAYS_INLINE void initializeIfNeeded(VM* vm) const
{
if (!table)
- createTable(globalData);
+ createTable(vm);
}
ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const
{
if (!table)
- createTable(&exec->globalData());
+ createTable(&exec->vm());
}
JS_EXPORT_PRIVATE void deleteTable() const;
// Find an entry in the table, and return the entry.
- ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, PropertyName identifier) const
+ ALWAYS_INLINE const HashEntry* entry(VM* vm, PropertyName identifier) const
{
- initializeIfNeeded(globalData);
+ initializeIfNeeded(vm);
return entry(identifier);
}
@@ -194,14 +194,14 @@ namespace JSC {
int m_position;
};
- ConstIterator begin(JSGlobalData& globalData) const
+ ConstIterator begin(VM& vm) const
{
- initializeIfNeeded(&globalData);
+ initializeIfNeeded(&vm);
return ConstIterator(this, 0);
}
- ConstIterator end(JSGlobalData& globalData) const
+ ConstIterator end(VM& vm) const
{
- initializeIfNeeded(&globalData);
+ initializeIfNeeded(&vm);
return ConstIterator(this, compactSize);
}
@@ -229,7 +229,7 @@ namespace JSC {
}
// Convert the hash table keys to identifiers.
- JS_EXPORT_PRIVATE void createTable(JSGlobalData*) const;
+ JS_EXPORT_PRIVATE void createTable(VM*) const;
};
JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, PropertyName, PropertySlot&);
@@ -353,6 +353,18 @@ namespace JSC {
return true;
}
+ template <class ThisImp>
+ inline void putEntry(ExecState* exec, const HashEntry* entry, PropertyName propertyName, JSValue value, ThisImp* thisObj, bool shouldThrow = false)
+ {
+ // If this is a function put it as an override property.
+ if (entry->attributes() & Function)
+ thisObj->putDirect(exec->vm(), propertyName, value);
+ else if (!(entry->attributes() & ReadOnly))
+ entry->propertyPutter()(exec, thisObj, value);
+ else if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ }
+
/**
* This one is for "put".
* It looks up a hash entry for the property to be set. If an entry
@@ -366,14 +378,7 @@ namespace JSC {
if (!entry)
return false;
- // If this is a function put it as an override property.
- if (entry->attributes() & Function)
- thisObj->putDirect(exec->globalData(), propertyName, value);
- else if (!(entry->attributes() & ReadOnly))
- entry->propertyPutter()(exec, thisObj, value);
- else if (shouldThrow)
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
-
+ putEntry<ThisImp>(exec, entry, propertyName, value, thisObj, shouldThrow);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index 7634487ad..71c53a3e4 100644
--- a/Source/JavaScriptCore/runtime/MathObject.cpp
+++ b/Source/JavaScriptCore/runtime/MathObject.cpp
@@ -52,6 +52,7 @@ static EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*);
static EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*);
static EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*);
static EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState*);
}
@@ -81,27 +82,28 @@ const ClassInfo MathObject::s_info = { "Math", &Base::s_info, 0, ExecState::math
sin mathProtoFuncSin DontEnum|Function 1
sqrt mathProtoFuncSqrt DontEnum|Function 1
tan mathProtoFuncTan DontEnum|Function 1
+ imul mathProtoFuncIMul DontEnum|Function 2
@end
*/
MathObject::MathObject(JSGlobalObject* globalObject, Structure* structure)
- : JSNonFinalObject(globalObject->globalData(), structure)
+ : JSNonFinalObject(globalObject->vm(), structure)
{
}
void MathObject::finishCreation(ExecState* exec, JSGlobalObject* globalObject)
{
- Base::finishCreation(globalObject->globalData());
+ Base::finishCreation(globalObject->vm());
ASSERT(inherits(&s_info));
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG10E"), jsNumber(0.4342944819032518), DontDelete | DontEnum | ReadOnly); // See ECMA-262 15.8.1.5
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "LOG10E"), jsNumber(0.4342944819032518), DontDelete | DontEnum | ReadOnly); // See ECMA-262 15.8.1.5
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
}
bool MathObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
@@ -174,11 +176,11 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
double result = -std::numeric_limits<double>::infinity();
for (unsigned k = 0; k < argsCount; ++k) {
double val = exec->argument(k).toNumber(exec);
- if (isnan(val)) {
+ if (std::isnan(val)) {
result = QNaN;
break;
}
- if (val > result || (val == 0 && result == 0 && !signbit(val)))
+ if (val > result || (!val && !result && !std::signbit(val)))
result = val;
}
return JSValue::encode(jsNumber(result));
@@ -190,11 +192,11 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
double result = +std::numeric_limits<double>::infinity();
for (unsigned k = 0; k < argsCount; ++k) {
double val = exec->argument(k).toNumber(exec);
- if (isnan(val)) {
+ if (std::isnan(val)) {
result = QNaN;
break;
}
- if (val < result || (val == 0 && result == 0 && signbit(val)))
+ if (val < result || (!val && !result && std::signbit(val)))
result = val;
}
return JSValue::encode(jsNumber(result));
@@ -244,9 +246,9 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
double arg = exec->argument(0).toNumber(exec);
double arg2 = exec->argument(1).toNumber(exec);
- if (isnan(arg2))
+ if (std::isnan(arg2))
return JSValue::encode(jsNaN());
- if (isinf(arg2) && fabs(arg) == 1)
+ if (std::isinf(arg2) && fabs(arg) == 1)
return JSValue::encode(jsNaN());
return JSValue::encode(jsNumber(mathPow(arg, arg2)));
}
@@ -265,7 +267,7 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec)
EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec)
{
- return JSValue::encode(exec->globalData().cachedSin(exec->argument(0).toNumber(exec)));
+ return JSValue::encode(exec->vm().cachedSin(exec->argument(0).toNumber(exec)));
}
EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec)
@@ -278,6 +280,15 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
}
+EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState* exec)
+{
+ int32_t left = exec->argument(0).toInt32(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsNull());
+ int32_t right = exec->argument(1).toInt32(exec);
+ return JSValue::encode(jsNumber(left * right));
+}
+
#if PLATFORM(IOS) && CPU(ARM_THUMB2)
// The following code is taken from netlib.org:
diff --git a/Source/JavaScriptCore/runtime/MathObject.h b/Source/JavaScriptCore/runtime/MathObject.h
index f4082f087..190614b84 100644
--- a/Source/JavaScriptCore/runtime/MathObject.h
+++ b/Source/JavaScriptCore/runtime/MathObject.h
@@ -43,9 +43,9 @@ namespace JSC {
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/MemoryStatistics.cpp b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
index 0f8efc604..5459ff3db 100644
--- a/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
+++ b/Source/JavaScriptCore/runtime/MemoryStatistics.cpp
@@ -27,7 +27,7 @@
#include "MemoryStatistics.h"
#include "ExecutableAllocator.h"
-#include "JSGlobalData.h"
+#include "VM.h"
#include "JSStack.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.h b/Source/JavaScriptCore/runtime/MemoryStatistics.h
index 9a86df296..79cec9c21 100644
--- a/Source/JavaScriptCore/runtime/MemoryStatistics.h
+++ b/Source/JavaScriptCore/runtime/MemoryStatistics.h
@@ -28,7 +28,7 @@
#include "Heap.h"
-class JSGlobalData;
+class VM;
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/NameConstructor.cpp b/Source/JavaScriptCore/runtime/NameConstructor.cpp
index b5facc7cf..e6f85693a 100644
--- a/Source/JavaScriptCore/runtime/NameConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NameConstructor.cpp
@@ -28,6 +28,7 @@
#include "JSGlobalObject.h"
#include "NamePrototype.h"
+#include "Operations.h"
namespace JSC {
@@ -42,15 +43,15 @@ NameConstructor::NameConstructor(JSGlobalObject* globalObject, Structure* struct
void NameConstructor::finishCreation(ExecState* exec, NamePrototype* prototype)
{
- Base::finishCreation(exec->globalData(), prototype->classInfo()->className);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, prototype, DontEnum | DontDelete | ReadOnly);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
+ Base::finishCreation(exec->vm(), prototype->classInfo()->className);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, prototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
}
static EncodedJSValue JSC_HOST_CALL constructPrivateName(ExecState* exec)
{
JSValue publicName = exec->argumentCount() ? exec->argument(0) : jsUndefined();
- return JSValue::encode(NameInstance::create(exec->globalData(), exec->lexicalGlobalObject()->privateNameStructure(), publicName.toString(exec)));
+ return JSValue::encode(NameInstance::create(exec->vm(), exec->lexicalGlobalObject()->privateNameStructure(), publicName.toString(exec)));
}
ConstructType NameConstructor::getConstructData(JSCell*, ConstructData& constructData)
diff --git a/Source/JavaScriptCore/runtime/NameConstructor.h b/Source/JavaScriptCore/runtime/NameConstructor.h
index 16c5eef68..b7a52e402 100644
--- a/Source/JavaScriptCore/runtime/NameConstructor.h
+++ b/Source/JavaScriptCore/runtime/NameConstructor.h
@@ -46,9 +46,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/NameInstance.cpp b/Source/JavaScriptCore/runtime/NameInstance.cpp
index f257243e8..dbbf0e2f6 100644
--- a/Source/JavaScriptCore/runtime/NameInstance.cpp
+++ b/Source/JavaScriptCore/runtime/NameInstance.cpp
@@ -27,15 +27,16 @@
#include "NameInstance.h"
#include "JSScope.h"
+#include "Operations.h"
namespace JSC {
const ClassInfo NameInstance::s_info = { "Name", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(NameInstance) };
-NameInstance::NameInstance(JSGlobalData& globalData, Structure* structure, JSString* nameString)
- : Base(globalData, structure)
+NameInstance::NameInstance(VM& vm, Structure* structure, JSString* nameString)
+ : Base(vm, structure)
{
- m_nameString.set(globalData, this, nameString);
+ m_nameString.set(vm, this, nameString);
}
void NameInstance::destroy(JSCell* cell)
diff --git a/Source/JavaScriptCore/runtime/NameInstance.h b/Source/JavaScriptCore/runtime/NameInstance.h
index 129e7c407..e5aa79d97 100644
--- a/Source/JavaScriptCore/runtime/NameInstance.h
+++ b/Source/JavaScriptCore/runtime/NameInstance.h
@@ -37,15 +37,15 @@ 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(NameInstanceType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), &s_info);
}
- static NameInstance* create(JSGlobalData& globalData, Structure* structure, JSString* nameString)
+ static NameInstance* create(VM& vm, Structure* structure, JSString* nameString)
{
- NameInstance* name = new (NotNull, allocateCell<NameInstance>(globalData.heap)) NameInstance(globalData, structure, nameString);
- name->finishCreation(globalData);
+ NameInstance* name = new (NotNull, allocateCell<NameInstance>(vm.heap)) NameInstance(vm, structure, nameString);
+ name->finishCreation(vm);
return name;
}
@@ -55,11 +55,11 @@ public:
protected:
static void destroy(JSCell*);
- NameInstance(JSGlobalData&, Structure*, JSString*);
+ NameInstance(VM&, Structure*, JSString*);
- void finishCreation(JSGlobalData& globalData)
+ void finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
}
diff --git a/Source/JavaScriptCore/runtime/NamePrototype.cpp b/Source/JavaScriptCore/runtime/NamePrototype.cpp
index f14e58522..a3b55fe74 100644
--- a/Source/JavaScriptCore/runtime/NamePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NamePrototype.cpp
@@ -27,6 +27,7 @@
#include "NamePrototype.h"
#include "Error.h"
+#include "Operations.h"
namespace JSC {
@@ -47,13 +48,13 @@ const ClassInfo NamePrototype::s_info = { "Name", &Base::s_info, 0, ExecState::p
*/
NamePrototype::NamePrototype(ExecState* exec, Structure* structure)
- : Base(exec->globalData(), structure, jsEmptyString(exec))
+ : Base(exec->vm(), structure, jsEmptyString(exec))
{
}
void NamePrototype::finishCreation(ExecState* exec)
{
- Base::finishCreation(exec->globalData());
+ Base::finishCreation(exec->vm());
ASSERT(inherits(&s_info));
}
diff --git a/Source/JavaScriptCore/runtime/NamePrototype.h b/Source/JavaScriptCore/runtime/NamePrototype.h
index 5d86decfd..a3abf330b 100644
--- a/Source/JavaScriptCore/runtime/NamePrototype.h
+++ b/Source/JavaScriptCore/runtime/NamePrototype.h
@@ -43,9 +43,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(NameInstanceType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(NameInstanceType, StructureFlags), &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
index 1f1730805..929cc8cb2 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -25,6 +25,7 @@
#include "JSFunction.h"
#include "JSString.h"
#include "NativeErrorPrototype.h"
+#include "Operations.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
index 8db237028..0a6ef6ec1 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h
@@ -43,9 +43,9 @@ namespace JSC {
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);
}
Structure* errorStructure() { return m_errorStructure.get(); }
@@ -53,14 +53,14 @@ namespace JSC {
protected:
void finishCreation(ExecState* exec, JSGlobalObject* globalObject, Structure* prototypeStructure, const String& name)
{
- Base::finishCreation(exec->globalData(), name);
+ Base::finishCreation(exec->vm(), name);
ASSERT(inherits(&s_info));
NativeErrorPrototype* prototype = NativeErrorPrototype::create(exec, globalObject, prototypeStructure, name, this);
- putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
- putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum);
- m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), globalObject, prototype));
+ putDirect(exec->vm(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
+ putDirect(exec->vm(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum);
+ m_errorStructure.set(exec->vm(), this, ErrorInstance::createStructure(exec->vm(), globalObject, prototype));
ASSERT(m_errorStructure);
ASSERT(m_errorStructure->isObject());
}
diff --git a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
index 296a86a22..c33ac3d92 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp
@@ -24,6 +24,7 @@
#include "JSGlobalObject.h"
#include "JSString.h"
#include "NativeErrorConstructor.h"
+#include "Operations.h"
namespace JSC {
@@ -35,9 +36,9 @@ NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, Structure* structure
void NativeErrorPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject, const WTF::String& nameAndMessage, NativeErrorConstructor* constructor)
{
Base::finishCreation(exec, globalObject);
- putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), DontEnum);
- putDirect(exec->globalData(), exec->propertyNames().message, jsEmptyString(exec), DontEnum);
- putDirect(exec->globalData(), exec->propertyNames().constructor, constructor, DontEnum);
+ putDirect(exec->vm(), exec->propertyNames().name, jsString(exec, nameAndMessage), DontEnum);
+ putDirect(exec->vm(), exec->propertyNames().message, jsEmptyString(exec), DontEnum);
+ putDirect(exec->vm(), exec->propertyNames().constructor, constructor, DontEnum);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
index daa643da7..14e149dcf 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
@@ -25,6 +25,7 @@
#include "Lookup.h"
#include "NumberObject.h"
#include "NumberPrototype.h"
+#include "Operations.h"
namespace JSC {
@@ -61,14 +62,14 @@ NumberConstructor::NumberConstructor(JSGlobalObject* globalObject, Structure* st
void NumberConstructor::finishCreation(ExecState* exec, NumberPrototype* numberPrototype)
{
- Base::finishCreation(exec->globalData(), numberPrototype->s_info.className);
+ Base::finishCreation(exec->vm(), numberPrototype->s_info.className);
ASSERT(inherits(&s_info));
// Number.Prototype
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
bool NumberConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
@@ -114,9 +115,9 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, PropertyName)
// ECMA 15.7.1
static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
{
- NumberObject* object = NumberObject::create(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure());
+ NumberObject* object = NumberObject::create(exec->vm(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure());
double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0;
- object->setInternalValue(exec->globalData(), jsNumber(n));
+ object->setInternalValue(exec->vm(), jsNumber(n));
return JSValue::encode(object);
}
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h
index 75f55f88e..45883ede1 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.h
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.h
@@ -46,9 +46,9 @@ namespace JSC {
static const ClassInfo s_info;
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
- return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info);
}
enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp
index b87753d4d..05349ef31 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.cpp
+++ b/Source/JavaScriptCore/runtime/NumberObject.cpp
@@ -24,6 +24,7 @@
#include "JSGlobalObject.h"
#include "NumberPrototype.h"
+#include "Operations.h"
namespace JSC {
@@ -31,21 +32,21 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberObject);
const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(NumberObject) };
-NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure)
- : JSWrapperObject(globalData, structure)
+NumberObject::NumberObject(VM& vm, Structure* structure)
+ : JSWrapperObject(vm, structure)
{
}
-void NumberObject::finishCreation(JSGlobalData& globalData)
+void NumberObject::finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
}
NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number)
{
- NumberObject* object = NumberObject::create(exec->globalData(), globalObject->numberObjectStructure());
- object->setInternalValue(exec->globalData(), number);
+ NumberObject* object = NumberObject::create(exec->vm(), globalObject->numberObjectStructure());
+ object->setInternalValue(exec->vm(), number);
return object;
}
diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h
index ed84207d9..1c7c8982b 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.h
+++ b/Source/JavaScriptCore/runtime/NumberObject.h
@@ -27,24 +27,24 @@ namespace JSC {
class NumberObject : public JSWrapperObject {
protected:
- NumberObject(JSGlobalData&, Structure*);
- void finishCreation(JSGlobalData&);
+ NumberObject(VM&, Structure*);
+ void finishCreation(VM&);
public:
typedef JSWrapperObject Base;
- static NumberObject* create(JSGlobalData& globalData, Structure* structure)
+ static NumberObject* create(VM& vm, Structure* structure)
{
- NumberObject* number = new (NotNull, allocateCell<NumberObject>(globalData.heap)) NumberObject(globalData, structure);
- number->finishCreation(globalData);
+ NumberObject* number = new (NotNull, allocateCell<NumberObject>(vm.heap)) NumberObject(vm, structure);
+ number->finishCreation(vm);
return number;
}
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(NumberObjectType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info);
}
};
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index 23c9dbfdd..54a947303 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -71,14 +71,14 @@ const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0,
ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberPrototype);
NumberPrototype::NumberPrototype(ExecState* exec, Structure* structure)
- : NumberObject(exec->globalData(), structure)
+ : NumberObject(exec->vm(), structure)
{
}
void NumberPrototype::finishCreation(ExecState* exec, JSGlobalObject*)
{
- Base::finishCreation(exec->globalData());
- setInternalValue(exec->globalData(), jsNumber(0));
+ Base::finishCreation(exec->vm());
+ setInternalValue(exec->vm(), jsNumber(0));
ASSERT(inherits(&s_info));
}
@@ -151,7 +151,7 @@ static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix)
{
- ASSERT(isfinite(number));
+ ASSERT(std::isfinite(number));
ASSERT(radix >= 2 && radix <= 36);
// Position the decimal point at the center of the string, set
@@ -161,7 +161,7 @@ static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radi
// Extract the sign.
bool isNegative = number < 0;
- if (signbit(number))
+ if (std::signbit(number))
number = -number;
double integerPart = floor(number);
@@ -198,12 +198,12 @@ static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radi
// Calculate the delta from the current number to the next & previous possible IEEE numbers.
double nextNumber = nextafter(number, std::numeric_limits<double>::infinity());
double lastNumber = nextafter(number, -std::numeric_limits<double>::infinity());
- ASSERT(isfinite(nextNumber) && !signbit(nextNumber));
- ASSERT(isfinite(lastNumber) && !signbit(lastNumber));
+ ASSERT(std::isfinite(nextNumber) && !std::signbit(nextNumber));
+ ASSERT(std::isfinite(lastNumber) && !std::signbit(lastNumber));
double deltaNextDouble = nextNumber - number;
double deltaLastDouble = number - lastNumber;
- ASSERT(isfinite(deltaNextDouble) && !signbit(deltaNextDouble));
- ASSERT(isfinite(deltaLastDouble) && !signbit(deltaLastDouble));
+ ASSERT(std::isfinite(deltaNextDouble) && !std::signbit(deltaNextDouble));
+ ASSERT(std::isfinite(deltaLastDouble) && !std::signbit(deltaLastDouble));
// We track the delta from the current value to the next, to track how many digits of the
// fraction we need to write. For example, if the value we are converting is precisely
@@ -380,7 +380,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
return throwVMError(exec, createRangeError(exec, ASCIILiteral("toExponential() argument must be between 0 and 20")));
// Handle NaN and Infinity.
- if (!isfinite(x))
+ if (!std::isfinite(x))
return JSValue::encode(jsString(exec, String::numberToStringECMAScript(x)));
// Round if the argument is not undefined, always format as exponential.
@@ -418,7 +418,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
// The check above will return false for NaN or Infinity, these will be
// handled by numberToString.
- ASSERT(isfinite(x));
+ ASSERT(std::isfinite(x));
NumberToStringBuffer buffer;
return JSValue::encode(jsString(exec, String(numberToFixedWidthString(x, decimalPlaces, buffer))));
@@ -448,7 +448,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
return JSValue::encode(jsString(exec, String::numberToStringECMAScript(x)));
// Handle NaN and Infinity.
- if (!isfinite(x))
+ if (!std::isfinite(x))
return JSValue::encode(jsString(exec, String::numberToStringECMAScript(x)));
NumberToStringBuffer buffer;
@@ -475,13 +475,13 @@ static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix
if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) {
ASSERT(value <= 36);
ASSERT(value >= 0);
- JSGlobalData* globalData = &exec->globalData();
- return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[value]));
+ VM* vm = &exec->vm();
+ return JSValue::encode(vm->smallStrings.singleCharacterString(vm, radixDigits[value]));
}
if (radix == 10) {
- JSGlobalData* globalData = &exec->globalData();
- return JSValue::encode(jsString(globalData, globalData->numericStrings.add(value)));
+ VM* vm = &exec->vm();
+ return JSValue::encode(jsString(vm, vm->numericStrings.add(value)));
}
return JSValue::encode(jsString(exec, toStringWithRadix(value, radix)));
@@ -503,11 +503,11 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
return integerValueToString(exec, radix, integerValue);
if (radix == 10) {
- JSGlobalData* globalData = &exec->globalData();
- return JSValue::encode(jsString(globalData, globalData->numericStrings.add(doubleValue)));
+ VM* vm = &exec->vm();
+ return JSValue::encode(jsString(vm, vm->numericStrings.add(doubleValue)));
}
- if (!isfinite(doubleValue))
+ if (!std::isfinite(doubleValue))
return JSValue::encode(jsString(exec, String::numberToStringECMAScript(doubleValue)));
RadixBuffer s;
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.h b/Source/JavaScriptCore/runtime/NumberPrototype.h
index d7caecf3f..b51251c72 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.h
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.h
@@ -38,9 +38,9 @@ namespace JSC {
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(NumberObjectType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index 7e74a914b..d72cbe84e 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -30,6 +30,7 @@
#include "JSGlobalObject.h"
#include "Lookup.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include "PropertyDescriptor.h"
#include "PropertyNameArray.h"
@@ -84,11 +85,11 @@ ObjectConstructor::ObjectConstructor(JSGlobalObject* globalObject, Structure* st
void ObjectConstructor::finishCreation(ExecState* exec, ObjectPrototype* objectPrototype)
{
- Base::finishCreation(exec->globalData(), Identifier(exec, "Object").string());
+ Base::finishCreation(exec->vm(), Identifier(exec, "Object").string());
// ECMA 15.2.3.1
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
bool ObjectConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
@@ -101,19 +102,19 @@ bool ObjectConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* ex
return getStaticFunctionDescriptor<JSObject>(exec, ExecState::objectConstructorTable(exec), jsCast<ObjectConstructor*>(object), propertyName, descriptor);
}
-// ECMA 15.2.2
-static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
+static ALWAYS_INLINE JSObject* constructObject(ExecState* exec)
{
+ JSGlobalObject* globalObject = exec->callee()->globalObject();
+ ArgList args(exec);
JSValue arg = args.at(0);
if (arg.isUndefinedOrNull())
- return constructEmptyObject(exec, globalObject);
+ return constructEmptyObject(exec, globalObject->objectPrototype());
return arg.toObject(exec, globalObject);
}
static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec)
{
- ArgList args(exec);
- return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
+ return JSValue::encode(constructObject(exec));
}
ConstructType ObjectConstructor::getConstructData(JSCell*, ConstructData& constructData)
@@ -124,8 +125,7 @@ ConstructType ObjectConstructor::getConstructData(JSCell*, ConstructData& constr
static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
{
- ArgList args(exec);
- return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
+ return JSValue::encode(constructObject(exec));
}
CallType ObjectConstructor::getCallData(JSCell*, CallData& callData)
@@ -160,17 +160,17 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState
JSObject* description = constructEmptyObject(exec);
if (!descriptor.isAccessorDescriptor()) {
- description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
- description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
} else {
ASSERT(descriptor.getter());
ASSERT(descriptor.setter());
- description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter(), 0);
- description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter(), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().get, descriptor.getter(), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().set, descriptor.setter(), 0);
}
- description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
- description->putDirect(exec->globalData(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
+ description->putDirect(exec->vm(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
return JSValue::encode(description);
}
@@ -349,7 +349,9 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
if (!exec->argument(0).isObject() && !exec->argument(0).isNull())
return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object prototype may only be an Object or null.")));
JSValue proto = exec->argument(0);
- JSObject* newObject = proto.isObject() ? constructEmptyObject(exec, asObject(proto)->inheritorID(exec->globalData())) : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
+ JSObject* newObject = proto.isObject()
+ ? constructEmptyObject(exec, asObject(proto))
+ : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
if (exec->argument(1).isUndefined())
return JSValue::encode(newObject);
if (!exec->argument(1).isObject())
@@ -366,7 +368,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
JSObject* object = asObject(obj);
if (isJSFinalObject(object)) {
- object->seal(exec->globalData());
+ object->seal(exec->vm());
return JSValue::encode(obj);
}
@@ -388,7 +390,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
}
// 3. Set the [[Extensible]] internal property of O to false.
- object->preventExtensions(exec->globalData());
+ object->preventExtensions(exec->vm());
// 4. Return O.
return JSValue::encode(obj);
@@ -403,7 +405,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
JSObject* object = asObject(obj);
if (isJSFinalObject(object) && !hasIndexedProperties(object->structure()->indexingType())) {
- object->freeze(exec->globalData());
+ object->freeze(exec->vm());
return JSValue::encode(obj);
}
@@ -429,7 +431,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
}
// 3. Set the [[Extensible]] internal property of O to false.
- object->preventExtensions(exec->globalData());
+ object->preventExtensions(exec->vm());
// 4. Return O.
return JSValue::encode(obj);
@@ -440,7 +442,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
JSValue obj = exec->argument(0);
if (!obj.isObject())
return throwVMError(exec, createTypeError(exec, ASCIILiteral("Object.preventExtensions can only be called on Objects.")));
- asObject(obj)->preventExtensions(exec->globalData());
+ asObject(obj)->preventExtensions(exec->vm());
return JSValue::encode(obj);
}
@@ -453,7 +455,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
JSObject* object = asObject(obj);
if (isJSFinalObject(object))
- return JSValue::encode(jsBoolean(object->isSealed(exec->globalData())));
+ return JSValue::encode(jsBoolean(object->isSealed(exec->vm())));
// 2. For each named own property name P of O,
PropertyNameArray properties(exec);
@@ -483,7 +485,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
JSObject* object = asObject(obj);
if (isJSFinalObject(object))
- return JSValue::encode(jsBoolean(object->isFrozen(exec->globalData())));
+ return JSValue::encode(jsBoolean(object->isFrozen(exec->vm())));
// 2. For each named own property name P of O,
PropertyNameArray properties(exec);
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.h b/Source/JavaScriptCore/runtime/ObjectConstructor.h
index c89134599..72c895fba 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.h
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.h
@@ -22,6 +22,8 @@
#define ObjectConstructor_h
#include "InternalFunction.h"
+#include "JSGlobalObject.h"
+#include "ObjectPrototype.h"
namespace JSC {
@@ -43,9 +45,9 @@ namespace JSC {
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:
@@ -58,6 +60,30 @@ namespace JSC {
static CallType getCallData(JSCell*, CallData&);
};
+ inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
+ {
+ return JSFinalObject::create(exec, structure);
+ }
+
+ inline JSObject* constructEmptyObject(ExecState* exec, JSObject* prototype, unsigned inlineCapacity)
+ {
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ PrototypeMap& prototypeMap = globalObject->vm().prototypeMap;
+ Structure* structure = prototypeMap.emptyObjectStructureForPrototype(
+ prototype, inlineCapacity);
+ return constructEmptyObject(exec, structure);
+ }
+
+ inline JSObject* constructEmptyObject(ExecState* exec, JSObject* prototype)
+ {
+ return constructEmptyObject(exec, prototype, JSFinalObject::defaultInlineCapacity());
+ }
+
+ inline JSObject* constructEmptyObject(ExecState* exec)
+ {
+ return constructEmptyObject(exec, exec->lexicalGlobalObject()->objectPrototype());
+ }
+
} // namespace JSC
#endif // ObjectConstructor_h
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index e94edfadf..eaed425df 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -25,6 +25,8 @@
#include "JSFunction.h"
#include "JSString.h"
#include "JSStringBuilder.h"
+#include "Operations.h"
+#include "StructureRareDataInlines.h"
namespace JSC {
@@ -38,51 +40,40 @@ static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*);
static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
-}
-
-#include "ObjectPrototype.lut.h"
-
-namespace JSC {
-
ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectPrototype);
-const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable, CREATE_METHOD_TABLE(ObjectPrototype) };
-
-/* Source for ObjectPrototype.lut.h
-@begin objectPrototypeTable
- toString objectProtoFuncToString DontEnum|Function 0
- toLocaleString objectProtoFuncToLocaleString DontEnum|Function 0
- valueOf objectProtoFuncValueOf DontEnum|Function 0
- hasOwnProperty objectProtoFuncHasOwnProperty DontEnum|Function 1
- propertyIsEnumerable objectProtoFuncPropertyIsEnumerable DontEnum|Function 1
- isPrototypeOf objectProtoFuncIsPrototypeOf DontEnum|Function 1
- __defineGetter__ objectProtoFuncDefineGetter DontEnum|Function 2
- __defineSetter__ objectProtoFuncDefineSetter DontEnum|Function 2
- __lookupGetter__ objectProtoFuncLookupGetter DontEnum|Function 1
- __lookupSetter__ objectProtoFuncLookupSetter DontEnum|Function 1
-@end
-*/
+const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ObjectPrototype) };
ObjectPrototype::ObjectPrototype(ExecState* exec, Structure* stucture)
- : JSNonFinalObject(exec->globalData(), stucture)
+ : JSNonFinalObject(exec->vm(), stucture)
{
}
-void ObjectPrototype::finishCreation(JSGlobalData& globalData, JSGlobalObject*)
+void ObjectPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject)
{
- Base::finishCreation(globalData);
+ VM& vm = exec->vm();
+
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
- notifyUsedAsPrototype(globalData);
-}
-
-bool ObjectPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
-{
- return getStaticFunctionSlot<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), jsCast<ObjectPrototype*>(cell), propertyName, slot);
+ vm.prototypeMap.addPrototype(this);
+
+ JSC_NATIVE_FUNCTION(vm.propertyNames->toString, objectProtoFuncToString, DontEnum, 0);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->toLocaleString, objectProtoFuncToLocaleString, DontEnum, 0);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->valueOf, objectProtoFuncValueOf, DontEnum, 0);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->hasOwnProperty, objectProtoFuncHasOwnProperty, DontEnum, 1);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable, DontEnum, 1);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->isPrototypeOf, objectProtoFuncIsPrototypeOf, DontEnum, 1);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->__defineGetter__, objectProtoFuncDefineGetter, DontEnum, 2);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->__defineSetter__, objectProtoFuncDefineSetter, DontEnum, 2);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->__lookupGetter__, objectProtoFuncLookupGetter, DontEnum, 1);
+ JSC_NATIVE_FUNCTION(vm.propertyNames->__lookupSetter__, objectProtoFuncLookupSetter, DontEnum, 1);
}
-bool ObjectPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
+ObjectPrototype* ObjectPrototype::create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
{
- return getStaticFunctionDescriptor<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), jsCast<ObjectPrototype*>(object), propertyName, descriptor);
+ ObjectPrototype* prototype = new (NotNull, allocateCell<ObjectPrototype>(*exec->heap())) ObjectPrototype(exec, structure);
+ prototype->finishCreation(exec, globalObject);
+ return prototype;
}
// ------------------------------ Functions --------------------------------
@@ -227,7 +218,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
return JSValue::encode(throwOutOfMemoryError(exec));
result = jsNontrivialString(exec, newString.release());
- thisObject->structure()->setObjectToStringValue(exec->globalData(), thisObject, result);
+ thisObject->structure()->setObjectToStringValue(exec->vm(), thisObject, result);
}
return JSValue::encode(result);
}
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h
index e3551d6fd..cf0143e29 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.h
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h
@@ -29,29 +29,20 @@ namespace JSC {
public:
typedef JSNonFinalObject Base;
- static ObjectPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
- {
- ObjectPrototype* prototype = new (NotNull, allocateCell<ObjectPrototype>(*exec->heap())) ObjectPrototype(exec, structure);
- prototype->finishCreation(exec->globalData(), globalObject);
- return prototype;
- }
+ static ObjectPrototype* create(ExecState*, JSGlobalObject*, Structure*);
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:
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSNonFinalObject::StructureFlags;
-
- void finishCreation(JSGlobalData&, JSGlobalObject*);
+ void finishCreation(ExecState*, JSGlobalObject*);
private:
ObjectPrototype(ExecState*, Structure*);
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
};
JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp
index d96bae575..d6cc0ff57 100644
--- a/Source/JavaScriptCore/runtime/Operations.cpp
+++ b/Source/JavaScriptCore/runtime/Operations.cpp
@@ -56,28 +56,32 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame));
}
-JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
+JSValue jsTypeStringForValue(VM& vm, JSGlobalObject* globalObject, JSValue v)
{
- JSGlobalData& globalData = callFrame->globalData();
if (v.isUndefined())
- return globalData.smallStrings.undefinedString(&globalData);
+ return vm.smallStrings.undefinedString();
if (v.isBoolean())
- return globalData.smallStrings.booleanString(&globalData);
+ return vm.smallStrings.booleanString();
if (v.isNumber())
- return globalData.smallStrings.numberString(&globalData);
+ return vm.smallStrings.numberString();
if (v.isString())
- return globalData.smallStrings.stringString(&globalData);
+ return vm.smallStrings.stringString();
if (v.isObject()) {
// Return "undefined" for objects that should be treated
// as null when doing comparisons.
- if (asObject(v)->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))
- return globalData.smallStrings.undefinedString(&globalData);
+ if (asObject(v)->structure()->masqueradesAsUndefined(globalObject))
+ return vm.smallStrings.undefinedString();
CallData callData;
JSObject* object = asObject(v);
if (object->methodTable()->getCallData(object, callData) != CallTypeNone)
- return globalData.smallStrings.functionString(&globalData);
+ return vm.smallStrings.functionString();
}
- return globalData.smallStrings.objectString(&globalData);
+ return vm.smallStrings.objectString();
+}
+
+JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
+{
+ return jsTypeStringForValue(callFrame->vm(), callFrame->lexicalGlobalObject(), v);
}
bool jsIsObjectType(CallFrame* callFrame, JSValue v)
@@ -86,7 +90,7 @@ bool jsIsObjectType(CallFrame* callFrame, JSValue v)
return v.isNull();
JSType type = v.asCell()->structure()->typeInfo().type();
- if (type == NumberType || type == StringType)
+ if (type == StringType)
return false;
if (type >= ObjectType) {
if (asObject(v)->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index 8e0a0a393..afac13000 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -24,359 +24,263 @@
#include "ExceptionHelpers.h"
#include "Interpreter.h"
+#include "JSCJSValueInlines.h"
+#include "JSFunctionInlines.h"
#include "JSProxy.h"
#include "JSString.h"
-#include "JSValueInlines.h"
+#include "StructureInlines.h"
namespace JSC {
- NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
- JSValue jsTypeStringForValue(CallFrame*, JSValue);
- bool jsIsObjectType(CallFrame*, JSValue);
- bool jsIsFunctionType(JSValue);
-
- ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
- {
- JSGlobalData& globalData = exec->globalData();
-
- unsigned length1 = s1->length();
- if (!length1)
- return s2;
- unsigned length2 = s2->length();
- if (!length2)
- return s1;
- if ((length1 + length2) < length1)
+NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
+JSValue jsTypeStringForValue(CallFrame*, JSValue);
+JSValue jsTypeStringForValue(VM&, JSGlobalObject*, JSValue);
+bool jsIsObjectType(CallFrame*, JSValue);
+bool jsIsFunctionType(JSValue);
+
+ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
+{
+ VM& vm = exec->vm();
+
+ unsigned length1 = s1->length();
+ if (!length1)
+ return s2;
+ unsigned length2 = s2->length();
+ if (!length2)
+ return s1;
+ if ((length1 + length2) < length1)
+ return throwOutOfMemoryError(exec);
+
+ return JSRopeString::create(vm, s1, s2);
+}
+
+ALWAYS_INLINE JSValue jsString(ExecState* exec, const String& u1, const String& u2, const String& u3)
+{
+ VM* vm = &exec->vm();
+
+ unsigned length1 = u1.length();
+ unsigned length2 = u2.length();
+ unsigned length3 = u3.length();
+ if (!length1)
+ return jsString(exec, jsString(vm, u2), jsString(vm, u3));
+ if (!length2)
+ return jsString(exec, jsString(vm, u1), jsString(vm, u3));
+ if (!length3)
+ return jsString(exec, jsString(vm, u1), jsString(vm, u2));
+
+ if ((length1 + length2) < length1)
+ return throwOutOfMemoryError(exec);
+ if ((length1 + length2 + length3) < length3)
+ return throwOutOfMemoryError(exec);
+
+ return JSRopeString::create(exec->vm(), jsString(vm, u1), jsString(vm, u2), jsString(vm, u3));
+}
+
+ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
+{
+ VM* vm = &exec->vm();
+ JSRopeString::RopeBuilder ropeBuilder(*vm);
+
+ unsigned oldLength = 0;
+
+ for (unsigned i = 0; i < count; ++i) {
+ JSValue v = strings[i].jsValue();
+ ropeBuilder.append(v.toString(exec));
+
+ if (ropeBuilder.length() < oldLength) // True for overflow
return throwOutOfMemoryError(exec);
-
- return JSRopeString::create(globalData, s1, s2);
- }
-
- ALWAYS_INLINE JSValue jsString(ExecState* exec, const String& u1, const String& u2, const String& u3)
- {
- JSGlobalData* globalData = &exec->globalData();
-
- unsigned length1 = u1.length();
- unsigned length2 = u2.length();
- unsigned length3 = u3.length();
- if (!length1)
- return jsString(exec, jsString(globalData, u2), jsString(globalData, u3));
- if (!length2)
- return jsString(exec, jsString(globalData, u1), jsString(globalData, u3));
- if (!length3)
- return jsString(exec, jsString(globalData, u1), jsString(globalData, u2));
-
- if ((length1 + length2) < length1)
- return throwOutOfMemoryError(exec);
- if ((length1 + length2 + length3) < length3)
- return throwOutOfMemoryError(exec);
-
- return JSRopeString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3));
+ oldLength = ropeBuilder.length();
}
- ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
- {
- JSGlobalData* globalData = &exec->globalData();
- JSRopeString::RopeBuilder ropeBuilder(*globalData);
+ return ropeBuilder.release();
+}
- unsigned oldLength = 0;
-
- for (unsigned i = 0; i < count; ++i) {
- JSValue v = strings[i].jsValue();
- ropeBuilder.append(v.toString(exec));
-
- if (ropeBuilder.length() < oldLength) // True for overflow
- return throwOutOfMemoryError(exec);
- oldLength = ropeBuilder.length();
- }
-
- return ropeBuilder.release();
- }
+ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
+{
+ VM* vm = &exec->vm();
+ JSRopeString::RopeBuilder ropeBuilder(*vm);
+ ropeBuilder.append(thisValue.toString(exec));
- ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
- {
- JSGlobalData* globalData = &exec->globalData();
- JSRopeString::RopeBuilder ropeBuilder(*globalData);
- ropeBuilder.append(thisValue.toString(exec));
+ unsigned oldLength = 0;
- unsigned oldLength = 0;
-
- for (unsigned i = 0; i < exec->argumentCount(); ++i) {
- JSValue v = exec->argument(i);
- ropeBuilder.append(v.toString(exec));
-
- if (ropeBuilder.length() < oldLength) // True for overflow
- return throwOutOfMemoryError(exec);
- oldLength = ropeBuilder.length();
- }
-
- return ropeBuilder.release();
- }
-
- // ECMA 11.9.3
- inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
- {
- if (v1.isInt32() && v2.isInt32())
- return v1 == v2;
-
- return equalSlowCase(exec, v1, v2);
- }
-
- ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
- {
- do {
- if (v1.isNumber() && v2.isNumber())
- return v1.asNumber() == v2.asNumber();
-
- bool s1 = v1.isString();
- bool s2 = v2.isString();
- if (s1 && s2)
- return asString(v1)->value(exec) == asString(v2)->value(exec);
-
- if (v1.isUndefinedOrNull()) {
- if (v2.isUndefinedOrNull())
- return true;
- if (!v2.isCell())
- return false;
- return v2.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
- }
-
- if (v2.isUndefinedOrNull()) {
- if (!v1.isCell())
- return false;
- return v1.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
- }
-
- if (v1.isObject()) {
- if (v2.isObject())
- return v1 == v2;
- JSValue p1 = v1.toPrimitive(exec);
- if (exec->hadException())
- return false;
- v1 = p1;
- if (v1.isInt32() && v2.isInt32())
- return v1 == v2;
- continue;
- }
-
- if (v2.isObject()) {
- JSValue p2 = v2.toPrimitive(exec);
- if (exec->hadException())
- return false;
- v2 = p2;
- if (v1.isInt32() && v2.isInt32())
- return v1 == v2;
- continue;
- }
-
- if (s1 || s2) {
- double d1 = v1.toNumber(exec);
- double d2 = v2.toNumber(exec);
- return d1 == d2;
- }
-
- if (v1.isBoolean()) {
- if (v2.isNumber())
- return static_cast<double>(v1.asBoolean()) == v2.asNumber();
- } else if (v2.isBoolean()) {
- if (v1.isNumber())
- return v1.asNumber() == static_cast<double>(v2.asBoolean());
- }
-
- return v1 == v2;
- } while (true);
- }
+ for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+ JSValue v = exec->argument(i);
+ ropeBuilder.append(v.toString(exec));
- // ECMA 11.9.3
- ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
- {
- ASSERT(v1.isCell() && v2.isCell());
-
- if (v1.asCell()->isString() && v2.asCell()->isString())
- return asString(v1)->value(exec) == asString(v2)->value(exec);
-
- return v1 == v2;
- }
-
- inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
- {
- if (v1.isInt32() && v2.isInt32())
- return v1 == v2;
-
- if (v1.isNumber() && v2.isNumber())
- return v1.asNumber() == v2.asNumber();
-
- if (!v1.isCell() || !v2.isCell())
- return v1 == v2;
-
- return strictEqualSlowCaseInline(exec, v1, v2);
+ if (ropeBuilder.length() < oldLength) // True for overflow
+ return throwOutOfMemoryError(exec);
+ oldLength = ropeBuilder.length();
}
- // See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct
- // evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value
- // true, for leftFirst, for '>' pass the value false (and reverse operand order).
- template<bool leftFirst>
- ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
- {
- if (v1.isInt32() && v2.isInt32())
- return v1.asInt32() < v2.asInt32();
-
- if (v1.isNumber() && v2.isNumber())
- return v1.asNumber() < v2.asNumber();
-
- if (isJSString(v1) && isJSString(v2))
- return codePointCompareLessThan(asString(v1)->value(callFrame), asString(v2)->value(callFrame));
-
- double n1;
- double n2;
- JSValue p1;
- JSValue p2;
- bool wasNotString1;
- bool wasNotString2;
- if (leftFirst) {
- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
- } else {
- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
- }
-
- if (wasNotString1 | wasNotString2)
- return n1 < n2;
- return codePointCompareLessThan(asString(p1)->value(callFrame), asString(p2)->value(callFrame));
+ return ropeBuilder.release();
+}
+
+// See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct
+// evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value
+// true, for leftFirst, for '>' pass the value false (and reverse operand order).
+template<bool leftFirst>
+ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
+{
+ if (v1.isInt32() && v2.isInt32())
+ return v1.asInt32() < v2.asInt32();
+
+ if (v1.isNumber() && v2.isNumber())
+ return v1.asNumber() < v2.asNumber();
+
+ if (isJSString(v1) && isJSString(v2))
+ return codePointCompareLessThan(asString(v1)->value(callFrame), asString(v2)->value(callFrame));
+
+ double n1;
+ double n2;
+ JSValue p1;
+ JSValue p2;
+ bool wasNotString1;
+ bool wasNotString2;
+ if (leftFirst) {
+ wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ } else {
+ wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
}
- // See ES5 11.8.3/11.8.4/11.8.5 for definition of leftFirst, this value ensures correct
- // evaluation ordering for argument conversions for '<=' and '=>'. For '<=' pass the
- // value true, for leftFirst, for '=>' pass the value false (and reverse operand order).
- template<bool leftFirst>
- ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
- {
- if (v1.isInt32() && v2.isInt32())
- return v1.asInt32() <= v2.asInt32();
-
- if (v1.isNumber() && v2.isNumber())
- return v1.asNumber() <= v2.asNumber();
-
- if (isJSString(v1) && isJSString(v2))
- return !codePointCompareLessThan(asString(v2)->value(callFrame), asString(v1)->value(callFrame));
-
- double n1;
- double n2;
- JSValue p1;
- JSValue p2;
- bool wasNotString1;
- bool wasNotString2;
- if (leftFirst) {
- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
- } else {
- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
- }
-
- if (wasNotString1 | wasNotString2)
- return n1 <= n2;
- return !codePointCompareLessThan(asString(p2)->value(callFrame), asString(p1)->value(callFrame));
+ if (wasNotString1 | wasNotString2)
+ return n1 < n2;
+ return codePointCompareLessThan(asString(p1)->value(callFrame), asString(p2)->value(callFrame));
+}
+
+// See ES5 11.8.3/11.8.4/11.8.5 for definition of leftFirst, this value ensures correct
+// evaluation ordering for argument conversions for '<=' and '=>'. For '<=' pass the
+// value true, for leftFirst, for '=>' pass the value false (and reverse operand order).
+template<bool leftFirst>
+ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
+{
+ if (v1.isInt32() && v2.isInt32())
+ return v1.asInt32() <= v2.asInt32();
+
+ if (v1.isNumber() && v2.isNumber())
+ return v1.asNumber() <= v2.asNumber();
+
+ if (isJSString(v1) && isJSString(v2))
+ return !codePointCompareLessThan(asString(v2)->value(callFrame), asString(v1)->value(callFrame));
+
+ double n1;
+ double n2;
+ JSValue p1;
+ JSValue p2;
+ bool wasNotString1;
+ bool wasNotString2;
+ if (leftFirst) {
+ wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
+ wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ } else {
+ wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
+ wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
}
- // Fast-path choices here are based on frequency data from SunSpider:
- // <times> Add case: <t1> <t2>
- // ---------------------------
- // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
- // 247412 Add case: 5 5
- // 20900 Add case: 5 6
- // 13962 Add case: 5 3
- // 4000 Add case: 3 5
-
- ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
- {
- if (v1.isNumber() && v2.isNumber())
- return jsNumber(v1.asNumber() + v2.asNumber());
+ if (wasNotString1 | wasNotString2)
+ return n1 <= n2;
+ return !codePointCompareLessThan(asString(p2)->value(callFrame), asString(p1)->value(callFrame));
+}
+
+// Fast-path choices here are based on frequency data from SunSpider:
+// <times> Add case: <t1> <t2>
+// ---------------------------
+// 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
+// 247412 Add case: 5 5
+// 20900 Add case: 5 6
+// 13962 Add case: 5 3
+// 4000 Add case: 3 5
+
+ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
+{
+ if (v1.isNumber() && v2.isNumber())
+ return jsNumber(v1.asNumber() + v2.asNumber());
- if (v1.isString() && !v2.isObject())
- return jsString(callFrame, asString(v1), v2.toString(callFrame));
+ if (v1.isString() && !v2.isObject())
+ return jsString(callFrame, asString(v1), v2.toString(callFrame));
- // All other cases are pretty uncommon
- return jsAddSlowCase(callFrame, v1, v2);
- }
+ // All other cases are pretty uncommon
+ return jsAddSlowCase(callFrame, v1, v2);
+}
#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
- inline size_t normalizePrototypeChainForChainAccess(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
- {
- JSCell* cell = base.asCell();
- size_t count = 0;
+inline size_t normalizePrototypeChainForChainAccess(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
+{
+ JSCell* cell = base.asCell();
+ size_t count = 0;
- while (slotBase != cell) {
- if (cell->isProxy())
- return InvalidPrototypeChain;
+ while (slotBase != cell) {
+ if (cell->isProxy())
+ return InvalidPrototypeChain;
- if (cell->structure()->typeInfo().hasImpureGetOwnPropertySlot())
- return InvalidPrototypeChain;
+ if (cell->structure()->typeInfo().hasImpureGetOwnPropertySlot())
+ return InvalidPrototypeChain;
- JSValue v = cell->structure()->prototypeForLookup(callFrame);
+ JSValue v = cell->structure()->prototypeForLookup(callFrame);
- // If we didn't find slotBase in base's prototype chain, then base
- // must be a proxy for another object.
+ // If we didn't find slotBase in base's prototype chain, then base
+ // must be a proxy for another object.
- if (v.isNull())
- return InvalidPrototypeChain;
+ if (v.isNull())
+ return InvalidPrototypeChain;
- cell = v.asCell();
+ cell = v.asCell();
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (cell->structure()->isDictionary()) {
- asObject(cell)->flattenDictionaryObject(callFrame->globalData());
- if (slotBase == cell)
- slotOffset = cell->structure()->get(callFrame->globalData(), propertyName);
- }
-
- ++count;
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (cell->structure()->isDictionary()) {
+ asObject(cell)->flattenDictionaryObject(callFrame->vm());
+ if (slotBase == cell)
+ slotOffset = cell->structure()->get(callFrame->vm(), propertyName);
}
-
- ASSERT(count);
- return count;
+
+ ++count;
}
-
- inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
- {
- size_t count = 0;
- while (1) {
- if (base->isProxy())
- return InvalidPrototypeChain;
+
+ ASSERT(count);
+ return count;
+}
+
+inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
+{
+ size_t count = 0;
+ while (1) {
+ if (base->isProxy())
+ return InvalidPrototypeChain;
- JSValue v = base->structure()->prototypeForLookup(callFrame);
- if (v.isNull())
- return count;
+ JSValue v = base->structure()->prototypeForLookup(callFrame);
+ if (v.isNull())
+ return count;
- base = v.asCell();
+ base = v.asCell();
- // Since we're accessing a prototype in a loop, it's a good bet that it
- // should not be treated as a dictionary.
- if (base->structure()->isDictionary())
- asObject(base)->flattenDictionaryObject(callFrame->globalData());
+ // Since we're accessing a prototype in a loop, it's a good bet that it
+ // should not be treated as a dictionary.
+ if (base->structure()->isDictionary())
+ asObject(base)->flattenDictionaryObject(callFrame->vm());
- ++count;
- }
+ ++count;
}
+}
- inline bool isPrototypeChainNormalized(JSGlobalObject* globalObject, Structure* structure)
- {
- for (;;) {
- if (structure->typeInfo().type() == ProxyType)
- return false;
+inline bool isPrototypeChainNormalized(JSGlobalObject* globalObject, Structure* structure)
+{
+ for (;;) {
+ if (structure->typeInfo().type() == ProxyType)
+ return false;
- JSValue v = structure->prototypeForLookup(globalObject);
- if (v.isNull())
- return true;
+ JSValue v = structure->prototypeForLookup(globalObject);
+ if (v.isNull())
+ return true;
- structure = v.asCell()->structure();
+ structure = v.asCell()->structure();
- if (structure->isDictionary())
- return false;
- }
+ if (structure->isDictionary())
+ return false;
}
+}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 386eb4fcf..40711bfa3 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -36,7 +36,6 @@
#include <wtf/PageBlock.h>
#include <wtf/StdLibExtras.h>
#include <wtf/StringExtras.h>
-#include <wtf/UnusedParam.h>
#if OS(DARWIN) && ENABLE(PARALLEL_GC)
#include <sys/sysctl.h>
@@ -72,6 +71,11 @@ static bool parse(const char* string, double& value)
return sscanf(string, "%lf", &value) == 1;
}
+static bool parse(const char* string, OptionRange& value)
+{
+ return value.init(string);
+}
+
template<typename T>
void overrideOptionWithHeuristic(T& variable, const char* name)
{
@@ -105,6 +109,59 @@ static unsigned computeNumberOfGCMarkers(int maxNumberOfGCMarkers)
return cpusToUse;
}
+bool OptionRange::init(const char* rangeString)
+{
+ // rangeString should be in the form of [!]<low>[:<high>]
+ // where low and high are unsigned
+
+ bool invert = false;
+
+ if (m_state > Uninitialized)
+ return true;
+
+ if (!rangeString) {
+ m_state = InitError;
+ return false;
+ }
+
+ m_rangeString = rangeString;
+
+ if (*rangeString == '!') {
+ invert = true;
+ rangeString++;
+ }
+
+ int scanResult = sscanf(rangeString, " %u:%u", &m_lowLimit, &m_highLimit);
+
+ if (!scanResult || scanResult == EOF) {
+ m_state = InitError;
+ return false;
+ }
+
+ if (scanResult == 1)
+ m_highLimit = m_lowLimit;
+
+ if (m_lowLimit > m_highLimit) {
+ m_state = InitError;
+ return false;
+ }
+
+ m_state = invert ? Inverted : Normal;
+
+ return true;
+}
+
+bool OptionRange::isInRange(unsigned count)
+{
+ if (m_state < Normal)
+ return true;
+
+ if ((m_lowLimit <= count) && (count <= m_highLimit))
+ return m_state == Normal ? true : false;
+
+ return m_state == Normal ? false : true;
+}
+
Options::Entry Options::s_options[Options::numberOfOptions];
// Realize the names for each of the options:
@@ -187,6 +244,7 @@ bool Options::setOption(const char* arg)
#define FOR_EACH_OPTION(type_, name_, defaultValue_) \
if (!strncmp(arg, #name_, equalStr - arg)) { \
type_ value; \
+ value = 0; \
bool success = parse(valueStr, value); \
if (success) { \
name_() = value; \
@@ -227,6 +285,9 @@ void Options::dumpOption(OptionID id, FILE* stream, const char* header, const ch
case int32Type:
fprintf(stream, "%d", s_options[id].u.int32Val);
break;
+ case optionRangeType:
+ fprintf(stream, "%s", s_options[id].u.optionRangeVal.rangeString());
+ break;
}
fprintf(stream, "%s", footer);
}
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index bf4a0cf75..559b6084b 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -60,6 +60,33 @@ namespace JSC {
// values after the sanity checks (for your own testing), then you're liable to
// ensure that the new values set are sane and reasonable for your own run.
+class OptionRange {
+private:
+ enum RangeState { Uninitialized, InitError, Normal, Inverted };
+public:
+ OptionRange& operator= (const int& rhs)
+ { // Only needed for initialization
+ if (!rhs) {
+ m_state = Uninitialized;
+ m_rangeString = 0;
+ m_lowLimit = 0;
+ m_highLimit = 0;
+ }
+ return *this;
+ }
+
+ bool init(const char*);
+ bool isInRange(unsigned);
+ const char* rangeString() { return (m_state > InitError) ? m_rangeString : "<null>"; }
+
+private:
+ RangeState m_state;
+ const char* m_rangeString;
+ unsigned m_lowLimit;
+ unsigned m_highLimit;
+};
+
+typedef OptionRange optionRange;
#define JSC_OPTIONS(v) \
v(bool, useJIT, true) \
@@ -74,10 +101,21 @@ namespace JSC {
v(bool, showDisassembly, false) \
v(bool, showDFGDisassembly, false) \
v(bool, showAllDFGNodes, false) \
+ v(optionRange, bytecodeRangeToDFGCompile, 0) \
+ v(bool, dumpBytecodeAtDFGTime, false) \
+ v(bool, dumpGraphAtEachPhase, false) \
+ v(bool, verboseCompilation, false) \
+ v(bool, logCompilationChanges, false) \
+ v(bool, printEachOSRExit, false) \
+ v(bool, validateGraph, false) \
+ v(bool, validateGraphAtEachPhase, false) \
+ \
+ v(bool, enableProfiler, false) \
\
v(unsigned, maximumOptimizationCandidateInstructionCount, 10000) \
\
v(unsigned, maximumFunctionForCallInlineCandidateInstructionCount, 180) \
+ v(unsigned, maximumFunctionForClosureCallInlineCandidateInstructionCount, 100) \
v(unsigned, maximumFunctionForConstructInlineCandidateInstructionCount, 100) \
\
/* Depth of inline stack, so 1 = no inlining, 2 = one level, etc. */ \
@@ -87,21 +125,20 @@ namespace JSC {
v(int32, thresholdForJITSoon, 100) \
\
v(int32, thresholdForOptimizeAfterWarmUp, 1000) \
- v(int32, thresholdForOptimizeAfterLongWarmUp, 5000) \
+ v(int32, thresholdForOptimizeAfterLongWarmUp, 1000) \
v(int32, thresholdForOptimizeSoon, 1000) \
\
v(int32, executionCounterIncrementForLoop, 1) \
v(int32, executionCounterIncrementForReturn, 15) \
\
+ v(int32, evalThresholdMultiplier, 10) \
+ \
v(bool, randomizeExecutionCountsBetweenCheckpoints, false) \
v(int32, maximumExecutionCountsBetweenCheckpoints, 1000) \
\
- v(double, likelyToTakeSlowCaseThreshold, 0.15) \
- v(double, couldTakeSlowCaseThreshold, 0.05) \
v(unsigned, likelyToTakeSlowCaseMinimumCount, 100) \
v(unsigned, couldTakeSlowCaseMinimumCount, 10) \
\
- v(double, osrExitProminenceForFrequentExitSite, 0.3) \
v(unsigned, osrExitCountForReoptimization, 100) \
v(unsigned, osrExitCountForReoptimizationFromLoop, 5) \
\
@@ -170,6 +207,7 @@ private:
unsignedType,
doubleType,
int32Type,
+ optionRangeType,
};
// For storing for an option value:
@@ -179,6 +217,7 @@ private:
unsigned unsignedVal;
double doubleVal;
int32 int32Val;
+ OptionRange optionRangeVal;
} u;
};
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
index 236a8e5ae..14b42fd9a 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -176,8 +176,8 @@ bool sameValue(ExecState* exec, JSValue a, JSValue b)
return false;
double x = a.asNumber();
double y = b.asNumber();
- if (isnan(x))
- return isnan(y);
+ if (std::isnan(x))
+ return std::isnan(y);
return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
}
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.h b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
index 2c3878f57..5a5857d1c 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.h
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
@@ -26,7 +26,7 @@
#ifndef PropertyDescriptor_h
#define PropertyDescriptor_h
-#include "JSValue.h"
+#include "JSCJSValue.h"
namespace JSC {
class GetterSetter;
diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
index 9c6ddb20f..9ddb6997c 100644
--- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -22,8 +22,10 @@
#define PropertyMapHashTable_h
#include "PropertyOffset.h"
+#include "Structure.h"
#include "WriteBarrier.h"
#include <wtf/HashTable.h>
+#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
#include <wtf/text/StringImpl.h>
@@ -50,9 +52,7 @@ namespace JSC {
inline bool isPowerOf2(unsigned v)
{
- // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
-
- return !(v & (v - 1)) && v;
+ return hasOneBitSet(v);
}
inline unsigned nextPowerOf2(unsigned v)
@@ -77,17 +77,16 @@ struct PropertyMapEntry {
unsigned attributes;
WriteBarrier<JSCell> specificValue;
- PropertyMapEntry(JSGlobalData& globalData, JSCell* owner, StringImpl* key, PropertyOffset offset, unsigned attributes, JSCell* specificValue)
+ PropertyMapEntry(VM& vm, JSCell* owner, StringImpl* key, PropertyOffset offset, unsigned attributes, JSCell* specificValue)
: key(key)
, offset(offset)
, attributes(attributes)
- , specificValue(globalData, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
+ , specificValue(vm, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
{
}
};
-class PropertyTable {
- WTF_MAKE_FAST_ALLOCATED;
+class PropertyTable : public JSCell {
// This is the implementation for 'iterator' and 'const_iterator',
// used for iterating over the table in insertion order.
@@ -130,6 +129,19 @@ class PropertyTable {
};
public:
+ static const bool needsDestruction = true;
+ static const bool hasImmortalStructure = true;
+ static void destroy(JSCell*);
+
+ static JS_EXPORTDATA const ClassInfo s_info;
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
+ }
+
+ static void visitChildren(JSCell*, SlotVisitor&);
+
typedef StringImpl* KeyType;
typedef PropertyMapEntry ValueType;
@@ -143,9 +155,9 @@ public:
typedef std::pair<ValueType*, unsigned> find_iterator;
// Constructor is passed an initial capacity, a PropertyTable to copy, or both.
- explicit PropertyTable(unsigned initialCapacity);
- PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);
- PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);
+ static PropertyTable* create(VM&, unsigned initialCapacity);
+ static PropertyTable* clone(VM&, JSCell* owner, const PropertyTable&);
+ static PropertyTable* clone(VM&, JSCell* owner, unsigned initialCapacity, const PropertyTable&);
~PropertyTable();
// Ordered iteration methods.
@@ -158,7 +170,8 @@ public:
find_iterator find(const KeyType&);
find_iterator findWithString(const KeyType&);
// Add a value to the table
- std::pair<find_iterator, bool> add(const ValueType& entry);
+ enum EffectOnPropertyOffset { PropertyOffsetMayChange, PropertyOffsetMustNotChange };
+ std::pair<find_iterator, bool> add(const ValueType& entry, PropertyOffset&, EffectOnPropertyOffset);
// Remove a value from the table.
void remove(const find_iterator& iter);
void remove(const KeyType& key);
@@ -181,7 +194,7 @@ public:
PropertyOffset nextOffset(PropertyOffset inlineCapacity);
// Copy this PropertyTable, ensuring the copy has at least the capacity provided.
- PassOwnPtr<PropertyTable> copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);
+ PropertyTable* copy(VM&, JSCell* owner, unsigned newCapacity);
#ifndef NDEBUG
size_t sizeInMemory();
@@ -189,6 +202,10 @@ public:
#endif
private:
+ PropertyTable(VM&, unsigned initialCapacity);
+ PropertyTable(VM&, JSCell*, const PropertyTable&);
+ PropertyTable(VM&, JSCell*, unsigned initialCapacity, const PropertyTable&);
+
PropertyTable(const PropertyTable&);
// Used to insert a value known not to be in the table, and where we know capacity to be available.
void reinsert(const ValueType& entry);
@@ -235,76 +252,10 @@ private:
unsigned m_deletedCount;
OwnPtr< Vector<PropertyOffset> > m_deletedOffsets;
- static const unsigned MinimumTableSize = 16;
+ static const unsigned MinimumTableSize = 8;
static const unsigned EmptyEntryIndex = 0;
};
-inline PropertyTable::PropertyTable(unsigned initialCapacity)
- : m_indexSize(sizeForCapacity(initialCapacity))
- , m_indexMask(m_indexSize - 1)
- , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
- , m_keyCount(0)
- , m_deletedCount(0)
-{
- ASSERT(isPowerOf2(m_indexSize));
-}
-
-inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, const PropertyTable& other)
- : m_indexSize(other.m_indexSize)
- , m_indexMask(other.m_indexMask)
- , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))
- , m_keyCount(other.m_keyCount)
- , m_deletedCount(other.m_deletedCount)
-{
- ASSERT(isPowerOf2(m_indexSize));
-
- memcpy(m_index, other.m_index, dataSize());
-
- iterator end = this->end();
- for (iterator iter = begin(); iter != end; ++iter) {
- iter->key->ref();
- Heap::writeBarrier(owner, iter->specificValue.get());
- }
-
- // Copy the m_deletedOffsets vector.
- Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
- if (otherDeletedOffsets)
- m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
-}
-
-inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
- : m_indexSize(sizeForCapacity(initialCapacity))
- , m_indexMask(m_indexSize - 1)
- , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
- , m_keyCount(0)
- , m_deletedCount(0)
-{
- ASSERT(isPowerOf2(m_indexSize));
- ASSERT(initialCapacity >= other.m_keyCount);
-
- const_iterator end = other.end();
- for (const_iterator iter = other.begin(); iter != end; ++iter) {
- ASSERT(canInsert());
- reinsert(*iter);
- iter->key->ref();
- Heap::writeBarrier(owner, iter->specificValue.get());
- }
-
- // Copy the m_deletedOffsets vector.
- Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
- if (otherDeletedOffsets)
- m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
-}
-
-inline PropertyTable::~PropertyTable()
-{
- iterator end = this->end();
- for (iterator iter = begin(); iter != end; ++iter)
- iter->key->deref();
-
- fastFree(m_index);
-}
-
inline PropertyTable::iterator PropertyTable::begin()
{
return iterator(skipDeletedEntries(table()));
@@ -390,12 +341,14 @@ inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType&
}
}
-inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry)
+inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry, PropertyOffset& offset, EffectOnPropertyOffset offsetEffect)
{
// Look for a value with a matching key already in the array.
find_iterator iter = find(entry.key);
- if (iter.first)
+ if (iter.first) {
+ RELEASE_ASSERT(iter.first->offset <= offset);
return std::make_pair(iter, false);
+ }
// Ref the key
entry.key->ref();
@@ -414,6 +367,12 @@ inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const Va
*iter.first = entry;
++m_keyCount;
+
+ if (offsetEffect == PropertyOffsetMayChange)
+ offset = std::max(offset, entry.offset);
+ else
+ RELEASE_ASSERT(offset >= entry.offset);
+
return std::make_pair(iter, true);
}
@@ -491,18 +450,18 @@ inline PropertyOffset PropertyTable::nextOffset(PropertyOffset inlineCapacity)
if (hasDeletedOffset())
return getDeletedOffset();
- return propertyOffsetFor(size(), inlineCapacity);
+ return offsetForPropertyNumber(size(), inlineCapacity);
}
-inline PassOwnPtr<PropertyTable> PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)
+inline PropertyTable* PropertyTable::copy(VM& vm, JSCell* owner, unsigned newCapacity)
{
ASSERT(newCapacity >= m_keyCount);
// Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it,
// save rehashing all keys.
if (sizeForCapacity(newCapacity) == m_indexSize)
- return adoptPtr(new PropertyTable(globalData, owner, *this));
- return adoptPtr(new PropertyTable(globalData, owner, newCapacity, *this));
+ return PropertyTable::clone(vm, owner, *this);
+ return PropertyTable::clone(vm, owner, newCapacity, *this);
}
#ifndef NDEBUG
@@ -588,7 +547,7 @@ inline size_t PropertyTable::dataSize()
inline unsigned PropertyTable::sizeForCapacity(unsigned capacity)
{
- if (capacity < 8)
+ if (capacity < MinimumTableSize / 2)
return MinimumTableSize;
return nextPowerOf2(capacity + 1) * 2;
}
diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.h b/Source/JavaScriptCore/runtime/PropertyNameArray.h
index 1cdac0049..96f1d0afa 100644
--- a/Source/JavaScriptCore/runtime/PropertyNameArray.h
+++ b/Source/JavaScriptCore/runtime/PropertyNameArray.h
@@ -52,9 +52,9 @@ namespace JSC {
// FIXME: Rename to PropertyNameArrayBuilder.
class PropertyNameArray {
public:
- PropertyNameArray(JSGlobalData* globalData)
+ PropertyNameArray(VM* vm)
: m_data(PropertyNameArrayData::create())
- , m_globalData(globalData)
+ , m_vm(vm)
, m_numCacheableSlots(0)
, m_baseObject(0)
{
@@ -62,17 +62,17 @@ namespace JSC {
PropertyNameArray(ExecState* exec)
: m_data(PropertyNameArrayData::create())
- , m_globalData(&exec->globalData())
+ , m_vm(&exec->vm())
, m_numCacheableSlots(0)
, m_baseObject(0)
{
}
- JSGlobalData* globalData() { return m_globalData; }
+ VM* vm() { return m_vm; }
void add(const Identifier& identifier) { add(identifier.impl()); }
JS_EXPORT_PRIVATE void add(StringImpl*);
- void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
+ void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_vm, identifier)); }
Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
@@ -106,7 +106,7 @@ namespace JSC {
RefPtr<PropertyNameArrayData> m_data;
IdentifierSet m_set;
- JSGlobalData* m_globalData;
+ VM* m_vm;
size_t m_numCacheableSlots;
JSObject* m_baseObject;
};
diff --git a/Source/JavaScriptCore/runtime/PropertyOffset.h b/Source/JavaScriptCore/runtime/PropertyOffset.h
index 1a2bba446..dc0297bf7 100644
--- a/Source/JavaScriptCore/runtime/PropertyOffset.h
+++ b/Source/JavaScriptCore/runtime/PropertyOffset.h
@@ -28,16 +28,9 @@
#include <wtf/Platform.h>
#include <wtf/StdLibExtras.h>
-#include <wtf/UnusedParam.h>
namespace JSC {
-#if USE(JSVALUE32_64)
-#define INLINE_STORAGE_CAPACITY 7
-#else
-#define INLINE_STORAGE_CAPACITY 6
-#endif
-
typedef int PropertyOffset;
static const PropertyOffset invalidOffset = -1;
@@ -45,9 +38,9 @@ static const PropertyOffset firstOutOfLineOffset = 100;
// Declare all of the functions because they tend to do forward calls.
inline void checkOffset(PropertyOffset);
-inline void checkOffset(PropertyOffset, PropertyOffset inlineCapacity);
+inline void checkOffset(PropertyOffset, int inlineCapacity);
inline void validateOffset(PropertyOffset);
-inline void validateOffset(PropertyOffset, PropertyOffset inlineCapacity);
+inline void validateOffset(PropertyOffset, int inlineCapacity);
inline bool isValidOffset(PropertyOffset);
inline bool isInlineOffset(PropertyOffset);
inline bool isOutOfLineOffset(PropertyOffset);
@@ -55,7 +48,7 @@ inline size_t offsetInInlineStorage(PropertyOffset);
inline size_t offsetInOutOfLineStorage(PropertyOffset);
inline size_t offsetInRespectiveStorage(PropertyOffset);
inline size_t numberOfOutOfLineSlotsForLastOffset(PropertyOffset);
-inline size_t numberOfSlotsForLastOffset(PropertyOffset, PropertyOffset inlineCapacity);
+inline size_t numberOfSlotsForLastOffset(PropertyOffset, int inlineCapacity);
inline void checkOffset(PropertyOffset offset)
{
@@ -63,7 +56,7 @@ inline void checkOffset(PropertyOffset offset)
ASSERT(offset >= invalidOffset);
}
-inline void checkOffset(PropertyOffset offset, PropertyOffset inlineCapacity)
+inline void checkOffset(PropertyOffset offset, int inlineCapacity)
{
UNUSED_PARAM(offset);
UNUSED_PARAM(inlineCapacity);
@@ -79,7 +72,7 @@ inline void validateOffset(PropertyOffset offset)
ASSERT(isValidOffset(offset));
}
-inline void validateOffset(PropertyOffset offset, PropertyOffset inlineCapacity)
+inline void validateOffset(PropertyOffset offset, int inlineCapacity)
{
checkOffset(offset, inlineCapacity);
ASSERT(isValidOffset(offset));
@@ -132,7 +125,7 @@ inline size_t numberOfOutOfLineSlotsForLastOffset(PropertyOffset offset)
return offset - firstOutOfLineOffset + 1;
}
-inline size_t numberOfSlotsForLastOffset(PropertyOffset offset, PropertyOffset inlineCapacity)
+inline size_t numberOfSlotsForLastOffset(PropertyOffset offset, int inlineCapacity)
{
checkOffset(offset, inlineCapacity);
if (offset < inlineCapacity)
@@ -140,7 +133,7 @@ inline size_t numberOfSlotsForLastOffset(PropertyOffset offset, PropertyOffset i
return inlineCapacity + numberOfOutOfLineSlotsForLastOffset(offset);
}
-inline PropertyOffset propertyOffsetFor(PropertyOffset propertyNumber, PropertyOffset inlineCapacity)
+inline PropertyOffset offsetForPropertyNumber(int propertyNumber, int inlineCapacity)
{
PropertyOffset offset = propertyNumber;
if (offset >= inlineCapacity) {
diff --git a/Source/JavaScriptCore/runtime/PropertySlot.cpp b/Source/JavaScriptCore/runtime/PropertySlot.cpp
index 8ac874115..291ea487c 100644
--- a/Source/JavaScriptCore/runtime/PropertySlot.cpp
+++ b/Source/JavaScriptCore/runtime/PropertySlot.cpp
@@ -23,6 +23,7 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/PropertySlot.h b/Source/JavaScriptCore/runtime/PropertySlot.h
index c673eaa50..6fb80d23d 100644
--- a/Source/JavaScriptCore/runtime/PropertySlot.h
+++ b/Source/JavaScriptCore/runtime/PropertySlot.h
@@ -21,7 +21,7 @@
#ifndef PropertySlot_h
#define PropertySlot_h
-#include "JSValue.h"
+#include "JSCJSValue.h"
#include "PropertyName.h"
#include "PropertyOffset.h"
#include "Register.h"
diff --git a/Source/JavaScriptCore/runtime/PropertyTable.cpp b/Source/JavaScriptCore/runtime/PropertyTable.cpp
new file mode 100644
index 000000000..bb5ecce4a
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/PropertyTable.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PropertyMapHashTable.h"
+
+#include "JSCJSValueInlines.h"
+#include "JSCellInlines.h"
+#include "SlotVisitorInlines.h"
+#include "StructureInlines.h"
+
+namespace JSC {
+
+const ClassInfo PropertyTable::s_info = { "PropertyTable", 0, 0, 0, CREATE_METHOD_TABLE(PropertyTable) };
+
+PropertyTable* PropertyTable::create(VM& vm, unsigned initialCapacity)
+{
+ PropertyTable* table = new (NotNull, allocateCell<PropertyTable>(vm.heap)) PropertyTable(vm, initialCapacity);
+ table->finishCreation(vm);
+ return table;
+}
+
+PropertyTable* PropertyTable::clone(VM& vm, JSCell* owner, const PropertyTable& other)
+{
+ PropertyTable* table = new (NotNull, allocateCell<PropertyTable>(vm.heap)) PropertyTable(vm, owner, other);
+ table->finishCreation(vm);
+ return table;
+}
+
+PropertyTable* PropertyTable::clone(VM& vm, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
+{
+ PropertyTable* table = new (NotNull, allocateCell<PropertyTable>(vm.heap)) PropertyTable(vm, owner, initialCapacity, other);
+ table->finishCreation(vm);
+ return table;
+}
+
+PropertyTable::PropertyTable(VM& vm, unsigned initialCapacity)
+ : JSCell(vm, vm.propertyTableStructure.get())
+ , m_indexSize(sizeForCapacity(initialCapacity))
+ , m_indexMask(m_indexSize - 1)
+ , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+ , m_keyCount(0)
+ , m_deletedCount(0)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+}
+
+PropertyTable::PropertyTable(VM& vm, JSCell* owner, const PropertyTable& other)
+ : JSCell(vm, vm.propertyTableStructure.get())
+ , m_indexSize(other.m_indexSize)
+ , m_indexMask(other.m_indexMask)
+ , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))
+ , m_keyCount(other.m_keyCount)
+ , m_deletedCount(other.m_deletedCount)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+
+ memcpy(m_index, other.m_index, dataSize());
+
+ iterator end = this->end();
+ for (iterator iter = begin(); iter != end; ++iter) {
+ iter->key->ref();
+ Heap::writeBarrier(owner, iter->specificValue.get());
+ }
+
+ // Copy the m_deletedOffsets vector.
+ Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
+ if (otherDeletedOffsets)
+ m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
+}
+
+PropertyTable::PropertyTable(VM& vm, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
+ : JSCell(vm, vm.propertyTableStructure.get())
+ , m_indexSize(sizeForCapacity(initialCapacity))
+ , m_indexMask(m_indexSize - 1)
+ , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+ , m_keyCount(0)
+ , m_deletedCount(0)
+{
+ ASSERT(isPowerOf2(m_indexSize));
+ ASSERT(initialCapacity >= other.m_keyCount);
+
+ const_iterator end = other.end();
+ for (const_iterator iter = other.begin(); iter != end; ++iter) {
+ ASSERT(canInsert());
+ reinsert(*iter);
+ iter->key->ref();
+ Heap::writeBarrier(owner, iter->specificValue.get());
+ }
+
+ // Copy the m_deletedOffsets vector.
+ Vector<PropertyOffset>* otherDeletedOffsets = other.m_deletedOffsets.get();
+ if (otherDeletedOffsets)
+ m_deletedOffsets = adoptPtr(new Vector<PropertyOffset>(*otherDeletedOffsets));
+}
+
+void PropertyTable::destroy(JSCell* cell)
+{
+ static_cast<PropertyTable*>(cell)->PropertyTable::~PropertyTable();
+}
+
+PropertyTable::~PropertyTable()
+{
+ iterator end = this->end();
+ for (iterator iter = begin(); iter != end; ++iter)
+ iter->key->deref();
+
+ fastFree(m_index);
+}
+
+void PropertyTable::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ PropertyTable* thisObject = jsCast<PropertyTable*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+ ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+
+ JSCell::visitChildren(thisObject, visitor);
+
+ PropertyTable::iterator end = thisObject->end();
+ for (PropertyTable::iterator ptr = thisObject->begin(); ptr != end; ++ptr)
+ visitor.append(&ptr->specificValue);
+}
+
+}
diff --git a/Source/JavaScriptCore/runtime/Protect.h b/Source/JavaScriptCore/runtime/Protect.h
index 843c9e111..78dd319a3 100644
--- a/Source/JavaScriptCore/runtime/Protect.h
+++ b/Source/JavaScriptCore/runtime/Protect.h
@@ -23,7 +23,7 @@
#define Protect_h
#include "Heap.h"
-#include "JSValue.h"
+#include "JSCJSValue.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/PrototypeMap.cpp b/Source/JavaScriptCore/runtime/PrototypeMap.cpp
new file mode 100644
index 000000000..29de45b10
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/PrototypeMap.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PrototypeMap.h"
+
+#include "JSGlobalObject.h"
+#include "Operations.h"
+
+namespace JSC {
+
+void PrototypeMap::addPrototype(JSObject* object)
+{
+ m_prototypes.add(object, object);
+
+ // Note that this method makes the somewhat odd decision to not check if this
+ // object currently has indexed accessors. We could do that check here, and if
+ // indexed accessors were found, we could tell the global object to have a bad
+ // time. But we avoid this, to allow the following to be always fast:
+ //
+ // 1) Create an object.
+ // 2) Give it a setter or read-only property that happens to have a numeric name.
+ // 3) Allocate objects that use this object as a prototype.
+ //
+ // This avoids anyone having a bad time. Even if the instance objects end up
+ // having indexed storage, the creation of indexed storage leads to a prototype
+ // chain walk that detects the presence of indexed setters and then does the
+ // right thing. As a result, having a bad time only happens if you add an
+ // indexed setter (or getter, or read-only field) to an object that is already
+ // used as a prototype.
+}
+
+Structure* PrototypeMap::emptyObjectStructureForPrototype(JSObject* prototype, unsigned inlineCapacity)
+{
+ StructureMap::AddResult addResult = m_structures.add(std::make_pair(prototype, inlineCapacity), nullptr);
+ if (!addResult.isNewEntry) {
+ ASSERT(isPrototype(prototype));
+ return addResult.iterator->value.get();
+ }
+
+ addPrototype(prototype);
+ Structure* structure = JSFinalObject::createStructure(
+ prototype->globalObject()->vm(), prototype->globalObject(), prototype, inlineCapacity);
+ addResult.iterator->value = structure;
+ return structure;
+}
+
+void PrototypeMap::clearEmptyObjectStructureForPrototype(JSObject* object, unsigned inlineCapacity)
+{
+ m_structures.remove(std::make_pair(object, inlineCapacity));
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/PrototypeMap.h b/Source/JavaScriptCore/runtime/PrototypeMap.h
new file mode 100644
index 000000000..9752ca7ea
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/PrototypeMap.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PrototypeMap_h
+#define PrototypeMap_h
+
+#include "WeakGCMap.h"
+#include <wtf/TriState.h>
+
+namespace JSC {
+
+class JSObject;
+class Structure;
+
+// Tracks the canonical structure an object should be allocated with when inheriting from a given prototype.
+class PrototypeMap {
+public:
+ JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
+ void clearEmptyObjectStructureForPrototype(JSObject*, unsigned inlineCapacity);
+ void addPrototype(JSObject*);
+ TriState isPrototype(JSObject*) const; // Returns a conservative estimate.
+
+private:
+ WeakGCMap<JSObject*, JSObject> m_prototypes;
+ typedef WeakGCMap<std::pair<JSObject*, unsigned>, Structure> StructureMap;
+ StructureMap m_structures;
+};
+
+inline TriState PrototypeMap::isPrototype(JSObject* object) const
+{
+ if (!m_prototypes.contains(object))
+ return FalseTriState;
+
+ // We know that 'object' was used as a prototype at one time, so be
+ // conservative and say that it might still be so. (It would be expensive
+ // to find out for sure, and we don't know of any cases where being precise
+ // would improve performance.)
+ return MixedTriState;
+}
+
+} // namespace JSC
+
+#endif // PrototypeMap_h
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 3229f5207..d27bc1eb1 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -24,16 +24,16 @@
#include "RegExp.h"
#include "Lexer.h"
+#include "Operations.h"
#include "RegExpCache.h"
-#include "yarr/Yarr.h"
-#include "yarr/YarrJIT.h"
+#include "Yarr.h"
+#include "YarrJIT.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wtf/Assertions.h>
#include <wtf/OwnArrayPtr.h>
-
#define REGEXP_FUNC_TEST_DATA_GEN 0
namespace JSC {
@@ -217,8 +217,8 @@ void RegExpFunctionalTestCollector::outputEscapedString(const String& s, bool es
}
#endif
-RegExp::RegExp(JSGlobalData& globalData, const String& patternString, RegExpFlags flags)
- : JSCell(globalData, globalData.regExpStructure.get())
+RegExp::RegExp(VM& vm, const String& patternString, RegExpFlags flags)
+ : JSCell(vm, vm.regExpStructure.get())
, m_state(NotCompiled)
, m_patternString(patternString)
, m_flags(flags)
@@ -231,9 +231,9 @@ RegExp::RegExp(JSGlobalData& globalData, const String& patternString, RegExpFlag
{
}
-void RegExp::finishCreation(JSGlobalData& globalData)
+void RegExp::finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
if (m_constructionError)
m_state = ParseError;
@@ -250,23 +250,23 @@ void RegExp::destroy(JSCell* cell)
thisObject->RegExp::~RegExp();
}
-RegExp* RegExp::createWithoutCaching(JSGlobalData& globalData, const String& patternString, RegExpFlags flags)
+RegExp* RegExp::createWithoutCaching(VM& vm, const String& patternString, RegExpFlags flags)
{
- RegExp* regExp = new (NotNull, allocateCell<RegExp>(globalData.heap)) RegExp(globalData, patternString, flags);
- regExp->finishCreation(globalData);
+ RegExp* regExp = new (NotNull, allocateCell<RegExp>(vm.heap)) RegExp(vm, patternString, flags);
+ regExp->finishCreation(vm);
return regExp;
}
-RegExp* RegExp::create(JSGlobalData& globalData, const String& patternString, RegExpFlags flags)
+RegExp* RegExp::create(VM& vm, const String& patternString, RegExpFlags flags)
{
- return globalData.regExpCache()->lookupOrCreate(patternString, flags);
+ return vm.regExpCache()->lookupOrCreate(patternString, flags);
}
-void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
+void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
{
Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
if (m_constructionError) {
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
m_state = ParseError;
return;
}
@@ -274,13 +274,13 @@ void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
if (!hasCode()) {
ASSERT(m_state == NotCompiled);
- globalData->regExpCache()->addToStrongCache(this);
+ vm->regExpCache()->addToStrongCache(this);
m_state = ByteCode;
}
#if ENABLE(YARR_JIT)
- if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) {
- Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode);
+ if (!pattern.m_containsBackreferences && vm->canUseRegExpJIT()) {
+ Yarr::jitCompile(pattern, charSize, vm, m_regExpJITCode);
#if ENABLE(YARR_JIT_DEBUG)
if (!m_regExpJITCode.isFallBack())
m_state = JITCode;
@@ -297,10 +297,10 @@ void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
UNUSED_PARAM(charSize);
#endif
- m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+ m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
}
-void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
+void RegExp::compileIfNecessary(VM& vm, Yarr::YarrCharSize charSize)
{
if (hasCode()) {
#if ENABLE(YARR_JIT)
@@ -315,17 +315,17 @@ void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize cha
#endif
}
- compile(&globalData, charSize);
+ compile(&vm, charSize);
}
-int RegExp::match(JSGlobalData& globalData, const String& s, unsigned startOffset, Vector<int, 32>& ovector)
+int RegExp::match(VM& vm, const String& s, unsigned startOffset, Vector<int, 32>& ovector)
{
#if ENABLE(REGEXP_TRACING)
m_rtMatchCallCount++;
#endif
ASSERT(m_state != ParseError);
- compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+ compileIfNecessary(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
int offsetVectorSize = (m_numSubpatterns + 1) * 2;
ovector.resize(offsetVectorSize);
@@ -384,11 +384,11 @@ int RegExp::match(JSGlobalData& globalData, const String& s, unsigned startOffse
return result;
}
-void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charSize)
+void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
{
Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
if (m_constructionError) {
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
m_state = ParseError;
return;
}
@@ -396,13 +396,13 @@ void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charS
if (!hasCode()) {
ASSERT(m_state == NotCompiled);
- globalData->regExpCache()->addToStrongCache(this);
+ vm->regExpCache()->addToStrongCache(this);
m_state = ByteCode;
}
#if ENABLE(YARR_JIT)
- if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) {
- Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode, Yarr::MatchOnly);
+ if (!pattern.m_containsBackreferences && vm->canUseRegExpJIT()) {
+ Yarr::jitCompile(pattern, charSize, vm, m_regExpJITCode, Yarr::MatchOnly);
#if ENABLE(YARR_JIT_DEBUG)
if (!m_regExpJITCode.isFallBack())
m_state = JITCode;
@@ -419,10 +419,10 @@ void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charS
UNUSED_PARAM(charSize);
#endif
- m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+ m_regExpBytecode = Yarr::byteCompile(pattern, &vm->m_regExpAllocator);
}
-void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, Yarr::YarrCharSize charSize)
+void RegExp::compileIfNecessaryMatchOnly(VM& vm, Yarr::YarrCharSize charSize)
{
if (hasCode()) {
#if ENABLE(YARR_JIT)
@@ -437,17 +437,17 @@ void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, Yarr::YarrCha
#endif
}
- compileMatchOnly(&globalData, charSize);
+ compileMatchOnly(&vm, charSize);
}
-MatchResult RegExp::match(JSGlobalData& globalData, const String& s, unsigned startOffset)
+MatchResult RegExp::match(VM& vm, const String& s, unsigned startOffset)
{
#if ENABLE(REGEXP_TRACING)
m_rtMatchCallCount++;
#endif
ASSERT(m_state != ParseError);
- compileIfNecessaryMatchOnly(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
+ compileIfNecessaryMatchOnly(vm, s.is8Bit() ? Yarr::Char8 : Yarr::Char16);
#if ENABLE(YARR_JIT)
if (m_state == JITCode) {
diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h
index b2b65d90c..94ea316a8 100644
--- a/Source/JavaScriptCore/runtime/RegExp.h
+++ b/Source/JavaScriptCore/runtime/RegExp.h
@@ -38,7 +38,7 @@
namespace JSC {
struct RegExpRepresentation;
- class JSGlobalData;
+ class VM;
JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const String&);
@@ -46,7 +46,7 @@ namespace JSC {
public:
typedef JSCell Base;
- JS_EXPORT_PRIVATE static RegExp* create(JSGlobalData&, const String& pattern, RegExpFlags);
+ JS_EXPORT_PRIVATE static RegExp* create(VM&, const String& pattern, RegExpFlags);
static const bool needsDestruction = true;
static const bool hasImmortalStructure = true;
static void destroy(JSCell*);
@@ -60,8 +60,8 @@ namespace JSC {
bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
const char* errorMessage() const { return m_constructionError; }
- JS_EXPORT_PRIVATE int match(JSGlobalData&, const String&, unsigned startOffset, Vector<int, 32>& ovector);
- MatchResult match(JSGlobalData&, const String&, unsigned startOffset);
+ JS_EXPORT_PRIVATE int match(VM&, const String&, unsigned startOffset, Vector<int, 32>& ovector);
+ MatchResult match(VM&, const String&, unsigned startOffset);
unsigned numSubpatterns() const { return m_numSubpatterns; }
bool hasCode()
@@ -75,9 +75,9 @@ namespace JSC {
void printTraceData();
#endif
- 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(LeafType, 0), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(LeafType, 0), &s_info);
}
static const ClassInfo s_info;
@@ -85,13 +85,13 @@ namespace JSC {
RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
protected:
- void finishCreation(JSGlobalData&);
+ void finishCreation(VM&);
private:
friend class RegExpCache;
- RegExp(JSGlobalData&, const String&, RegExpFlags);
+ RegExp(VM&, const String&, RegExpFlags);
- static RegExp* createWithoutCaching(JSGlobalData&, const String&, RegExpFlags);
+ static RegExp* createWithoutCaching(VM&, const String&, RegExpFlags);
enum RegExpState {
ParseError,
@@ -100,11 +100,11 @@ namespace JSC {
NotCompiled
} m_state;
- void compile(JSGlobalData*, Yarr::YarrCharSize);
- void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize);
+ void compile(VM*, Yarr::YarrCharSize);
+ void compileIfNecessary(VM&, Yarr::YarrCharSize);
- void compileMatchOnly(JSGlobalData*, Yarr::YarrCharSize);
- void compileIfNecessaryMatchOnly(JSGlobalData&, Yarr::YarrCharSize);
+ void compileMatchOnly(VM*, Yarr::YarrCharSize);
+ void compileIfNecessaryMatchOnly(VM&, Yarr::YarrCharSize);
#if ENABLE(YARR_JIT_DEBUG)
void matchCompareWithInterpreter(const String&, int startOffset, int* offsetVector, int jitResult);
diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp
index 8acafba23..1ab3f5f51 100644
--- a/Source/JavaScriptCore/runtime/RegExpCache.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2010 University of Szeged
* Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,8 +27,9 @@
*/
#include "config.h"
-
#include "RegExpCache.h"
+
+#include "Operations.h"
#include "RegExpObject.h"
#include "StrongInlines.h"
@@ -39,18 +41,18 @@ RegExp* RegExpCache::lookupOrCreate(const String& patternString, RegExpFlags fla
if (RegExp* regExp = m_weakCache.get(key))
return regExp;
- RegExp* regExp = RegExp::createWithoutCaching(*m_globalData, patternString, flags);
+ RegExp* regExp = RegExp::createWithoutCaching(*m_vm, patternString, flags);
#if ENABLE(REGEXP_TRACING)
- m_globalData->addRegExpToTrace(regExp);
+ m_vm->addRegExpToTrace(regExp);
#endif
weakAdd(m_weakCache, key, PassWeak<RegExp>(regExp, this));
return regExp;
}
-RegExpCache::RegExpCache(JSGlobalData* globalData)
+RegExpCache::RegExpCache(VM* vm)
: m_nextEntryInStrongCache(0)
- , m_globalData(globalData)
+ , m_vm(vm)
{
}
@@ -66,7 +68,7 @@ void RegExpCache::addToStrongCache(RegExp* regExp)
String pattern = regExp->pattern();
if (pattern.length() > maxStrongCacheablePatternLength)
return;
- m_strongCache[m_nextEntryInStrongCache].set(*m_globalData, regExp);
+ m_strongCache[m_nextEntryInStrongCache].set(*m_vm, regExp);
m_nextEntryInStrongCache++;
if (m_nextEntryInStrongCache == maxStrongCacheableEntries)
m_nextEntryInStrongCache = 0;
diff --git a/Source/JavaScriptCore/runtime/RegExpCache.h b/Source/JavaScriptCore/runtime/RegExpCache.h
index c6a4a0aa2..4f854d1ba 100644
--- a/Source/JavaScriptCore/runtime/RegExpCache.h
+++ b/Source/JavaScriptCore/runtime/RegExpCache.h
@@ -29,6 +29,7 @@
#include "RegExpKey.h"
#include "Strong.h"
#include "Weak.h"
+#include "WeakInlines.h"
#include <wtf/FixedArray.h>
#include <wtf/HashMap.h>
@@ -42,7 +43,7 @@ friend class RegExp;
typedef HashMap<RegExpKey, Weak<RegExp> > RegExpCacheMap;
public:
- RegExpCache(JSGlobalData* globalData);
+ RegExpCache(VM* vm);
void invalidateCode();
private:
@@ -58,7 +59,7 @@ private:
RegExpCacheMap m_weakCache; // Holds all regular expressions currently live.
int m_nextEntryInStrongCache;
WTF::FixedArray<Strong<RegExp>, maxStrongCacheableEntries> m_strongCache; // Holds a select few regular expressions that have compiled and executed
- JSGlobalData* m_globalData;
+ VM* m_vm;
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
index 47cff15f1..c54b4783d 100644
--- a/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "RegExpCachedResult.h"
+#include "Operations.h"
#include "RegExpMatchesArray.h"
namespace JSC {
@@ -41,8 +42,8 @@ void RegExpCachedResult::visitChildren(SlotVisitor& visitor)
RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)
{
if (m_result) {
- m_reifiedInput.set(exec->globalData(), owner, m_lastInput.get());
- m_reifiedResult.set(exec->globalData(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
+ m_reifiedInput.set(exec->vm(), owner, m_lastInput.get());
+ m_reifiedResult.set(exec->vm(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
m_result = MatchResult::failed();
}
return m_reifiedResult.get();
@@ -53,7 +54,7 @@ void RegExpCachedResult::setInput(ExecState* exec, JSObject* owner, JSString* in
// Make sure we're reified, otherwise m_reifiedInput will be ignored.
lastResult(exec, owner);
ASSERT(!m_result);
- m_reifiedInput.set(exec->globalData(), owner, input);
+ m_reifiedInput.set(exec->vm(), owner, input);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.h b/Source/JavaScriptCore/runtime/RegExpCachedResult.h
index 812ff4336..d2763bc77 100644
--- a/Source/JavaScriptCore/runtime/RegExpCachedResult.h
+++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.h
@@ -44,17 +44,17 @@ namespace JSC {
// m_reifiedResult and m_reifiedInput hold the cached results.
class RegExpCachedResult {
public:
- RegExpCachedResult(JSGlobalData& globalData, JSObject* owner, RegExp* emptyRegExp)
+ RegExpCachedResult(VM& vm, JSObject* owner, RegExp* emptyRegExp)
: m_result(0, 0)
{
- m_lastInput.set(globalData, owner, jsEmptyString(&globalData));
- m_lastRegExp.set(globalData, owner, emptyRegExp);
+ m_lastInput.set(vm, owner, jsEmptyString(&vm));
+ m_lastRegExp.set(vm, owner, emptyRegExp);
}
- ALWAYS_INLINE void record(JSGlobalData& globalData, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result)
+ ALWAYS_INLINE void record(VM& vm, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result)
{
- m_lastRegExp.set(globalData, owner, regExp);
- m_lastInput.set(globalData, owner, input);
+ m_lastRegExp.set(vm, owner, regExp);
+ m_lastInput.set(vm, owner, input);
m_result = result;
}
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index cc6ceb1d1..8b12a5a05 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -23,6 +23,7 @@
#include "RegExpConstructor.h"
#include "Error.h"
+#include "Operations.h"
#include "RegExpMatchesArray.h"
#include "RegExpPrototype.h"
@@ -83,21 +84,21 @@ const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_i
RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
: InternalFunction(globalObject, structure)
- , m_cachedResult(globalObject->globalData(), this, regExpPrototype->regExp())
+ , m_cachedResult(globalObject->vm(), this, regExpPrototype->regExp())
, m_multiline(false)
{
}
void RegExpConstructor::finishCreation(ExecState* exec, RegExpPrototype* regExpPrototype)
{
- Base::finishCreation(exec->globalData(), Identifier(exec, "RegExp").string());
+ Base::finishCreation(exec->vm(), Identifier(exec, "RegExp").string());
ASSERT(inherits(&s_info));
// ECMA 15.10.5.1 RegExp.prototype
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
// no. of arguments for constructor
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
}
void RegExpConstructor::destroy(JSCell* cell)
@@ -282,7 +283,7 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A
return throwError(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
}
- RegExp* regExp = RegExp::create(exec->globalData(), pattern, flags);
+ RegExp* regExp = RegExp::create(exec->vm(), pattern, flags);
if (!regExp->isValid())
return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
return RegExpObject::create(exec, exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 2cb1c1204..0942070d5 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -43,9 +43,9 @@ namespace JSC {
return constructor;
}
- 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);
}
static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
@@ -55,8 +55,8 @@ namespace JSC {
static const ClassInfo s_info;
- MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const String&, int startOffset, int** ovector);
- MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const String&, int startOffset);
+ MatchResult performMatch(VM&, RegExp*, JSString*, const String&, int startOffset, int** ovector);
+ MatchResult performMatch(VM&, RegExp*, JSString*, const String&, int startOffset);
void setMultiline(bool multiline) { m_multiline = multiline; }
bool multiline() const { return m_multiline; }
@@ -101,9 +101,9 @@ namespace JSC {
expression matching through the performMatch function. We use cached results to calculate,
e.g., RegExp.lastMatch and RegExp.leftParen.
*/
- ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector)
+ ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(VM& vm, RegExp* regExp, JSString* string, const String& input, int startOffset, int** ovector)
{
- int position = regExp->match(globalData, input, startOffset, m_ovector);
+ int position = regExp->match(vm, input, startOffset, m_ovector);
if (ovector)
*ovector = m_ovector.data();
@@ -116,15 +116,15 @@ namespace JSC {
ASSERT(m_ovector[1] >= position);
size_t end = m_ovector[1];
- m_cachedResult.record(globalData, this, regExp, string, MatchResult(position, end));
+ m_cachedResult.record(vm, this, regExp, string, MatchResult(position, end));
return MatchResult(position, end);
}
- ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const String& input, int startOffset)
+ ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(VM& vm, RegExp* regExp, JSString* string, const String& input, int startOffset)
{
- MatchResult result = regExp->match(globalData, input, startOffset);
+ MatchResult result = regExp->match(vm, input, startOffset);
if (result)
- m_cachedResult.record(globalData, this, regExp, string, result);
+ m_cachedResult.record(vm, this, regExp, string, result);
return result;
}
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
index 19f3b81ad..062650a86 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp
@@ -27,33 +27,34 @@
#include "RegExpMatchesArray.h"
#include "ButterflyInlines.h"
+#include "Operations.h"
namespace JSC {
const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)};
-RegExpMatchesArray::RegExpMatchesArray(JSGlobalData& globalData, Butterfly* butterfly, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result)
- : JSArray(globalData, globalObject->regExpMatchesArrayStructure(), butterfly)
+RegExpMatchesArray::RegExpMatchesArray(VM& vm, Butterfly* butterfly, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result)
+ : JSArray(vm, globalObject->regExpMatchesArrayStructure(), butterfly)
, m_result(result)
, m_state(ReifiedNone)
{
- m_input.set(globalData, this, input);
- m_regExp.set(globalData, this, regExp);
+ m_input.set(vm, this, input);
+ m_regExp.set(vm, this, regExp);
}
RegExpMatchesArray* RegExpMatchesArray::create(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result)
{
ASSERT(result);
- JSGlobalData& globalData = exec->globalData();
- Butterfly* butterfly = createArrayButterfly(globalData, regExp->numSubpatterns() + 1);
- RegExpMatchesArray* array = new (NotNull, allocateCell<RegExpMatchesArray>(globalData.heap)) RegExpMatchesArray(globalData, butterfly, exec->lexicalGlobalObject(), input, regExp, result);
- array->finishCreation(globalData);
+ VM& vm = exec->vm();
+ Butterfly* butterfly = createArrayButterfly(vm, regExp->numSubpatterns() + 1);
+ RegExpMatchesArray* array = new (NotNull, allocateCell<RegExpMatchesArray>(vm.heap)) RegExpMatchesArray(vm, butterfly, exec->lexicalGlobalObject(), input, regExp, result);
+ array->finishCreation(vm);
return array;
}
-void RegExpMatchesArray::finishCreation(JSGlobalData& globalData)
+void RegExpMatchesArray::finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
}
void RegExpMatchesArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -77,7 +78,7 @@ void RegExpMatchesArray::reifyAllProperties(ExecState* exec)
if (unsigned numSubpatterns = m_regExp->numSubpatterns()) {
Vector<int, 32> subpatternResults;
- int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, subpatternResults);
+ int position = m_regExp->match(exec->vm(), m_input->value(exec), m_result.start, subpatternResults);
ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start);
ASSERT(m_result.start == static_cast<size_t>(subpatternResults[0]));
ASSERT(m_result.end == static_cast<size_t>(subpatternResults[1]));
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
index a5b860b9d..c7c942052 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -28,7 +28,7 @@ namespace JSC {
class RegExpMatchesArray : public JSArray {
private:
- RegExpMatchesArray(JSGlobalData&, Butterfly*, JSGlobalObject*, JSString*, RegExp*, MatchResult);
+ RegExpMatchesArray(VM&, Butterfly*, JSGlobalObject*, JSString*, RegExp*, MatchResult);
enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll };
@@ -42,15 +42,15 @@ namespace JSC {
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, ArrayWithArrayStorage);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayWithSlowPutArrayStorage);
}
static void visitChildren(JSCell*, SlotVisitor&);
protected:
- void finishCreation(JSGlobalData&);
+ void finishCreation(VM&);
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 00dd1ed74..8b2d03c02 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -30,6 +30,7 @@
#include "JSString.h"
#include "Lexer.h"
#include "Lookup.h"
+#include "Operations.h"
#include "RegExpConstructor.h"
#include "RegExpMatchesArray.h"
#include "RegExpPrototype.h"
@@ -63,8 +64,8 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &Base::s_info, 0, ExecState::
*/
RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
- : JSNonFinalObject(globalObject->globalData(), structure)
- , m_regExp(globalObject->globalData(), this, regExp)
+ : JSNonFinalObject(globalObject->vm(), structure)
+ , m_regExp(globalObject->vm(), this, regExp)
, m_lastIndexIsWritable(true)
{
m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
@@ -72,7 +73,7 @@ RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, R
void RegExpObject::finishCreation(JSGlobalObject* globalObject)
{
- Base::finishCreation(globalObject->globalData());
+ Base::finishCreation(globalObject->vm());
ASSERT(inherits(&s_info));
}
@@ -314,9 +315,9 @@ MatchResult RegExpObject::match(ExecState* exec, JSString* string)
RegExp* regExp = this->regExp();
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
String input = string->value(exec);
- JSGlobalData& globalData = exec->globalData();
+ VM& vm = exec->vm();
if (!regExp->global())
- return regExpConstructor->performMatch(globalData, regExp, string, input, 0);
+ return regExpConstructor->performMatch(vm, regExp, string, input, 0);
JSValue jsLastIndex = getLastIndex();
unsigned lastIndex;
@@ -335,7 +336,7 @@ MatchResult RegExpObject::match(ExecState* exec, JSString* string)
lastIndex = static_cast<unsigned>(doubleLastIndex);
}
- MatchResult result = regExpConstructor->performMatch(globalData, regExp, string, input, lastIndex);
+ MatchResult result = regExpConstructor->performMatch(vm, regExp, string, input, lastIndex);
setLastIndex(exec, result.end);
return result;
}
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index f43d6bc79..7ed3dea91 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -37,14 +37,14 @@ namespace JSC {
return object;
}
- static RegExpObject* create(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+ static RegExpObject* create(VM& vm, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
{
- RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(globalData.heap)) RegExpObject(globalObject, structure, regExp);
+ RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(vm.heap)) RegExpObject(globalObject, structure, regExp);
object->finishCreation(globalObject);
return object;
}
- void setRegExp(JSGlobalData& globalData, RegExp* r) { m_regExp.set(globalData, this, r); }
+ void setRegExp(VM& vm, RegExp* r) { m_regExp.set(vm, this, r); }
RegExp* regExp() const { return m_regExp.get(); }
void setLastIndex(ExecState* exec, size_t lastIndex)
@@ -58,7 +58,7 @@ namespace JSC {
void setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow)
{
if (LIKELY(m_lastIndexIsWritable))
- m_lastIndex.set(exec->globalData(), this, lastIndex);
+ m_lastIndex.set(exec->vm(), this, lastIndex);
else if (shouldThrow)
throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
}
@@ -76,9 +76,9 @@ namespace JSC {
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);
}
protected:
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index e4bf2cf9a..daebcbc1d 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -24,12 +24,13 @@
#include "ArrayPrototype.h"
#include "Error.h"
#include "JSArray.h"
+#include "JSCJSValue.h"
#include "JSFunction.h"
#include "JSObject.h"
#include "JSString.h"
#include "JSStringBuilder.h"
-#include "JSValue.h"
#include "ObjectPrototype.h"
+#include "Operations.h"
#include "RegExpObject.h"
#include "RegExp.h"
#include "RegExpCache.h"
@@ -119,13 +120,13 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
if (flags == InvalidFlags)
return throwVMError(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
}
- regExp = RegExp::create(exec->globalData(), pattern, flags);
+ regExp = RegExp::create(exec->vm(), pattern, flags);
}
if (!regExp->isValid())
return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
- asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
+ asRegExpObject(thisValue)->setRegExp(exec->vm(), regExp);
asRegExpObject(thisValue)->setLastIndex(exec, 0);
return JSValue::encode(jsUndefined());
}
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.h b/Source/JavaScriptCore/runtime/RegExpPrototype.h
index 78c6ae1d4..703306be7 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.h
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.h
@@ -39,9 +39,9 @@ namespace JSC {
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/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp
index 56a359279..5f35cca5e 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp
@@ -29,6 +29,7 @@
#include "HeapRootVisitor.h"
#include "JSGlobalObject.h"
#include "JSString.h"
+#include "Operations.h"
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/text/StringImpl.h>
@@ -80,6 +81,22 @@ SmallStrings::SmallStrings()
m_singleCharacterStrings[i] = 0;
}
+void SmallStrings::initializeCommonStrings(VM& vm)
+{
+ createEmptyString(&vm);
+#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) initialize(&vm, m_##name, #name);
+ JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE
+}
+
+void SmallStrings::visitStrongReferences(SlotVisitor& visitor)
+{
+ visitor.appendUnbarrieredPointer(&m_emptyString);
+#define JSC_COMMON_STRINGS_ATTRIBUTE_VISIT(name) visitor.appendUnbarrieredPointer(&m_##name);
+ JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_VISIT)
+#undef JSC_COMMON_STRINGS_ATTRIBUTE_VISIT
+}
+
SmallStrings::~SmallStrings()
{
}
@@ -89,23 +106,20 @@ void SmallStrings::finalizeSmallStrings()
finalize(m_emptyString);
for (unsigned i = 0; i < singleCharacterStringCount; ++i)
finalize(m_singleCharacterStrings[i]);
-#define JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE(name) finalize(m_##name);
- JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE)
-#undef JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE
}
-void SmallStrings::createEmptyString(JSGlobalData* globalData)
+void SmallStrings::createEmptyString(VM* vm)
{
ASSERT(!m_emptyString);
- m_emptyString = JSString::createHasOtherOwner(*globalData, StringImpl::empty());
+ m_emptyString = JSString::createHasOtherOwner(*vm, StringImpl::empty());
}
-void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
+void SmallStrings::createSingleCharacterString(VM* vm, unsigned char character)
{
if (!m_storage)
m_storage = adoptPtr(new SmallStringsStorage);
ASSERT(!m_singleCharacterStrings[character]);
- m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*globalData, PassRefPtr<StringImpl>(m_storage->rep(character)));
+ m_singleCharacterStrings[character] = JSString::createHasOtherOwner(*vm, PassRefPtr<StringImpl>(m_storage->rep(character)));
}
StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
@@ -115,9 +129,9 @@ StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
return m_storage->rep(character);
}
-void SmallStrings::initialize(JSGlobalData* globalData, JSString*& string, const char* value) const
+void SmallStrings::initialize(VM* vm, JSString*& string, const char* value) const
{
- string = JSString::create(*globalData, StringImpl::create(value));
+ string = JSString::create(*vm, StringImpl::create(value));
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h
index 5bc9d2252..f00043021 100644
--- a/Source/JavaScriptCore/runtime/SmallStrings.h
+++ b/Source/JavaScriptCore/runtime/SmallStrings.h
@@ -26,6 +26,8 @@
#ifndef SmallStrings_h
#define SmallStrings_h
+#include "WriteBarrier.h"
+
#include <wtf/FixedArray.h>
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
@@ -48,7 +50,7 @@ class StringImpl;
namespace JSC {
class HeapRootVisitor;
- class JSGlobalData;
+ class VM;
class JSString;
class SmallStringsStorage;
class SlotVisitor;
@@ -61,17 +63,15 @@ namespace JSC {
SmallStrings();
~SmallStrings();
- JSString* emptyString(JSGlobalData* globalData)
+ JSString* emptyString()
{
- if (!m_emptyString)
- createEmptyString(globalData);
return m_emptyString;
}
- JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
+ JSString* singleCharacterString(VM* vm, unsigned char character)
{
if (!m_singleCharacterStrings[character])
- createSingleCharacterString(globalData, character);
+ createSingleCharacterString(vm, character);
return m_singleCharacterStrings[character];
}
@@ -81,11 +81,12 @@ namespace JSC {
JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
+ void initializeCommonStrings(VM&);
+ void visitStrongReferences(SlotVisitor&);
+
#define JSC_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \
- JSString* name##String(JSGlobalData* globalData) const \
+ JSString* name##String() const \
{ \
- if (!m_##name) \
- initialize(globalData, m_##name, #name); \
return m_##name; \
}
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION)
@@ -94,13 +95,13 @@ namespace JSC {
private:
static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
- JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*);
- JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char);
+ JS_EXPORT_PRIVATE void createEmptyString(VM*);
+ JS_EXPORT_PRIVATE void createSingleCharacterString(VM*, unsigned char);
- void initialize(JSGlobalData* globalData, JSString*& string, const char* value) const;
+ void initialize(VM* vm, JSString*& string, const char* value) const;
JSString* m_emptyString;
-#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) mutable JSString* m_##name;
+#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) JSString* m_##name;
JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION)
#undef JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION
JSString* m_singleCharacterStrings[singleCharacterStringCount];
diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp
index 7f21e2c9f..1997c5b70 100644
--- a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp
+++ b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp
@@ -29,6 +29,7 @@
#include "ClassInfo.h"
#include "GetterSetter.h"
#include "JSObject.h"
+#include "Operations.h"
#include "PropertySlot.h"
#include "Reject.h"
#include "SlotVisitor.h"
@@ -38,8 +39,8 @@ namespace JSC {
const ClassInfo SparseArrayValueMap::s_info = { "SparseArrayValueMap", 0, 0, 0, CREATE_METHOD_TABLE(SparseArrayValueMap) };
-SparseArrayValueMap::SparseArrayValueMap(JSGlobalData& globalData)
- : Base(globalData, globalData.sparseArrayValueMapStructure.get())
+SparseArrayValueMap::SparseArrayValueMap(VM& vm)
+ : Base(vm, vm.sparseArrayValueMapStructure.get())
, m_flags(Normal)
, m_reportedCapacity(0)
{
@@ -49,15 +50,15 @@ SparseArrayValueMap::~SparseArrayValueMap()
{
}
-void SparseArrayValueMap::finishCreation(JSGlobalData& globalData)
+void SparseArrayValueMap::finishCreation(VM& vm)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
}
-SparseArrayValueMap* SparseArrayValueMap::create(JSGlobalData& globalData)
+SparseArrayValueMap* SparseArrayValueMap::create(VM& vm)
{
- SparseArrayValueMap* result = new (NotNull, allocateCell<SparseArrayValueMap>(globalData.heap)) SparseArrayValueMap(globalData);
- result->finishCreation(globalData);
+ SparseArrayValueMap* result = new (NotNull, allocateCell<SparseArrayValueMap>(vm.heap)) SparseArrayValueMap(vm);
+ result->finishCreation(vm);
return result;
}
@@ -66,9 +67,9 @@ void SparseArrayValueMap::destroy(JSCell* cell)
static_cast<SparseArrayValueMap*>(cell)->SparseArrayValueMap::~SparseArrayValueMap();
}
-Structure* SparseArrayValueMap::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+Structure* SparseArrayValueMap::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info);
}
SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSObject* array, unsigned i)
@@ -117,7 +118,7 @@ bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i
}
entry.attributes = attributes;
- entry.set(exec->globalData(), this, value);
+ entry.set(exec->vm(), this, value);
return true;
}
@@ -171,7 +172,7 @@ void SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueM
return;
}
- set(exec->globalData(), map, value);
+ set(exec->vm(), map, value);
return;
}
diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMap.h b/Source/JavaScriptCore/runtime/SparseArrayValueMap.h
index 366a7b8ba..31b279fa7 100644
--- a/Source/JavaScriptCore/runtime/SparseArrayValueMap.h
+++ b/Source/JavaScriptCore/runtime/SparseArrayValueMap.h
@@ -65,10 +65,10 @@ private:
LengthIsReadOnly = 2,
};
- SparseArrayValueMap(JSGlobalData&);
+ SparseArrayValueMap(VM&);
~SparseArrayValueMap();
- void finishCreation(JSGlobalData&);
+ void finishCreation(VM&);
static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
@@ -79,13 +79,13 @@ public:
typedef Map::const_iterator const_iterator;
typedef Map::AddResult AddResult;
- static SparseArrayValueMap* create(JSGlobalData&);
+ static SparseArrayValueMap* create(VM&);
static const bool needsDestruction = true;
static const bool hasImmortalStructure = true;
static void destroy(JSCell*);
- static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype);
+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
static void visitChildren(JSCell*, SlotVisitor&);
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
index b1f28c8aa..eaef9397b 100644
--- a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
+++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
@@ -27,6 +27,7 @@
#include "StrictEvalActivation.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
namespace JSC {
@@ -36,7 +37,7 @@ const ClassInfo StrictEvalActivation::s_info = { "Object", &Base::s_info, 0, 0,
StrictEvalActivation::StrictEvalActivation(ExecState* exec)
: Base(
- exec->globalData(),
+ exec->vm(),
exec->lexicalGlobalObject()->strictEvalActivationStructure(),
exec->scope()
)
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.h b/Source/JavaScriptCore/runtime/StrictEvalActivation.h
index 9f64feb15..df490d5e7 100644
--- a/Source/JavaScriptCore/runtime/StrictEvalActivation.h
+++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.h
@@ -37,16 +37,16 @@ public:
static StrictEvalActivation* create(ExecState* exec)
{
StrictEvalActivation* activation = new (NotNull, allocateCell<StrictEvalActivation>(*exec->heap())) StrictEvalActivation(exec);
- activation->finishCreation(exec->globalData());
+ activation->finishCreation(exec->vm());
return activation;
}
static bool deleteProperty(JSCell*, ExecState*, PropertyName);
static JSObject* toThisObject(JSCell*, ExecState*);
- 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);
}
static const ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp
index 7f36a84be..df507ce07 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp
@@ -25,6 +25,7 @@
#include "JITCode.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
#include "StringPrototype.h"
namespace JSC {
@@ -54,9 +55,9 @@ StringConstructor::StringConstructor(JSGlobalObject* globalObject, Structure* st
void StringConstructor::finishCreation(ExecState* exec, StringPrototype* stringPrototype)
{
- Base::finishCreation(exec->globalData(), stringPrototype->classInfo()->className);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
+ Base::finishCreation(exec->vm(), stringPrototype->classInfo()->className);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
}
bool StringConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
@@ -88,6 +89,11 @@ static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec)
return JSValue::encode(stringFromCharCodeSlowCase(exec));
}
+JSCell* JSC_HOST_CALL stringFromCharCode(ExecState* exec, int32_t arg)
+{
+ return jsSingleCharacterString(exec, arg);
+}
+
static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* exec)
{
JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.h b/Source/JavaScriptCore/runtime/StringConstructor.h
index 11f70d499..40e574c02 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.h
+++ b/Source/JavaScriptCore/runtime/StringConstructor.h
@@ -40,9 +40,9 @@ namespace JSC {
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:
@@ -57,6 +57,8 @@ namespace JSC {
static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
};
+
+ JSCell* JSC_HOST_CALL stringFromCharCode(ExecState*, int32_t);
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp
index ab7d6cb23..bdbe27fe6 100644
--- a/Source/JavaScriptCore/runtime/StringObject.cpp
+++ b/Source/JavaScriptCore/runtime/StringObject.cpp
@@ -23,6 +23,7 @@
#include "Error.h"
#include "JSGlobalObject.h"
+#include "Operations.h"
#include "PropertyNameArray.h"
namespace JSC {
@@ -31,16 +32,16 @@ ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringObject);
const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringObject) };
-StringObject::StringObject(JSGlobalData& globalData, Structure* structure)
- : JSWrapperObject(globalData, structure)
+StringObject::StringObject(VM& vm, Structure* structure)
+ : JSWrapperObject(vm, structure)
{
}
-void StringObject::finishCreation(JSGlobalData& globalData, JSString* string)
+void StringObject::finishCreation(VM& vm, JSString* string)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
ASSERT(inherits(&s_info));
- setInternalValue(globalData, string);
+ setInternalValue(vm, string);
}
bool StringObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
@@ -165,7 +166,7 @@ void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, Proper
StringObject* constructString(ExecState* exec, JSGlobalObject* globalObject, JSValue string)
{
StringObject* object = StringObject::create(exec, globalObject->stringObjectStructure());
- object->setInternalValue(exec->globalData(), string);
+ object->setInternalValue(exec->vm(), string);
return object;
}
diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h
index 4369eace1..6a92541c1 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -33,14 +33,14 @@ namespace JSC {
static StringObject* create(ExecState* exec, Structure* structure)
{
JSString* string = jsEmptyString(exec);
- StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), structure);
- object->finishCreation(exec->globalData(), string);
+ StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->vm(), structure);
+ object->finishCreation(exec->vm(), string);
return object;
}
static StringObject* create(ExecState* exec, Structure* structure, JSString* string)
{
- StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), structure);
- object->finishCreation(exec->globalData(), string);
+ StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->vm(), structure);
+ object->finishCreation(exec->vm(), string);
return object;
}
static StringObject* create(ExecState*, JSGlobalObject*, JSString*);
@@ -61,15 +61,15 @@ namespace JSC {
JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
- 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:
- JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSString*);
+ JS_EXPORT_PRIVATE void finishCreation(VM&, JSString*);
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
- JS_EXPORT_PRIVATE StringObject(JSGlobalData&, Structure*);
+ JS_EXPORT_PRIVATE StringObject(VM&, Structure*);
};
StringObject* asStringObject(JSValue);
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 25f989776..c422fd17b 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
* Copyright (C) 2009 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
@@ -82,80 +82,67 @@ static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*);
static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*);
static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
-}
-
-#include "StringPrototype.lut.h"
-
-namespace JSC {
-
-const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable, CREATE_METHOD_TABLE(StringPrototype) };
-
-/* Source for StringPrototype.lut.h
-@begin stringTable 26
- toString stringProtoFuncToString DontEnum|Function 0
- valueOf stringProtoFuncToString DontEnum|Function 0
- charAt stringProtoFuncCharAt DontEnum|Function 1
- charCodeAt stringProtoFuncCharCodeAt DontEnum|Function 1
- concat stringProtoFuncConcat DontEnum|Function 1
- indexOf stringProtoFuncIndexOf DontEnum|Function 1
- lastIndexOf stringProtoFuncLastIndexOf DontEnum|Function 1
- match stringProtoFuncMatch DontEnum|Function 1
- replace stringProtoFuncReplace DontEnum|Function 2
- search stringProtoFuncSearch DontEnum|Function 1
- slice stringProtoFuncSlice DontEnum|Function 2
- split stringProtoFuncSplit DontEnum|Function 2
- substr stringProtoFuncSubstr DontEnum|Function 2
- substring stringProtoFuncSubstring DontEnum|Function 2
- toLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
- toUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
- localeCompare stringProtoFuncLocaleCompare DontEnum|Function 1
-
- # toLocaleLowerCase and toLocaleUpperCase are currently identical to toLowerCase and toUpperCase
- toLocaleLowerCase stringProtoFuncToLowerCase DontEnum|Function 0
- toLocaleUpperCase stringProtoFuncToUpperCase DontEnum|Function 0
-
- big stringProtoFuncBig DontEnum|Function 0
- small stringProtoFuncSmall DontEnum|Function 0
- blink stringProtoFuncBlink DontEnum|Function 0
- bold stringProtoFuncBold DontEnum|Function 0
- fixed stringProtoFuncFixed DontEnum|Function 0
- italics stringProtoFuncItalics DontEnum|Function 0
- strike stringProtoFuncStrike DontEnum|Function 0
- sub stringProtoFuncSub DontEnum|Function 0
- sup stringProtoFuncSup DontEnum|Function 0
- fontcolor stringProtoFuncFontcolor DontEnum|Function 1
- fontsize stringProtoFuncFontsize DontEnum|Function 1
- anchor stringProtoFuncAnchor DontEnum|Function 1
- link stringProtoFuncLink DontEnum|Function 1
- trim stringProtoFuncTrim DontEnum|Function 0
- trimLeft stringProtoFuncTrimLeft DontEnum|Function 0
- trimRight stringProtoFuncTrimRight DontEnum|Function 0
-@end
-*/
+const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringPrototype) };
// ECMA 15.5.4
StringPrototype::StringPrototype(ExecState* exec, Structure* structure)
- : StringObject(exec->globalData(), structure)
+ : StringObject(exec->vm(), structure)
{
}
-void StringPrototype::finishCreation(ExecState* exec, JSGlobalObject*, JSString* nameAndMessage)
+void StringPrototype::finishCreation(ExecState* exec, JSGlobalObject* globalObject, JSString* nameAndMessage)
{
- Base::finishCreation(exec->globalData(), nameAndMessage);
+ VM& vm = exec->vm();
+
+ Base::finishCreation(vm, nameAndMessage);
ASSERT(inherits(&s_info));
- // The constructor will be added later, after StringConstructor has been built
- putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
-}
+ JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->toString, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
+ JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->valueOf, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
+ JSC_NATIVE_INTRINSIC_FUNCTION("charAt", stringProtoFuncCharAt, DontEnum, 1, CharAtIntrinsic);
+ JSC_NATIVE_INTRINSIC_FUNCTION("charCodeAt", stringProtoFuncCharCodeAt, DontEnum, 1, CharCodeAtIntrinsic);
+ JSC_NATIVE_FUNCTION("concat", stringProtoFuncConcat, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("indexOf", stringProtoFuncIndexOf, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("lastIndexOf", stringProtoFuncLastIndexOf, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("match", stringProtoFuncMatch, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("replace", stringProtoFuncReplace, DontEnum, 2);
+ JSC_NATIVE_FUNCTION("search", stringProtoFuncSearch, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("slice", stringProtoFuncSlice, DontEnum, 2);
+ JSC_NATIVE_FUNCTION("split", stringProtoFuncSplit, DontEnum, 2);
+ JSC_NATIVE_FUNCTION("substr", stringProtoFuncSubstr, DontEnum, 2);
+ JSC_NATIVE_FUNCTION("substring", stringProtoFuncSubstring, DontEnum, 2);
+ JSC_NATIVE_FUNCTION("toLowerCase", stringProtoFuncToLowerCase, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("toUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("localeCompare", stringProtoFuncLocaleCompare, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("toLocaleLowerCase", stringProtoFuncToLowerCase, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("toLocaleUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("big", stringProtoFuncBig, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("small", stringProtoFuncSmall, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("blink", stringProtoFuncBlink, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("bold", stringProtoFuncBold, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("fixed", stringProtoFuncFixed, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("italics", stringProtoFuncItalics, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("strike", stringProtoFuncStrike, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("sub", stringProtoFuncSub, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("sup", stringProtoFuncSup, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("fontcolor", stringProtoFuncFontcolor, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("fontsize", stringProtoFuncFontsize, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("anchor", stringProtoFuncAnchor, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("link", stringProtoFuncLink, DontEnum, 1);
+ JSC_NATIVE_FUNCTION("trim", stringProtoFuncTrim, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("trimLeft", stringProtoFuncTrimLeft, DontEnum, 0);
+ JSC_NATIVE_FUNCTION("trimRight", stringProtoFuncTrimRight, DontEnum, 0);
-bool StringPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot)
-{
- return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(cell), propertyName, slot);
+ // The constructor will be added later, after StringConstructor has been built
+ putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
}
-bool StringPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
+StringPrototype* StringPrototype::create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
{
- return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), jsCast<StringPrototype*>(object), propertyName, descriptor);
+ JSString* empty = jsEmptyString(exec);
+ StringPrototype* prototype = new (NotNull, allocateCell<StringPrototype>(*exec->heap())) StringPrototype(exec, structure);
+ prototype->finishCreation(exec, globalObject, empty);
+ return prototype;
}
// ------------------------------ Functions --------------------------
@@ -418,12 +405,12 @@ static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSSt
unsigned startPosition = 0;
Vector<StringRange, 16> sourceRanges;
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
unsigned sourceLen = source.length();
while (true) {
- MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition);
+ MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, source, startPosition);
if (!result)
break;
@@ -493,11 +480,11 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
CachedCall cachedCall(exec, func, argCount);
if (exec->hadException())
return JSValue::encode(jsNull());
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
if (source.is8Bit()) {
while (true) {
int* ovector;
- MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+ MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, source, startPosition, &ovector);
if (!result)
break;
@@ -511,7 +498,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
if (matchStart < 0)
cachedCall.setArgument(i, jsUndefined());
else
- cachedCall.setArgument(i, jsSubstring8(globalData, source, matchStart, matchLen));
+ cachedCall.setArgument(i, jsSubstring8(vm, source, matchStart, matchLen));
}
cachedCall.setArgument(i++, jsNumber(result.start));
@@ -536,7 +523,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
} else {
while (true) {
int* ovector;
- MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+ MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, source, startPosition, &ovector);
if (!result)
break;
@@ -550,7 +537,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
if (matchStart < 0)
cachedCall.setArgument(i, jsUndefined());
else
- cachedCall.setArgument(i, jsSubstring(globalData, source, matchStart, matchLen));
+ cachedCall.setArgument(i, jsSubstring(vm, source, matchStart, matchLen));
}
cachedCall.setArgument(i++, jsNumber(result.start));
@@ -574,10 +561,10 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
}
}
} else {
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
do {
int* ovector;
- MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector);
+ MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, source, startPosition, &ovector);
if (!result)
break;
@@ -810,7 +797,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
else if (!(dpos <= len)) // true for NaN
dpos = len;
- size_t result = s.reverseFind(u2, static_cast<unsigned>(dpos));
+ size_t result;
+ unsigned startPosition = static_cast<unsigned>(dpos);
+ if (!startPosition)
+ result = s.startsWith(u2) ? 0 : notFound;
+ else
+ result = s.reverseFind(u2, startPosition);
if (result == notFound)
return JSValue::encode(jsNumber(-1));
return JSValue::encode(jsNumber(result));
@@ -823,7 +815,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
return throwVMTypeError(exec);
JSString* string = thisValue.toString(exec);
String s = string->value(exec);
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
JSValue a0 = exec->argument(0);
@@ -845,12 +837,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
* replaced with the result of the expression new RegExp(regexp).
* Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
*/
- regExp = RegExp::create(exec->globalData(), a0.isUndefined() ? String("") : a0.toString(exec)->value(exec), NoFlags);
+ regExp = RegExp::create(exec->vm(), a0.isUndefined() ? String("") : a0.toString(exec)->value(exec), NoFlags);
if (!regExp->isValid())
return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
- MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, s, 0);
+ MatchResult result = regExpConstructor->performMatch(*vm, regExp, string, s, 0);
// case without 'g' flag is handled like RegExp.prototype.exec
if (!global)
return JSValue::encode(result ? RegExpMatchesArray::create(exec, string, regExp, result) : jsNull());
@@ -863,7 +855,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
list.append(jsSubstring(exec, s, result.start, length));
if (!length)
++end;
- result = regExpConstructor->performMatch(*globalData, regExp, string, s, end);
+ result = regExpConstructor->performMatch(*vm, regExp, string, s, end);
}
if (list.isEmpty()) {
// if there are no matches at all, it's important to return
@@ -882,7 +874,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
return throwVMTypeError(exec);
JSString* string = thisValue.toString(exec);
String s = string->value(exec);
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
JSValue a0 = exec->argument(0);
@@ -896,12 +888,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
* replaced with the result of the expression new RegExp(regexp).
* Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
*/
- reg = RegExp::create(exec->globalData(), a0.isUndefined() ? String("") : a0.toString(exec)->value(exec), NoFlags);
+ reg = RegExp::create(exec->vm(), a0.isUndefined() ? String("") : a0.toString(exec)->value(exec), NoFlags);
if (!reg->isValid())
return throwVMError(exec, createSyntaxError(exec, reg->errorMessage()));
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
- MatchResult result = regExpConstructor->performMatch(*globalData, reg, string, s, 0);
+ MatchResult result = regExpConstructor->performMatch(*vm, reg, string, s, 0);
return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1));
}
@@ -991,7 +983,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// otherwise let R = ToString(separator).
JSValue separatorValue = exec->argument(0);
if (separatorValue.inherits(&RegExpObject::s_info)) {
- JSGlobalData* globalData = &exec->globalData();
+ VM* vm = &exec->vm();
RegExp* reg = asRegExpObject(separatorValue)->regExp();
// 9. If lim == 0, return A.
@@ -1014,7 +1006,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// c. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
- if (!reg->match(*globalData, input, 0))
+ if (!reg->match(*vm, input, 0))
result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input));
return JSValue::encode(result);
}
@@ -1025,7 +1017,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
while (matchPosition < input.length()) {
// a. Call SplitMatch(S, q, R) and let z be its MatchResult result.
Vector<int, 32> ovector;
- int mpos = reg->match(*globalData, input, matchPosition, ovector);
+ int mpos = reg->match(*vm, input, matchPosition, ovector);
// b. If z is failure, then let q = q + 1.
if (mpos < 0)
break;
@@ -1290,9 +1282,6 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
{
- if (exec->argumentCount() < 1)
- return JSValue::encode(jsNumber(0));
-
JSValue thisValue = exec->hostThisValue();
if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
return throwVMTypeError(exec);
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h
index b846c7bb3..a7aca4c3e 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.h
+++ b/Source/JavaScriptCore/runtime/StringPrototype.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -34,27 +34,18 @@ namespace JSC {
public:
typedef StringObject Base;
- static StringPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
- {
- JSString* empty = jsEmptyString(exec);
- StringPrototype* prototype = new (NotNull, allocateCell<StringPrototype>(*exec->heap())) StringPrototype(exec, structure);
- prototype->finishCreation(exec, globalObject, empty);
- return prototype;
- }
-
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+ static StringPrototype* create(ExecState*, JSGlobalObject*, Structure*);
- 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);
}
static const ClassInfo s_info;
protected:
void finishCreation(ExecState*, JSGlobalObject*, JSString*);
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags;
+ static const unsigned StructureFlags = StringObject::StructureFlags;
};
diff --git a/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp b/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp
index 22b7367bc..8835a5c1c 100644
--- a/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp
+++ b/Source/JavaScriptCore/runtime/StringRecursionChecker.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@
#include "Error.h"
#include "ExceptionHelpers.h"
+#include "Operations.h"
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/StringRecursionChecker.h b/Source/JavaScriptCore/runtime/StringRecursionChecker.h
index a1b4a51fe..6f236f1f1 100644
--- a/Source/JavaScriptCore/runtime/StringRecursionChecker.h
+++ b/Source/JavaScriptCore/runtime/StringRecursionChecker.h
@@ -21,6 +21,7 @@
#define StringRecursionChecker_h
#include "Interpreter.h"
+#include "VMStackBounds.h"
#include <wtf/StackStats.h>
#include <wtf/WTFThreadData.h>
@@ -49,10 +50,11 @@ private:
inline JSValue StringRecursionChecker::performCheck()
{
- const StackBounds& nativeStack = wtfThreadData().stack();
+ VM& vm = m_exec->vm();
+ const VMStackBounds nativeStack(vm, wtfThreadData().stack());
if (!nativeStack.isSafeToRecurse())
return throwStackOverflowError();
- bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).isNewEntry;
+ bool alreadyVisited = !vm.stringRecursionCheckVisitedObjects.add(m_thisObject).isNewEntry;
if (alreadyVisited)
return emptyString(); // Return empty string to avoid infinite recursion.
return JSValue(); // Indicate success.
@@ -74,8 +76,8 @@ inline StringRecursionChecker::~StringRecursionChecker()
{
if (m_earlyReturnValue)
return;
- ASSERT(m_exec->globalData().stringRecursionCheckVisitedObjects.contains(m_thisObject));
- m_exec->globalData().stringRecursionCheckVisitedObjects.remove(m_thisObject);
+ ASSERT(m_exec->vm().stringRecursionCheckVisitedObjects.contains(m_thisObject));
+ m_exec->vm().stringRecursionCheckVisitedObjects.remove(m_thisObject);
}
}
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index 9ffe3b060..f551eaecc 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 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
@@ -26,11 +26,13 @@
#include "config.h"
#include "Structure.h"
+#include "CodeBlock.h"
#include "JSObject.h"
#include "JSPropertyNameIterator.h"
#include "Lookup.h"
#include "PropertyNameArray.h"
#include "StructureChain.h"
+#include "StructureRareDataInlines.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/RefPtr.h>
#include <wtf/Threading.h>
@@ -79,21 +81,21 @@ inline Structure* StructureTransitionTable::get(StringImpl* rep, unsigned attrib
return map()->get(make_pair(rep, attributes));
}
-inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure)
+inline void StructureTransitionTable::add(VM& vm, Structure* structure)
{
if (isUsingSingleSlot()) {
Structure* existingTransition = singleTransition();
// This handles the first transition being added.
if (!existingTransition) {
- setSingleTransition(globalData, structure);
+ setSingleTransition(vm, structure);
return;
}
// This handles the second transition being added
// (or the first transition being despecified!)
setMap(new TransitionMap());
- add(globalData, existingTransition);
+ add(vm, existingTransition);
}
// Add the structure to the map.
@@ -101,7 +103,7 @@ inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* s
// Newer versions of the STL have an std::make_pair function that takes rvalue references.
// When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
// See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details
- map()->set(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure);
+ map()->set(make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure);
}
void Structure::dumpStatistics()
@@ -120,7 +122,7 @@ void Structure::dumpStatistics()
switch (structure->m_transitionTable.size()) {
case 0:
++numberLeaf;
- if (!structure->m_previous)
+ if (!structure->previousID())
++numberSingletons;
break;
@@ -129,9 +131,9 @@ void Structure::dumpStatistics()
break;
}
- if (structure->m_propertyTable) {
+ if (structure->propertyTable()) {
++numberWithPropertyMaps;
- totalPropertyMapsSize += structure->m_propertyTable->sizeInMemory();
+ totalPropertyMapsSize += structure->propertyTable()->sizeInMemory();
}
}
@@ -149,17 +151,16 @@ void Structure::dumpStatistics()
#endif
}
-Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, PropertyOffset inlineCapacity)
- : JSCell(globalData, globalData.structureStructure.get())
- , m_typeInfo(typeInfo)
- , m_indexingType(indexingType)
- , m_globalObject(globalData, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
- , m_prototype(globalData, this, prototype)
+Structure::Structure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
+ : JSCell(vm, vm.structureStructure.get())
+ , m_globalObject(vm, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
+ , m_prototype(vm, this, prototype)
, m_classInfo(classInfo)
, m_transitionWatchpointSet(InitializedWatching)
- , m_outOfLineCapacity(0)
- , m_inlineCapacity(inlineCapacity)
, m_offset(invalidOffset)
+ , m_typeInfo(typeInfo)
+ , m_indexingType(indexingType)
+ , m_inlineCapacity(inlineCapacity)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
@@ -171,20 +172,22 @@ Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSV
, m_didTransition(false)
, m_staticFunctionReified(false)
{
+ ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
+ ASSERT(static_cast<PropertyOffset>(inlineCapacity) < firstOutOfLineOffset);
+ ASSERT(!typeInfo.structureHasRareData());
}
const ClassInfo Structure::s_info = { "Structure", 0, 0, 0, CREATE_METHOD_TABLE(Structure) };
-Structure::Structure(JSGlobalData& globalData)
+Structure::Structure(VM& vm)
: JSCell(CreatingEarlyCell)
- , m_typeInfo(CompoundType, OverridesVisitChildren)
- , m_indexingType(0)
- , m_prototype(globalData, this, jsNull())
+ , m_prototype(vm, this, jsNull())
, m_classInfo(&s_info)
, m_transitionWatchpointSet(InitializedWatching)
- , m_outOfLineCapacity(0)
- , m_inlineCapacity(0)
, m_offset(invalidOffset)
+ , m_typeInfo(CompoundType, OverridesVisitChildren)
+ , m_indexingType(0)
+ , m_inlineCapacity(0)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
@@ -198,16 +201,15 @@ Structure::Structure(JSGlobalData& globalData)
{
}
-Structure::Structure(JSGlobalData& globalData, const Structure* previous)
- : JSCell(globalData, globalData.structureStructure.get())
- , m_typeInfo(previous->typeInfo())
- , m_indexingType(previous->indexingTypeIncludingHistory())
- , m_prototype(globalData, this, previous->storedPrototype())
+Structure::Structure(VM& vm, const Structure* previous)
+ : JSCell(vm, vm.structureStructure.get())
+ , m_prototype(vm, this, previous->storedPrototype())
, m_classInfo(previous->m_classInfo)
, m_transitionWatchpointSet(InitializedWatching)
- , m_outOfLineCapacity(previous->m_outOfLineCapacity)
- , m_inlineCapacity(previous->m_inlineCapacity)
, m_offset(invalidOffset)
+ , m_typeInfo(previous->typeInfo().type(), previous->typeInfo().flags() & ~StructureHasRareData)
+ , m_indexingType(previous->indexingTypeIncludingHistory())
+ , m_inlineCapacity(previous->m_inlineCapacity)
, m_dictionaryKind(previous->m_dictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
@@ -219,9 +221,14 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
, m_didTransition(true)
, m_staticFunctionReified(previous->m_staticFunctionReified)
{
+ if (previous->typeInfo().structureHasRareData() && previous->rareData()->needsCloning())
+ cloneRareDataFrom(vm, previous);
+ else if (previous->previousID())
+ m_previousOrRareData.set(vm, this, previous->previousID());
+
previous->notifyTransitionFromThisStructure();
if (previous->m_globalObject)
- m_globalObject.set(globalData, this, previous->m_globalObject.get());
+ m_globalObject.set(vm, this, previous->m_globalObject.get());
}
void Structure::destroy(JSCell* cell)
@@ -229,10 +236,10 @@ void Structure::destroy(JSCell* cell)
static_cast<Structure*>(cell)->Structure::~Structure();
}
-void Structure::materializePropertyMap(JSGlobalData& globalData)
+void Structure::materializePropertyMap(VM& vm)
{
ASSERT(structure()->classInfo() == &s_info);
- ASSERT(!m_propertyTable);
+ ASSERT(!propertyTable());
Vector<Structure*, 8> structures;
structures.append(this);
@@ -242,26 +249,28 @@ void Structure::materializePropertyMap(JSGlobalData& globalData)
// Search for the last Structure with a property table.
while ((structure = structure->previousID())) {
if (structure->m_isPinnedPropertyTable) {
- ASSERT(structure->m_propertyTable);
- ASSERT(!structure->m_previous);
+ ASSERT(structure->propertyTable());
+ ASSERT(!structure->previousID());
- m_propertyTable = structure->m_propertyTable->copy(globalData, 0, numberOfSlotsForLastOffset(m_offset, m_typeInfo.type()));
+ propertyTable().set(vm, this, structure->propertyTable()->copy(vm, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)));
break;
}
structures.append(structure);
}
- if (!m_propertyTable)
- createPropertyMap(numberOfSlotsForLastOffset(m_offset, m_typeInfo.type()));
+ if (!propertyTable())
+ createPropertyMap(vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
- for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
+ for (ptrdiff_t i = structures.size() - 1; i >= 0; --i) {
structure = structures[i];
if (!structure->m_nameInPrevious)
continue;
- PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
- m_propertyTable->add(entry);
+ PropertyMapEntry entry(vm, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
+ propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
}
+
+ checkOffsetConsistency();
}
inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity)
@@ -271,26 +280,21 @@ inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity)
return currentCapacity * outOfLineGrowthFactor;
}
-void Structure::growOutOfLineCapacity()
-{
- m_outOfLineCapacity = nextOutOfLineStorageCapacity(m_outOfLineCapacity);
-}
-
size_t Structure::suggestedNewOutOfLineStorageCapacity()
{
- return nextOutOfLineStorageCapacity(m_outOfLineCapacity);
+ return nextOutOfLineStorageCapacity(outOfLineCapacity());
}
-void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, PropertyName propertyName)
+void Structure::despecifyDictionaryFunction(VM& vm, PropertyName propertyName)
{
StringImpl* rep = propertyName.uid();
- materializePropertyMapIfNecessary(globalData);
+ materializePropertyMapIfNecessary(vm);
ASSERT(isDictionary());
- ASSERT(m_propertyTable);
+ ASSERT(propertyTable());
- PropertyMapEntry* entry = m_propertyTable->find(rep).first;
+ PropertyMapEntry* entry = propertyTable()->find(rep).first;
ASSERT(entry);
entry->specificValue.clear();
}
@@ -304,7 +308,7 @@ Structure* Structure::addPropertyTransitionToExistingStructure(Structure* struct
JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get();
if (specificValueInPrevious && specificValueInPrevious != specificValue)
return 0;
- validateOffset(existingTransition->m_offset, structure->m_typeInfo.type());
+ validateOffset(existingTransition->m_offset, existingTransition->inlineCapacity());
offset = existingTransition->m_offset;
return existingTransition;
}
@@ -340,7 +344,7 @@ NonPropertyTransition Structure::suggestedArrayStorageTransition() const
return AllocateArrayStorage;
}
-Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
+Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
{
// If we have a specific function, we may have got to this point if there is
// already a transition with the correct property name and attributes, but
@@ -360,185 +364,190 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
specificValue = 0;
if (structure->transitionCount() > s_maxTransitionLength) {
- Structure* transition = toCacheableDictionaryTransition(globalData, structure);
+ Structure* transition = toCacheableDictionaryTransition(vm, structure);
ASSERT(structure != transition);
- offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
- if (transition->outOfLineSize() > transition->outOfLineCapacity())
- transition->growOutOfLineCapacity();
+ offset = transition->putSpecificValue(vm, propertyName, attributes, specificValue);
return transition;
}
- Structure* transition = create(globalData, structure);
+ Structure* transition = create(vm, structure);
- transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
- transition->m_previous.set(globalData, transition, structure);
+ transition->m_cachedPrototypeChain.setMayBeNull(vm, transition, structure->m_cachedPrototypeChain.get());
+ transition->setPreviousID(vm, transition, structure);
transition->m_nameInPrevious = propertyName.uid();
transition->m_attributesInPrevious = attributes;
- transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue);
-
- if (structure->m_propertyTable) {
- if (structure->m_isPinnedPropertyTable)
- transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1);
- else
- transition->m_propertyTable = structure->m_propertyTable.release();
- } else {
- if (structure->m_previous)
- transition->materializePropertyMap(globalData);
- else
- transition->createPropertyMap();
- }
+ transition->m_specificValueInPrevious.setMayBeNull(vm, transition, specificValue);
+ transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm, transition));
+ transition->m_offset = structure->m_offset;
- offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
- if (transition->outOfLineSize() > transition->outOfLineCapacity())
- transition->growOutOfLineCapacity();
+ offset = transition->putSpecificValue(vm, propertyName, attributes, specificValue);
- transition->m_offset = offset;
- structure->m_transitionTable.add(globalData, transition);
+ checkOffset(transition->m_offset, transition->inlineCapacity());
+ structure->m_transitionTable.add(vm, transition);
+ transition->checkOffsetConsistency();
+ structure->checkOffsetConsistency();
return transition;
}
-Structure* Structure::removePropertyTransition(JSGlobalData& globalData, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
+Structure* Structure::removePropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, PropertyOffset& offset)
{
ASSERT(!structure->isUncacheableDictionary());
- Structure* transition = toUncacheableDictionaryTransition(globalData, structure);
+ Structure* transition = toUncacheableDictionaryTransition(vm, structure);
offset = transition->remove(propertyName);
+ transition->checkOffsetConsistency();
return transition;
}
-Structure* Structure::changePrototypeTransition(JSGlobalData& globalData, Structure* structure, JSValue prototype)
+Structure* Structure::changePrototypeTransition(VM& vm, Structure* structure, JSValue prototype)
{
- Structure* transition = create(globalData, structure);
+ Structure* transition = create(vm, structure);
- transition->m_prototype.set(globalData, transition, prototype);
+ transition->m_prototype.set(vm, transition, prototype);
- // Don't set m_offset, as one can not transition to this.
-
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ structure->materializePropertyMapIfNecessary(vm);
+ transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
+ transition->m_offset = structure->m_offset;
transition->pin();
+ transition->checkOffsetConsistency();
return transition;
}
-Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Structure* structure, PropertyName replaceFunction)
+Structure* Structure::despecifyFunctionTransition(VM& vm, Structure* structure, PropertyName replaceFunction)
{
ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
- Structure* transition = create(globalData, structure);
+ Structure* transition = create(vm, structure);
++transition->m_specificFunctionThrashCount;
- // Don't set m_offset, as one can not transition to this.
-
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ structure->materializePropertyMapIfNecessary(vm);
+ transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
+ transition->m_offset = structure->m_offset;
transition->pin();
if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
- transition->despecifyAllFunctions(globalData);
+ transition->despecifyAllFunctions(vm);
else {
- bool removed = transition->despecifyFunction(globalData, replaceFunction);
+ bool removed = transition->despecifyFunction(vm, replaceFunction);
ASSERT_UNUSED(removed, removed);
}
+ transition->checkOffsetConsistency();
return transition;
}
-Structure* Structure::attributeChangeTransition(JSGlobalData& globalData, Structure* structure, PropertyName propertyName, unsigned attributes)
+Structure* Structure::attributeChangeTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes)
{
if (!structure->isUncacheableDictionary()) {
- Structure* transition = create(globalData, structure);
-
- // Don't set m_offset, as one can not transition to this.
+ Structure* transition = create(vm, structure);
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ structure->materializePropertyMapIfNecessary(vm);
+ transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
+ transition->m_offset = structure->m_offset;
transition->pin();
structure = transition;
}
- ASSERT(structure->m_propertyTable);
- PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.uid()).first;
+ ASSERT(structure->propertyTable());
+ PropertyMapEntry* entry = structure->propertyTable()->find(propertyName.uid()).first;
ASSERT(entry);
entry->attributes = attributes;
+ structure->checkOffsetConsistency();
return structure;
}
-Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
+Structure* Structure::toDictionaryTransition(VM& vm, Structure* structure, DictionaryKind kind)
{
ASSERT(!structure->isUncacheableDictionary());
- Structure* transition = create(globalData, structure);
+ Structure* transition = create(vm, structure);
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ structure->materializePropertyMapIfNecessary(vm);
+ transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
+ transition->m_offset = structure->m_offset;
transition->m_dictionaryKind = kind;
transition->pin();
+ transition->checkOffsetConsistency();
return transition;
}
-Structure* Structure::toCacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::toCacheableDictionaryTransition(VM& vm, Structure* structure)
{
- return toDictionaryTransition(globalData, structure, CachedDictionaryKind);
+ return toDictionaryTransition(vm, structure, CachedDictionaryKind);
}
-Structure* Structure::toUncacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::toUncacheableDictionaryTransition(VM& vm, Structure* structure)
{
- return toDictionaryTransition(globalData, structure, UncachedDictionaryKind);
+ return toDictionaryTransition(vm, structure, UncachedDictionaryKind);
}
// In future we may want to cache this transition.
-Structure* Structure::sealTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::sealTransition(VM& vm, Structure* structure)
{
- Structure* transition = preventExtensionsTransition(globalData, structure);
+ Structure* transition = preventExtensionsTransition(vm, structure);
- if (transition->m_propertyTable) {
- PropertyTable::iterator end = transition->m_propertyTable->end();
- for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
+ if (transition->propertyTable()) {
+ PropertyTable::iterator end = transition->propertyTable()->end();
+ for (PropertyTable::iterator iter = transition->propertyTable()->begin(); iter != end; ++iter)
iter->attributes |= DontDelete;
}
+ transition->checkOffsetConsistency();
return transition;
}
// In future we may want to cache this transition.
-Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::freezeTransition(VM& vm, Structure* structure)
{
- Structure* transition = preventExtensionsTransition(globalData, structure);
+ Structure* transition = preventExtensionsTransition(vm, structure);
- if (transition->m_propertyTable) {
- PropertyTable::iterator iter = transition->m_propertyTable->begin();
- PropertyTable::iterator end = transition->m_propertyTable->end();
+ if (transition->propertyTable()) {
+ PropertyTable::iterator iter = transition->propertyTable()->begin();
+ PropertyTable::iterator end = transition->propertyTable()->end();
if (iter != end)
transition->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
for (; iter != end; ++iter)
iter->attributes |= iter->attributes & Accessor ? DontDelete : (DontDelete | ReadOnly);
}
+ transition->checkOffsetConsistency();
return transition;
}
// In future we may want to cache this transition.
-Structure* Structure::preventExtensionsTransition(JSGlobalData& globalData, Structure* structure)
+Structure* Structure::preventExtensionsTransition(VM& vm, Structure* structure)
{
- Structure* transition = create(globalData, structure);
+ Structure* transition = create(vm, structure);
// Don't set m_offset, as one can not transition to this.
- structure->materializePropertyMapIfNecessary(globalData);
- transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition);
+ structure->materializePropertyMapIfNecessary(vm);
+ transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm, transition));
+ transition->m_offset = structure->m_offset;
transition->m_preventExtensions = true;
transition->pin();
+ transition->checkOffsetConsistency();
return transition;
}
-Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure* structure, NonPropertyTransition transitionKind)
+PropertyTable* Structure::takePropertyTableOrCloneIfPinned(VM& vm, Structure* owner)
+{
+ materializePropertyMapIfNecessaryForPinning(vm);
+ if (m_isPinnedPropertyTable)
+ return propertyTable()->copy(vm, owner, propertyTable()->size() + 1);
+ PropertyTable* takenPropertyTable = propertyTable().get();
+ propertyTable().clear();
+ return takenPropertyTable;
+}
+
+Structure* Structure::nonPropertyTransition(VM& vm, Structure* structure, NonPropertyTransition transitionKind)
{
unsigned attributes = toAttributes(transitionKind);
IndexingType indexingType = newIndexingType(structure->indexingTypeIncludingHistory(), transitionKind);
@@ -559,40 +568,31 @@ Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure*
return existingTransition;
}
- Structure* transition = create(globalData, structure);
- transition->m_previous.set(globalData, transition, structure);
+ Structure* transition = create(vm, structure);
+ transition->setPreviousID(vm, transition, structure);
transition->m_attributesInPrevious = attributes;
transition->m_indexingType = indexingType;
+ transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm, transition));
transition->m_offset = structure->m_offset;
+ checkOffset(transition->m_offset, transition->inlineCapacity());
- if (structure->m_propertyTable) {
- if (structure->m_isPinnedPropertyTable)
- transition->m_propertyTable = structure->m_propertyTable->copy(globalData, transition, structure->m_propertyTable->size() + 1);
- else
- transition->m_propertyTable = structure->m_propertyTable.release();
- } else {
- if (structure->m_previous)
- transition->materializePropertyMap(globalData);
- else
- transition->createPropertyMap();
- }
-
- structure->m_transitionTable.add(globalData, transition);
+ structure->m_transitionTable.add(vm, transition);
+ transition->checkOffsetConsistency();
return transition;
}
// In future we may want to cache this property.
-bool Structure::isSealed(JSGlobalData& globalData)
+bool Structure::isSealed(VM& vm)
{
if (isExtensible())
return false;
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return true;
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ PropertyTable::iterator end = propertyTable()->end();
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
if ((iter->attributes & DontDelete) != DontDelete)
return false;
}
@@ -600,17 +600,17 @@ bool Structure::isSealed(JSGlobalData& globalData)
}
// In future we may want to cache this property.
-bool Structure::isFrozen(JSGlobalData& globalData)
+bool Structure::isFrozen(VM& vm)
{
if (isExtensible())
return false;
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return true;
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ PropertyTable::iterator end = propertyTable()->end();
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
if (!(iter->attributes & DontDelete))
return false;
if (!(iter->attributes & (ReadOnly | Accessor)))
@@ -619,59 +619,59 @@ bool Structure::isFrozen(JSGlobalData& globalData)
return true;
}
-Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object)
+Structure* Structure::flattenDictionaryStructure(VM& vm, JSObject* object)
{
+ checkOffsetConsistency();
ASSERT(isDictionary());
if (isUncacheableDictionary()) {
- ASSERT(m_propertyTable);
+ ASSERT(propertyTable());
- size_t propertyCount = m_propertyTable->size();
+ size_t propertyCount = propertyTable()->size();
// Holds our values compacted by insertion order.
Vector<JSValue> values(propertyCount);
// Copies out our values from their hashed locations, compacting property table offsets as we go.
unsigned i = 0;
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter, ++i) {
- values[i] = object->getDirectOffset(iter->offset);
- iter->offset = propertyOffsetFor(i, m_inlineCapacity);
+ PropertyTable::iterator end = propertyTable()->end();
+ m_offset = invalidOffset;
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter, ++i) {
+ values[i] = object->getDirect(iter->offset);
+ m_offset = iter->offset = offsetForPropertyNumber(i, m_inlineCapacity);
}
// Copies in our values to their compacted locations.
for (unsigned i = 0; i < propertyCount; i++)
- object->putDirectOffset(globalData, propertyOffsetFor(i, m_inlineCapacity), values[i]);
+ object->putDirect(vm, offsetForPropertyNumber(i, m_inlineCapacity), values[i]);
- m_propertyTable->clearDeletedOffsets();
+ propertyTable()->clearDeletedOffsets();
+ checkOffsetConsistency();
}
m_dictionaryKind = NoneDictionaryKind;
return this;
}
-PropertyOffset Structure::addPropertyWithoutTransition(JSGlobalData& globalData, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
+PropertyOffset Structure::addPropertyWithoutTransition(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
{
- ASSERT(!m_enumerationCache);
+ ASSERT(!enumerationCache());
if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
specificValue = 0;
- materializePropertyMapIfNecessaryForPinning(globalData);
+ materializePropertyMapIfNecessaryForPinning(vm);
pin();
- PropertyOffset offset = putSpecificValue(globalData, propertyName, attributes, specificValue);
- if (outOfLineSize() > outOfLineCapacity())
- growOutOfLineCapacity();
- return offset;
+ return putSpecificValue(vm, propertyName, attributes, specificValue);
}
-PropertyOffset Structure::removePropertyWithoutTransition(JSGlobalData& globalData, PropertyName propertyName)
+PropertyOffset Structure::removePropertyWithoutTransition(VM& vm, PropertyName propertyName)
{
ASSERT(isUncacheableDictionary());
- ASSERT(!m_enumerationCache);
+ ASSERT(!enumerationCache());
- materializePropertyMapIfNecessaryForPinning(globalData);
+ materializePropertyMapIfNecessaryForPinning(vm);
pin();
return remove(propertyName);
@@ -679,12 +679,28 @@ PropertyOffset Structure::removePropertyWithoutTransition(JSGlobalData& globalDa
void Structure::pin()
{
- ASSERT(m_propertyTable);
+ ASSERT(propertyTable());
m_isPinnedPropertyTable = true;
- m_previous.clear();
+ clearPreviousID();
m_nameInPrevious.clear();
}
+void Structure::allocateRareData(VM& vm)
+{
+ ASSERT(!typeInfo().structureHasRareData());
+ StructureRareData* rareData = StructureRareData::create(vm, previous());
+ m_typeInfo = TypeInfo(typeInfo().type(), typeInfo().flags() | StructureHasRareData);
+ m_previousOrRareData.set(vm, this, rareData);
+}
+
+void Structure::cloneRareDataFrom(VM& vm, const Structure* other)
+{
+ ASSERT(other->typeInfo().structureHasRareData());
+ StructureRareData* newRareData = StructureRareData::clone(vm, other->rareData());
+ m_typeInfo = TypeInfo(typeInfo().type(), typeInfo().flags() | StructureHasRareData);
+ m_previousOrRareData.set(vm, this, newRareData);
+}
+
#if DUMP_PROPERTYMAP_STATS
struct PropertyMapStatisticsExitLogger {
@@ -708,29 +724,34 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
inline void Structure::checkConsistency()
{
+ checkOffsetConsistency();
}
#endif
-PassOwnPtr<PropertyTable> Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner)
+PropertyTable* Structure::copyPropertyTable(VM& vm, Structure* owner)
{
- return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0);
+ if (!propertyTable())
+ return 0;
+ return PropertyTable::clone(vm, owner, *propertyTable().get());
}
-PassOwnPtr<PropertyTable> Structure::copyPropertyTableForPinning(JSGlobalData& globalData, Structure* owner)
+PropertyTable* Structure::copyPropertyTableForPinning(VM& vm, Structure* owner)
{
- return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : new PropertyTable(numberOfSlotsForLastOffset(m_offset, m_typeInfo.type())));
+ if (propertyTable())
+ return PropertyTable::clone(vm, owner, *propertyTable().get());
+ return PropertyTable::create(vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
}
-PropertyOffset Structure::get(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
+PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
{
ASSERT(structure()->classInfo() == &s_info);
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return invalidOffset;
- PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
+ PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
if (!entry)
return invalidOffset;
@@ -739,13 +760,13 @@ PropertyOffset Structure::get(JSGlobalData& globalData, PropertyName propertyNam
return entry->offset;
}
-bool Structure::despecifyFunction(JSGlobalData& globalData, PropertyName propertyName)
+bool Structure::despecifyFunction(VM& vm, PropertyName propertyName)
{
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return false;
- PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
+ PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
if (!entry)
return false;
@@ -754,20 +775,20 @@ bool Structure::despecifyFunction(JSGlobalData& globalData, PropertyName propert
return true;
}
-void Structure::despecifyAllFunctions(JSGlobalData& globalData)
+void Structure::despecifyAllFunctions(VM& vm)
{
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return;
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter)
+ PropertyTable::iterator end = propertyTable()->end();
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter)
iter->specificValue.clear();
}
-PropertyOffset Structure::putSpecificValue(JSGlobalData& globalData, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
+PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
{
- ASSERT(!JSC::isValidOffset(get(globalData, propertyName)));
+ ASSERT(!JSC::isValidOffset(get(vm, propertyName)));
checkConsistency();
if (attributes & DontEnum)
@@ -775,13 +796,13 @@ PropertyOffset Structure::putSpecificValue(JSGlobalData& globalData, PropertyNam
StringImpl* rep = propertyName.uid();
- if (!m_propertyTable)
- createPropertyMap();
-
- PropertyOffset newOffset = m_propertyTable->nextOffset(m_inlineCapacity);
+ if (!propertyTable())
+ createPropertyMap(vm);
- m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue));
+ PropertyOffset newOffset = propertyTable()->nextOffset(m_inlineCapacity);
+ propertyTable()->add(PropertyMapEntry(vm, this, rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);
+
checkConsistency();
return newOffset;
}
@@ -792,41 +813,40 @@ PropertyOffset Structure::remove(PropertyName propertyName)
StringImpl* rep = propertyName.uid();
- if (!m_propertyTable)
+ if (!propertyTable())
return invalidOffset;
- PropertyTable::find_iterator position = m_propertyTable->find(rep);
+ PropertyTable::find_iterator position = propertyTable()->find(rep);
if (!position.first)
return invalidOffset;
PropertyOffset offset = position.first->offset;
- m_propertyTable->remove(position);
- m_propertyTable->addDeletedOffset(offset);
+ propertyTable()->remove(position);
+ propertyTable()->addDeletedOffset(offset);
checkConsistency();
return offset;
}
-void Structure::createPropertyMap(unsigned capacity)
+void Structure::createPropertyMap(VM& vm, unsigned capacity)
{
- ASSERT(!m_propertyTable);
+ ASSERT(!propertyTable());
checkConsistency();
- m_propertyTable = adoptPtr(new PropertyTable(capacity));
- checkConsistency();
+ propertyTable().set(vm, this, PropertyTable::create(vm, capacity));
}
-void Structure::getPropertyNamesFromStructure(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
+void Structure::getPropertyNamesFromStructure(VM& vm, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
return;
bool knownUnique = !propertyNames.size();
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ PropertyTable::iterator end = propertyTable()->end();
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum));
if (iter->key->isIdentifier() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) {
if (knownUnique)
@@ -837,6 +857,11 @@ void Structure::getPropertyNamesFromStructure(JSGlobalData& globalData, Property
}
}
+JSValue Structure::prototypeForLookup(CodeBlock* codeBlock) const
+{
+ return prototypeForLookup(codeBlock->globalObject());
+}
+
void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
Structure* thisObject = jsCast<Structure*>(cell);
@@ -851,18 +876,17 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor)
visitor.append(&thisObject->m_prototype);
visitor.append(&thisObject->m_cachedPrototypeChain);
}
- visitor.append(&thisObject->m_previous);
+ visitor.append(&thisObject->m_previousOrRareData);
visitor.append(&thisObject->m_specificValueInPrevious);
- visitor.append(&thisObject->m_enumerationCache);
- if (thisObject->m_propertyTable) {
- PropertyTable::iterator end = thisObject->m_propertyTable->end();
- for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr)
- visitor.append(&ptr->specificValue);
- }
- visitor.append(&thisObject->m_objectToStringValue);
+
+ if (thisObject->m_isPinnedPropertyTable) {
+ ASSERT(thisObject->m_propertyTableUnsafe);
+ visitor.append(&thisObject->m_propertyTableUnsafe);
+ } else if (thisObject->m_propertyTableUnsafe)
+ thisObject->m_propertyTableUnsafe.clear();
}
-bool Structure::prototypeChainMayInterceptStoreTo(JSGlobalData& globalData, PropertyName propertyName)
+bool Structure::prototypeChainMayInterceptStoreTo(VM& vm, PropertyName propertyName)
{
unsigned i = propertyName.asIndex();
if (i != PropertyName::NotAnIndex)
@@ -877,7 +901,7 @@ bool Structure::prototypeChainMayInterceptStoreTo(JSGlobalData& globalData, Prop
unsigned attributes;
JSCell* specificValue;
- PropertyOffset offset = current->get(globalData, propertyName, attributes, specificValue);
+ PropertyOffset offset = current->get(vm, propertyName, attributes, specificValue);
if (!JSC::isValidOffset(offset))
continue;
@@ -892,6 +916,7 @@ bool Structure::prototypeChainMayInterceptStoreTo(JSGlobalData& globalData, Prop
void PropertyTable::checkConsistency()
{
+ checkOffsetConsistency();
ASSERT(m_indexSize >= PropertyTable::MinimumTableSize);
ASSERT(m_indexMask);
ASSERT(m_indexSize == m_indexMask + 1);
@@ -949,17 +974,17 @@ void PropertyTable::checkConsistency()
void Structure::checkConsistency()
{
- if (!m_propertyTable)
+ if (!propertyTable())
return;
if (!m_hasNonEnumerableProperties) {
- PropertyTable::iterator end = m_propertyTable->end();
- for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+ PropertyTable::iterator end = propertyTable()->end();
+ for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
ASSERT(!(iter->attributes & DontEnum));
}
}
- m_propertyTable->checkConsistency();
+ propertyTable()->checkConsistency();
}
#endif // DO_PROPERTYMAP_CONSTENCY_CHECK
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 6e4402c52..45379efd6 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 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,18 +28,17 @@
#include "ClassInfo.h"
#include "IndexingType.h"
+#include "JSCJSValue.h"
#include "JSCell.h"
#include "JSType.h"
-#include "JSValue.h"
-#include "PropertyMapHashTable.h"
#include "PropertyName.h"
#include "PropertyNameArray.h"
+#include "PropertyOffset.h"
#include "Protect.h"
+#include "StructureRareData.h"
#include "StructureTransitionTable.h"
#include "JSTypeInfo.h"
#include "Watchpoint.h"
-#include "Weak.h"
-#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/text/StringImpl.h>
@@ -47,562 +46,436 @@
namespace JSC {
- class LLIntOffsetsExtractor;
- class PropertyNameArray;
- class PropertyNameArrayData;
- class StructureChain;
- class SlotVisitor;
- class JSString;
-
- // The out-of-line property storage capacity to use when first allocating out-of-line
- // storage. Note that all objects start out without having any out-of-line storage;
- // this comes into play only on the first property store that exhausts inline storage.
- static const unsigned initialOutOfLineCapacity = 4;
-
- // The factor by which to grow out-of-line storage when it is exhausted, after the
- // initial allocation.
- static const unsigned outOfLineGrowthFactor = 2;
-
- class Structure : public JSCell {
- public:
- friend class StructureTransitionTable;
-
- typedef JSCell Base;
-
- static Structure* create(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, PropertyOffset inlineCapacity = 0);
-
- protected:
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- ASSERT(m_prototype);
- ASSERT(m_prototype.isObject() || m_prototype.isNull());
- }
-
- void finishCreation(JSGlobalData& globalData, CreatingEarlyCellTag)
- {
- Base::finishCreation(globalData, this, CreatingEarlyCell);
- ASSERT(m_prototype);
- ASSERT(m_prototype.isNull());
- ASSERT(!globalData.structureStructure);
- }
-
- public:
- static void dumpStatistics();
-
- JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
- JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
- static Structure* removePropertyTransition(JSGlobalData&, Structure*, PropertyName, PropertyOffset&);
- JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
- JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, PropertyName);
- static Structure* attributeChangeTransition(JSGlobalData&, Structure*, PropertyName, unsigned attributes);
- static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
- static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
- static Structure* sealTransition(JSGlobalData&, Structure*);
- static Structure* freezeTransition(JSGlobalData&, Structure*);
- static Structure* preventExtensionsTransition(JSGlobalData&, Structure*);
- static Structure* nonPropertyTransition(JSGlobalData&, Structure*, NonPropertyTransition);
-
- bool isSealed(JSGlobalData&);
- bool isFrozen(JSGlobalData&);
- bool isExtensible() const { return !m_preventExtensions; }
- bool didTransition() const { return m_didTransition; }
- bool putWillGrowOutOfLineStorage()
- {
- ASSERT(outOfLineCapacity() >= outOfLineSize());
-
- if (!m_propertyTable) {
- unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
- ASSERT(outOfLineCapacity() >= currentSize);
- return currentSize == outOfLineCapacity();
- }
-
- ASSERT(totalStorageCapacity() >= m_propertyTable->propertyStorageSize());
- if (m_propertyTable->hasDeletedOffset())
- return false;
-
- ASSERT(totalStorageCapacity() >= m_propertyTable->size());
- return m_propertyTable->size() == totalStorageCapacity();
- }
- JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity();
+class LLIntOffsetsExtractor;
+class PropertyNameArray;
+class PropertyNameArrayData;
+class PropertyTable;
+class StructureChain;
+class SlotVisitor;
+class JSString;
- Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
+// The out-of-line property storage capacity to use when first allocating out-of-line
+// storage. Note that all objects start out without having any out-of-line storage;
+// this comes into play only on the first property store that exhausts inline storage.
+static const unsigned initialOutOfLineCapacity = 4;
- static const bool needsDestruction = true;
- static const bool hasImmortalStructure = true;
- static void destroy(JSCell*);
+// The factor by which to grow out-of-line storage when it is exhausted, after the
+// initial allocation.
+static const unsigned outOfLineGrowthFactor = 2;
- // These should be used with caution.
- JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(JSGlobalData&, PropertyName, unsigned attributes, JSCell* specificValue);
- PropertyOffset removePropertyWithoutTransition(JSGlobalData&, PropertyName);
- void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
-
- bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
- bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
+class Structure : public JSCell {
+public:
+ friend class StructureTransitionTable;
- bool propertyAccessesAreCacheable() { return m_dictionaryKind != UncachedDictionaryKind && !typeInfo().prohibitsPropertyCaching(); }
+ typedef JSCell Base;
- // Type accessors.
- const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
- bool isObject() const { return typeInfo().isObject(); }
+ static Structure* create(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
- IndexingType indexingType() const { return m_indexingType & AllArrayTypes; }
- IndexingType indexingTypeIncludingHistory() const { return m_indexingType; }
-
- bool mayInterceptIndexedAccesses() const
- {
- return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors);
- }
-
- bool anyObjectInChainMayInterceptIndexedAccesses() const;
-
- bool needsSlowPutIndexing() const;
- NonPropertyTransition suggestedArrayStorageTransition() const;
-
- JSGlobalObject* globalObject() const { return m_globalObject.get(); }
- void setGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { m_globalObject.set(globalData, this, globalObject); }
-
- JSValue storedPrototype() const { return m_prototype.get(); }
- JSValue prototypeForLookup(ExecState*) const;
- JSValue prototypeForLookup(JSGlobalObject*) const;
- JSValue prototypeForLookup(CodeBlock*) const;
- StructureChain* prototypeChain(JSGlobalData&, JSGlobalObject*) const;
- StructureChain* prototypeChain(ExecState*) const;
- static void visitChildren(JSCell*, SlotVisitor&);
-
- // Will just the prototype chain intercept this property access?
- bool prototypeChainMayInterceptStoreTo(JSGlobalData&, PropertyName);
-
- bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
-
- Structure* previousID() const
- {
- ASSERT(structure()->classInfo() == &s_info);
- return m_previous.get();
- }
- bool transitivelyTransitionedFrom(Structure* structureToFind);
-
- void growOutOfLineCapacity();
- unsigned outOfLineCapacity() const
- {
- ASSERT(structure()->classInfo() == &s_info);
- return m_outOfLineCapacity;
- }
- unsigned outOfLineSize() const
- {
- ASSERT(structure()->classInfo() == &s_info);
- if (m_propertyTable) {
- unsigned totalSize = m_propertyTable->propertyStorageSize();
- unsigned inlineCapacity = this->inlineCapacity();
- if (totalSize < inlineCapacity)
- return 0;
- return totalSize - inlineCapacity;
- }
- return numberOfOutOfLineSlotsForLastOffset(m_offset);
- }
- bool hasInlineStorage() const
- {
- return !!m_inlineCapacity;
- }
- unsigned inlineCapacity() const
- {
- return m_inlineCapacity;
- }
- unsigned inlineSize() const
- {
- unsigned result;
- if (m_propertyTable)
- result = m_propertyTable->propertyStorageSize();
- else
- result = m_offset + 1;
- return std::min<unsigned>(result, m_inlineCapacity);
- }
- unsigned totalStorageSize() const
- {
- if (m_propertyTable)
- return m_propertyTable->propertyStorageSize();
- return numberOfSlotsForLastOffset(m_offset, m_typeInfo.type());
- }
- unsigned totalStorageCapacity() const
- {
- ASSERT(structure()->classInfo() == &s_info);
- return m_outOfLineCapacity + inlineCapacity();
- }
-
- PropertyOffset firstValidOffset() const
- {
- if (hasInlineStorage())
- return 0;
- return firstOutOfLineOffset;
- }
- PropertyOffset lastValidOffset() const
- {
- if (m_propertyTable)
- return propertyOffsetFor(m_propertyTable->propertyStorageSize() - 1, m_inlineCapacity);
- return m_offset;
- }
- bool isValidOffset(PropertyOffset offset) const
- {
- return offset >= firstValidOffset()
- && offset <= lastValidOffset();
- }
-
- bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
-
- PropertyOffset get(JSGlobalData&, PropertyName);
- PropertyOffset get(JSGlobalData&, const WTF::String& name);
- JS_EXPORT_PRIVATE PropertyOffset get(JSGlobalData&, PropertyName, unsigned& attributes, JSCell*& specificValue);
-
- bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
- bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
- void setHasGetterSetterProperties(bool is__proto__)
- {
- m_hasGetterSetterProperties = true;
- if (!is__proto__)
- m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
- }
- void setContainsReadOnlyProperties()
- {
- m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
- }
+protected:
+ void finishCreation(VM& vm)
+ {
+ Base::finishCreation(vm);
+ ASSERT(m_prototype);
+ ASSERT(m_prototype.isObject() || m_prototype.isNull());
+ }
- bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
-
- bool isEmpty() const
- {
- if (m_propertyTable)
- return m_propertyTable->isEmpty();
- return !JSC::isValidOffset(m_offset);
- }
-
- JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, PropertyName);
- void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
-
- void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
- JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
- void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode);
-
- JSString* objectToStringValue() { return m_objectToStringValue.get(); }
-
- void setObjectToStringValue(JSGlobalData& globalData, const JSCell* owner, JSString* value)
- {
- m_objectToStringValue.set(globalData, owner, value);
- }
-
- bool staticFunctionsReified()
- {
- return m_staticFunctionReified;
- }
-
- void setStaticFunctionsReified()
- {
- m_staticFunctionReified = true;
- }
-
- const ClassInfo* classInfo() const { return m_classInfo; }
-
- static ptrdiff_t prototypeOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_prototype);
- }
-
- static ptrdiff_t globalObjectOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_globalObject);
- }
-
- static ptrdiff_t typeInfoFlagsOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
- }
-
- static ptrdiff_t typeInfoTypeOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
- }
-
- static ptrdiff_t classInfoOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_classInfo);
- }
+ void finishCreation(VM& vm, CreatingEarlyCellTag)
+ {
+ Base::finishCreation(vm, this, CreatingEarlyCell);
+ ASSERT(m_prototype);
+ ASSERT(m_prototype.isNull());
+ ASSERT(!vm.structureStructure);
+ }
+
+public:
+ static void dumpStatistics();
+
+ JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
+ JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
+ static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
+ JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(VM&, Structure*, JSValue prototype);
+ JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(VM&, Structure*, PropertyName);
+ static Structure* attributeChangeTransition(VM&, Structure*, PropertyName, unsigned attributes);
+ static Structure* toCacheableDictionaryTransition(VM&, Structure*);
+ static Structure* toUncacheableDictionaryTransition(VM&, Structure*);
+ static Structure* sealTransition(VM&, Structure*);
+ static Structure* freezeTransition(VM&, Structure*);
+ static Structure* preventExtensionsTransition(VM&, Structure*);
+ static Structure* nonPropertyTransition(VM&, Structure*, NonPropertyTransition);
+
+ bool isSealed(VM&);
+ bool isFrozen(VM&);
+ bool isExtensible() const { return !m_preventExtensions; }
+ bool didTransition() const { return m_didTransition; }
+ bool putWillGrowOutOfLineStorage();
+ JS_EXPORT_PRIVATE size_t suggestedNewOutOfLineStorageCapacity();
+
+ Structure* flattenDictionaryStructure(VM&, JSObject*);
+
+ static const bool needsDestruction = true;
+ static const bool hasImmortalStructure = true;
+ static void destroy(JSCell*);
+
+ // These should be used with caution.
+ JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
+ PropertyOffset removePropertyWithoutTransition(VM&, PropertyName);
+ void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); }
- static ptrdiff_t indexingTypeOffset()
- {
- return OBJECT_OFFSETOF(Structure, m_indexingType);
- }
+ bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
+ bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
+
+ bool propertyAccessesAreCacheable() { return m_dictionaryKind != UncachedDictionaryKind && !typeInfo().prohibitsPropertyCaching(); }
+
+ // Type accessors.
+ const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
+ bool isObject() const { return typeInfo().isObject(); }
- static Structure* createStructure(JSGlobalData&);
+ IndexingType indexingType() const { return m_indexingType & AllArrayTypes; }
+ IndexingType indexingTypeIncludingHistory() const { return m_indexingType; }
- bool transitionWatchpointSetHasBeenInvalidated() const
- {
- return m_transitionWatchpointSet.hasBeenInvalidated();
- }
+ bool mayInterceptIndexedAccesses() const
+ {
+ return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors);
+ }
- bool transitionWatchpointSetIsStillValid() const
- {
- return m_transitionWatchpointSet.isStillValid();
- }
+ bool anyObjectInChainMayInterceptIndexedAccesses() const;
- void addTransitionWatchpoint(Watchpoint* watchpoint) const
- {
- ASSERT(transitionWatchpointSetIsStillValid());
- m_transitionWatchpointSet.add(watchpoint);
- }
+ bool needsSlowPutIndexing() const;
+ NonPropertyTransition suggestedArrayStorageTransition() const;
- void notifyTransitionFromThisStructure() const
- {
- m_transitionWatchpointSet.notifyWrite();
- }
+ JSGlobalObject* globalObject() const { return m_globalObject.get(); }
+ void setGlobalObject(VM& vm, JSGlobalObject* globalObject) { m_globalObject.set(vm, this, globalObject); }
- static JS_EXPORTDATA const ClassInfo s_info;
-
- private:
- friend class LLIntOffsetsExtractor;
-
- JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, PropertyOffset inlineCapacity);
- Structure(JSGlobalData&);
- Structure(JSGlobalData&, const Structure*);
-
- static Structure* create(JSGlobalData&, const Structure*);
+ JSValue storedPrototype() const { return m_prototype.get(); }
+ JSValue prototypeForLookup(ExecState*) const;
+ JSValue prototypeForLookup(JSGlobalObject*) const;
+ JSValue prototypeForLookup(CodeBlock*) const;
+ StructureChain* prototypeChain(VM&, JSGlobalObject*) const;
+ StructureChain* prototypeChain(ExecState*) const;
+ static void visitChildren(JSCell*, SlotVisitor&);
- typedef enum {
- NoneDictionaryKind = 0,
- CachedDictionaryKind = 1,
- UncachedDictionaryKind = 2
- } DictionaryKind;
- static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind);
-
- PropertyOffset putSpecificValue(JSGlobalData&, PropertyName, unsigned attributes, JSCell* specificValue);
- PropertyOffset remove(PropertyName);
-
- void createPropertyMap(unsigned keyCount = 0);
- void checkConsistency();
-
- bool despecifyFunction(JSGlobalData&, PropertyName);
- void despecifyAllFunctions(JSGlobalData&);
-
- PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
- PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner);
- JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&);
- void materializePropertyMapIfNecessary(JSGlobalData& globalData)
- {
- ASSERT(structure()->classInfo() == &s_info);
- if (!m_propertyTable && m_previous)
- materializePropertyMap(globalData);
- }
- void materializePropertyMapIfNecessaryForPinning(JSGlobalData& globalData)
- {
- ASSERT(structure()->classInfo() == &s_info);
- if (!m_propertyTable)
- materializePropertyMap(globalData);
- }
-
- int transitionCount() const
- {
- // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
- return numberOfSlotsForLastOffset(m_offset, m_typeInfo.type());
- }
-
- bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
- bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
+ // Will just the prototype chain intercept this property access?
+ bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
- void pin();
-
- static const int s_maxTransitionLength = 64;
-
- static const unsigned maxSpecificFunctionThrashCount = 3;
-
- TypeInfo m_typeInfo;
- IndexingType m_indexingType;
+ bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
- WriteBarrier<JSGlobalObject> m_globalObject;
- WriteBarrier<Unknown> m_prototype;
- mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
-
- WriteBarrier<Structure> m_previous;
- RefPtr<StringImpl> m_nameInPrevious;
- WriteBarrier<JSCell> m_specificValueInPrevious;
-
- const ClassInfo* m_classInfo;
+ Structure* previousID() const
+ {
+ ASSERT(structure()->classInfo() == &s_info);
+ if (typeInfo().structureHasRareData())
+ return rareData()->previousID();
+ return previous();
+ }
+ bool transitivelyTransitionedFrom(Structure* structureToFind);
- StructureTransitionTable m_transitionTable;
+ unsigned outOfLineCapacity() const
+ {
+ ASSERT(checkOffsetConsistency());
+
+ unsigned outOfLineSize = this->outOfLineSize();
- WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
+ if (!outOfLineSize)
+ return 0;
- OwnPtr<PropertyTable> m_propertyTable;
+ if (outOfLineSize <= initialOutOfLineCapacity)
+ return initialOutOfLineCapacity;
- WriteBarrier<JSString> m_objectToStringValue;
-
- mutable InlineWatchpointSet m_transitionWatchpointSet;
-
- uint32_t m_outOfLineCapacity;
- uint8_t m_inlineCapacity;
- COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
-
- // m_offset does not account for anonymous slots
- PropertyOffset m_offset;
-
- unsigned m_dictionaryKind : 2;
- bool m_isPinnedPropertyTable : 1;
- bool m_hasGetterSetterProperties : 1;
- bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
- bool m_hasNonEnumerableProperties : 1;
- unsigned m_attributesInPrevious : 22;
- unsigned m_specificFunctionThrashCount : 2;
- unsigned m_preventExtensions : 1;
- unsigned m_didTransition : 1;
- unsigned m_staticFunctionReified;
- };
-
- inline Structure* Structure::create(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, PropertyOffset inlineCapacity)
- {
- ASSERT(globalData.structureStructure);
- ASSERT(classInfo);
- Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
- structure->finishCreation(globalData);
- return structure;
+ ASSERT(outOfLineSize > initialOutOfLineCapacity);
+ COMPILE_ASSERT(outOfLineGrowthFactor == 2, outOfLineGrowthFactor_is_two);
+ return WTF::roundUpToPowerOfTwo(outOfLineSize);
}
-
- inline Structure* Structure::createStructure(JSGlobalData& globalData)
+ unsigned outOfLineSize() const
{
- ASSERT(!globalData.structureStructure);
- Structure* structure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData);
- structure->finishCreation(globalData, CreatingEarlyCell);
- return structure;
+ ASSERT(checkOffsetConsistency());
+ ASSERT(structure()->classInfo() == &s_info);
+
+ return numberOfOutOfLineSlotsForLastOffset(m_offset);
}
-
- inline Structure* Structure::create(JSGlobalData& globalData, const Structure* structure)
+ bool hasInlineStorage() const
{
- ASSERT(globalData.structureStructure);
- Structure* newStructure = new (NotNull, allocateCell<Structure>(globalData.heap)) Structure(globalData, structure);
- newStructure->finishCreation(globalData);
- return newStructure;
+ return !!m_inlineCapacity;
}
-
- inline PropertyOffset Structure::get(JSGlobalData& globalData, PropertyName propertyName)
+ unsigned inlineCapacity() const
+ {
+ return m_inlineCapacity;
+ }
+ unsigned inlineSize() const
+ {
+ return std::min<unsigned>(m_offset + 1, m_inlineCapacity);
+ }
+ unsigned totalStorageSize() const
+ {
+ return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
+ }
+ unsigned totalStorageCapacity() const
{
ASSERT(structure()->classInfo() == &s_info);
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
- return invalidOffset;
-
- PropertyMapEntry* entry = m_propertyTable->find(propertyName.uid()).first;
- return entry ? entry->offset : invalidOffset;
+ return outOfLineCapacity() + inlineCapacity();
}
- inline PropertyOffset Structure::get(JSGlobalData& globalData, const WTF::String& name)
+ PropertyOffset firstValidOffset() const
{
- ASSERT(structure()->classInfo() == &s_info);
- materializePropertyMapIfNecessary(globalData);
- if (!m_propertyTable)
- return invalidOffset;
+ if (hasInlineStorage())
+ return 0;
+ return firstOutOfLineOffset;
+ }
+ PropertyOffset lastValidOffset() const
+ {
+ return m_offset;
+ }
+ bool isValidOffset(PropertyOffset offset) const
+ {
+ return offset >= firstValidOffset()
+ && offset <= lastValidOffset();
+ }
+
+ bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject);
- PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first;
- return entry ? entry->offset : invalidOffset;
+ PropertyOffset get(VM&, PropertyName);
+ PropertyOffset get(VM&, const WTF::String& name);
+ JS_EXPORT_PRIVATE PropertyOffset get(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
+
+ bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
+ bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
+ void setHasGetterSetterProperties(bool is__proto__)
+ {
+ m_hasGetterSetterProperties = true;
+ if (!is__proto__)
+ m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
}
-
- inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+ void setContainsReadOnlyProperties()
+ {
+ m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+ }
+
+ bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
+
+ bool isEmpty() const
{
- return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+ ASSERT(checkOffsetConsistency());
+ return !JSC::isValidOffset(m_offset);
}
- inline JSValue JSValue::structureOrUndefined() const
+ JS_EXPORT_PRIVATE void despecifyDictionaryFunction(VM&, PropertyName);
+ void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
+
+ void setEnumerationCache(VM&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+ JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
+ void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
+
+ JSString* objectToStringValue()
{
- if (isCell())
- return JSValue(asCell()->structure());
- return jsUndefined();
+ if (!typeInfo().structureHasRareData())
+ return 0;
+ return rareData()->objectToStringValue();
}
- inline bool JSCell::isObject() const
+ void setObjectToStringValue(VM& vm, const JSCell* owner, JSString* value)
{
- return m_structure->isObject();
+ if (!typeInfo().structureHasRareData())
+ allocateRareData(vm);
+ rareData()->setObjectToStringValue(vm, owner, value);
}
- inline bool JSCell::isString() const
+ bool staticFunctionsReified()
{
- return m_structure->typeInfo().type() == StringType;
+ return m_staticFunctionReified;
}
- inline bool JSCell::isGetterSetter() const
+ void setStaticFunctionsReified()
{
- return m_structure->typeInfo().type() == GetterSetterType;
+ m_staticFunctionReified = true;
}
- inline bool JSCell::isProxy() const
+ const ClassInfo* classInfo() const { return m_classInfo; }
+
+ static ptrdiff_t prototypeOffset()
{
- return structure()->typeInfo().type() == ProxyType;
+ return OBJECT_OFFSETOF(Structure, m_prototype);
}
- inline bool JSCell::isAPIValueWrapper() const
+ static ptrdiff_t globalObjectOffset()
{
- return m_structure->typeInfo().type() == APIValueWrapperType;
+ return OBJECT_OFFSETOF(Structure, m_globalObject);
}
- inline void JSCell::setStructure(JSGlobalData& globalData, Structure* structure)
+ static ptrdiff_t typeInfoFlagsOffset()
{
- ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
- ASSERT(structure->classInfo() == m_structure->classInfo());
- ASSERT(!m_structure
- || m_structure->transitionWatchpointSetHasBeenInvalidated()
- || m_structure.get() == structure);
- m_structure.set(globalData, this, structure);
+ return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
}
- ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
+ static ptrdiff_t typeInfoTypeOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
+ }
+
+ static ptrdiff_t classInfoOffset()
+ {
+ return OBJECT_OFFSETOF(Structure, m_classInfo);
+ }
+
+ static ptrdiff_t indexingTypeOffset()
{
- ASSERT(!m_isCheckingForDefaultMarkViolation);
- if (!cell)
- return;
-#if ENABLE(GC_VALIDATION)
- validate(cell);
-#endif
- if (Heap::testAndSetMarked(cell) || !cell->structure())
- return;
+ return OBJECT_OFFSETOF(Structure, m_indexingType);
+ }
- m_visitCount++;
+ static Structure* createStructure(VM&);
+
+ bool transitionWatchpointSetHasBeenInvalidated() const
+ {
+ return m_transitionWatchpointSet.hasBeenInvalidated();
+ }
+
+ bool transitionWatchpointSetIsStillValid() const
+ {
+ return m_transitionWatchpointSet.isStillValid();
+ }
+
+ void addTransitionWatchpoint(Watchpoint* watchpoint) const
+ {
+ ASSERT(transitionWatchpointSetIsStillValid());
+ m_transitionWatchpointSet.add(watchpoint);
+ }
+
+ void notifyTransitionFromThisStructure() const
+ {
+ m_transitionWatchpointSet.notifyWrite();
+ }
- MARK_LOG_CHILD(*this, cell);
+ static JS_EXPORTDATA const ClassInfo s_info;
+
+private:
+ friend class LLIntOffsetsExtractor;
- // Should never attempt to mark something that is zapped.
- ASSERT(!cell->isZapped());
+ JS_EXPORT_PRIVATE Structure(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity);
+ Structure(VM&);
+ Structure(VM&, const Structure*);
+
+ static Structure* create(VM&, const Structure*);
- m_stack.append(cell);
+ typedef enum {
+ NoneDictionaryKind = 0,
+ CachedDictionaryKind = 1,
+ UncachedDictionaryKind = 2
+ } DictionaryKind;
+ static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind);
+
+ PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
+ PropertyOffset remove(PropertyName);
+
+ void createPropertyMap(VM&, unsigned keyCount = 0);
+ void checkConsistency();
+
+ bool despecifyFunction(VM&, PropertyName);
+ void despecifyAllFunctions(VM&);
+
+ WriteBarrier<PropertyTable>& propertyTable();
+ PropertyTable* takePropertyTableOrCloneIfPinned(VM&, Structure* owner);
+ PropertyTable* copyPropertyTable(VM&, Structure* owner);
+ PropertyTable* copyPropertyTableForPinning(VM&, Structure* owner);
+ JS_EXPORT_PRIVATE void materializePropertyMap(VM&);
+ void materializePropertyMapIfNecessary(VM& vm)
+ {
+ ASSERT(structure()->classInfo() == &s_info);
+ ASSERT(checkOffsetConsistency());
+ if (!propertyTable() && previousID())
+ materializePropertyMap(vm);
+ }
+ void materializePropertyMapIfNecessaryForPinning(VM& vm)
+ {
+ ASSERT(structure()->classInfo() == &s_info);
+ checkOffsetConsistency();
+ if (!propertyTable())
+ materializePropertyMap(vm);
}
- inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
+ void setPreviousID(VM& vm, Structure* transition, Structure* structure)
{
- // Newer versions of the STL have an std::make_pair function that takes rvalue references.
- // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
- // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details.
- return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);
+ if (typeInfo().structureHasRareData())
+ rareData()->setPreviousID(vm, transition, structure);
+ else
+ m_previousOrRareData.set(vm, transition, structure);
}
- inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
+ void clearPreviousID()
{
- for (Structure* current = this; current; current = current->previousID()) {
- if (current == structureToFind)
- return true;
- }
- return false;
+ if (typeInfo().structureHasRareData())
+ rareData()->clearPreviousID();
+ else
+ m_previousOrRareData.clear();
}
- inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
- : m_structure(globalData, this, structure)
+ int transitionCount() const
{
+ // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both.
+ return numberOfSlotsForLastOffset(m_offset, m_inlineCapacity);
}
- inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
+ bool isValid(JSGlobalObject*, StructureChain* cachedPrototypeChain) const;
+ bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
+
+ void pin();
+
+ Structure* previous() const
{
-#if ENABLE(GC_VALIDATION)
- ASSERT(globalData.isInitializingObject());
- globalData.setInitializingObjectClass(0);
- if (structure)
-#endif
- m_structure.setEarlyValue(globalData, this, structure);
- // Very first set of allocations won't have a real structure.
- ASSERT(m_structure || !globalData.structureStructure);
+ ASSERT(!typeInfo().structureHasRareData());
+ return static_cast<Structure*>(m_previousOrRareData.get());
}
+ StructureRareData* rareData() const
+ {
+ ASSERT(typeInfo().structureHasRareData());
+ return static_cast<StructureRareData*>(m_previousOrRareData.get());
+ }
+
+ bool checkOffsetConsistency() const;
+
+ void allocateRareData(VM&);
+ void cloneRareDataFrom(VM&, const Structure*);
+
+ static const int s_maxTransitionLength = 64;
+
+ static const unsigned maxSpecificFunctionThrashCount = 3;
+
+ WriteBarrier<JSGlobalObject> m_globalObject;
+ WriteBarrier<Unknown> m_prototype;
+ mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
+
+ WriteBarrier<JSCell> m_previousOrRareData;
+
+ RefPtr<StringImpl> m_nameInPrevious;
+ WriteBarrier<JSCell> m_specificValueInPrevious;
+
+ const ClassInfo* m_classInfo;
+
+ StructureTransitionTable m_transitionTable;
+
+ // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
+ WriteBarrier<PropertyTable> m_propertyTableUnsafe;
+
+ mutable InlineWatchpointSet m_transitionWatchpointSet;
+
+ COMPILE_ASSERT(firstOutOfLineOffset < 256, firstOutOfLineOffset_fits);
+
+ // m_offset does not account for anonymous slots
+ PropertyOffset m_offset;
+
+ TypeInfo m_typeInfo;
+ IndexingType m_indexingType;
+
+ uint8_t m_inlineCapacity;
+ unsigned m_dictionaryKind : 2;
+ bool m_isPinnedPropertyTable : 1;
+ bool m_hasGetterSetterProperties : 1;
+ bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
+ bool m_hasNonEnumerableProperties : 1;
+ unsigned m_attributesInPrevious : 14;
+ unsigned m_specificFunctionThrashCount : 2;
+ unsigned m_preventExtensions : 1;
+ unsigned m_didTransition : 1;
+ unsigned m_staticFunctionReified;
+};
+
} // namespace JSC
#endif // Structure_h
diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp
index a1c97340e..85abcd34f 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.cpp
+++ b/Source/JavaScriptCore/runtime/StructureChain.cpp
@@ -27,6 +27,7 @@
#include "StructureChain.h"
#include "JSObject.h"
+#include "Operations.h"
#include "Structure.h"
#include <wtf/RefPtr.h>
@@ -34,8 +35,8 @@ namespace JSC {
ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0, CREATE_METHOD_TABLE(StructureChain) };
-StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure)
- : JSCell(globalData, structure)
+StructureChain::StructureChain(VM& vm, Structure* structure)
+ : JSCell(vm, structure)
{
}
diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h
index 878f606b4..e652fecc2 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.h
+++ b/Source/JavaScriptCore/runtime/StructureChain.h
@@ -46,16 +46,16 @@ namespace JSC {
public:
typedef JSCell Base;
- static StructureChain* create(JSGlobalData& globalData, Structure* head)
+ static StructureChain* create(VM& vm, Structure* head)
{
- StructureChain* chain = new (NotNull, allocateCell<StructureChain>(globalData.heap)) StructureChain(globalData, globalData.structureChainStructure.get());
- chain->finishCreation(globalData, head);
+ StructureChain* chain = new (NotNull, allocateCell<StructureChain>(vm.heap)) StructureChain(vm, vm.structureChainStructure.get());
+ chain->finishCreation(vm, head);
return chain;
}
WriteBarrier<Structure>* head() { return m_vector.get(); }
static void visitChildren(JSCell*, SlotVisitor&);
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info); }
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info); }
static ClassInfo s_info;
@@ -64,9 +64,9 @@ namespace JSC {
static void destroy(JSCell*);
protected:
- void finishCreation(JSGlobalData& globalData, Structure* head)
+ void finishCreation(VM& vm, Structure* head)
{
- Base::finishCreation(globalData);
+ Base::finishCreation(vm);
size_t size = 0;
for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
++size;
@@ -75,13 +75,13 @@ namespace JSC {
size_t i = 0;
for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
- m_vector[i++].set(globalData, this, current);
+ m_vector[i++].set(vm, this, current);
}
private:
friend class LLIntOffsetsExtractor;
- StructureChain(JSGlobalData&, Structure*);
+ StructureChain(VM&, Structure*);
OwnArrayPtr<WriteBarrier<Structure> > m_vector;
};
diff --git a/Source/JavaScriptCore/runtime/StructureInlines.h b/Source/JavaScriptCore/runtime/StructureInlines.h
new file mode 100644
index 000000000..75ca40dd7
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StructureInlines.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureInlines_h
+#define StructureInlines_h
+
+#include "PropertyMapHashTable.h"
+#include "Structure.h"
+
+namespace JSC {
+
+inline Structure* Structure::create(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
+{
+ ASSERT(vm.structureStructure);
+ ASSERT(classInfo);
+ Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
+ structure->finishCreation(vm);
+ return structure;
+}
+
+inline Structure* Structure::createStructure(VM& vm)
+{
+ ASSERT(!vm.structureStructure);
+ Structure* structure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm);
+ structure->finishCreation(vm, CreatingEarlyCell);
+ return structure;
+}
+
+inline Structure* Structure::create(VM& vm, const Structure* structure)
+{
+ ASSERT(vm.structureStructure);
+ Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
+ newStructure->finishCreation(vm);
+ return newStructure;
+}
+
+inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
+{
+ ASSERT(structure()->classInfo() == &s_info);
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
+ return invalidOffset;
+
+ PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
+ return entry ? entry->offset : invalidOffset;
+}
+
+inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
+{
+ ASSERT(structure()->classInfo() == &s_info);
+ materializePropertyMapIfNecessary(vm);
+ if (!propertyTable())
+ return invalidOffset;
+
+ PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
+ return entry ? entry->offset : invalidOffset;
+}
+
+inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+{
+ return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+}
+
+ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
+{
+ ASSERT(!m_isCheckingForDefaultMarkViolation);
+ if (!cell)
+ return;
+#if ENABLE(GC_VALIDATION)
+ validate(cell);
+#endif
+ if (Heap::testAndSetMarked(cell) || !cell->structure())
+ return;
+
+ m_visitCount++;
+
+ MARK_LOG_CHILD(*this, cell);
+
+ // Should never attempt to mark something that is zapped.
+ ASSERT(!cell->isZapped());
+
+ m_stack.append(cell);
+}
+
+inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
+{
+ for (Structure* current = this; current; current = current->previousID()) {
+ if (current == structureToFind)
+ return true;
+ }
+ return false;
+}
+
+inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
+{
+ ASSERT(!isDictionary());
+ if (!typeInfo().structureHasRareData())
+ allocateRareData(vm);
+ rareData()->setEnumerationCache(vm, this, enumerationCache);
+}
+
+inline JSPropertyNameIterator* Structure::enumerationCache()
+{
+ if (!typeInfo().structureHasRareData())
+ return 0;
+ return rareData()->enumerationCache();
+}
+
+inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
+{
+ if (isObject())
+ return m_prototype.get();
+
+ ASSERT(typeInfo().type() == StringType);
+ return globalObject->stringPrototype();
+}
+
+inline JSValue Structure::prototypeForLookup(ExecState* exec) const
+{
+ return prototypeForLookup(exec->lexicalGlobalObject());
+}
+
+inline StructureChain* Structure::prototypeChain(VM& vm, JSGlobalObject* globalObject) const
+{
+ // We cache our prototype chain so our clients can share it.
+ if (!isValid(globalObject, m_cachedPrototypeChain.get())) {
+ JSValue prototype = prototypeForLookup(globalObject);
+ m_cachedPrototypeChain.set(vm, this, StructureChain::create(vm, prototype.isNull() ? 0 : asObject(prototype)->structure()));
+ }
+ return m_cachedPrototypeChain.get();
+}
+
+inline StructureChain* Structure::prototypeChain(ExecState* exec) const
+{
+ return prototypeChain(exec->vm(), exec->lexicalGlobalObject());
+}
+
+inline bool Structure::isValid(JSGlobalObject* globalObject, StructureChain* cachedPrototypeChain) const
+{
+ if (!cachedPrototypeChain)
+ return false;
+
+ JSValue prototype = prototypeForLookup(globalObject);
+ WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
+ while (*cachedStructure && !prototype.isNull()) {
+ if (asObject(prototype)->structure() != cachedStructure->get())
+ return false;
+ ++cachedStructure;
+ prototype = asObject(prototype)->prototype();
+ }
+ return prototype.isNull() && !*cachedStructure;
+}
+
+inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
+{
+ return isValid(exec->lexicalGlobalObject(), cachedPrototypeChain);
+}
+
+inline bool Structure::putWillGrowOutOfLineStorage()
+{
+ checkOffsetConsistency();
+
+ ASSERT(outOfLineCapacity() >= outOfLineSize());
+
+ if (!propertyTable()) {
+ unsigned currentSize = numberOfOutOfLineSlotsForLastOffset(m_offset);
+ ASSERT(outOfLineCapacity() >= currentSize);
+ return currentSize == outOfLineCapacity();
+ }
+
+ ASSERT(totalStorageCapacity() >= propertyTable()->propertyStorageSize());
+ if (propertyTable()->hasDeletedOffset())
+ return false;
+
+ ASSERT(totalStorageCapacity() >= propertyTable()->size());
+ return propertyTable()->size() == totalStorageCapacity();
+}
+
+ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
+{
+ ASSERT(!globalObject() || !globalObject()->vm().heap.isBusy());
+ return m_propertyTableUnsafe;
+}
+
+ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
+{
+ PropertyTable* propertyTable = m_propertyTableUnsafe.get();
+
+ if (!propertyTable) {
+ ASSERT(!m_isPinnedPropertyTable);
+ return true;
+ }
+
+ RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
+ unsigned totalSize = propertyTable->propertyStorageSize();
+ RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
+
+ return true;
+}
+
+} // namespace JSC
+
+#endif // StructureInlines_h
+
diff --git a/Source/JavaScriptCore/runtime/StructureRareData.cpp b/Source/JavaScriptCore/runtime/StructureRareData.cpp
new file mode 100644
index 000000000..00880d32c
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StructureRareData.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureRareData.h"
+
+#include "JSString.h"
+#include "Operations.h"
+
+namespace JSC {
+
+const ClassInfo StructureRareData::s_info = { "StructureRareData", 0, 0, 0, CREATE_METHOD_TABLE(StructureRareData) };
+
+Structure* StructureRareData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info);
+}
+
+StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
+{
+ StructureRareData* rareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, previous);
+ rareData->finishCreation(vm);
+ return rareData;
+}
+
+StructureRareData* StructureRareData::clone(VM& vm, const StructureRareData* other)
+{
+ StructureRareData* newRareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, other);
+ newRareData->finishCreation(vm);
+ return newRareData;
+}
+
+StructureRareData::StructureRareData(VM& vm, Structure* previous)
+ : JSCell(vm, vm.structureRareDataStructure.get())
+{
+ if (previous)
+ m_previous.set(vm, this, previous);
+}
+
+StructureRareData::StructureRareData(VM& vm, const StructureRareData* other)
+ : JSCell(vm, other->structure())
+{
+ if (other->previousID())
+ m_previous.set(vm, this, other->previousID());
+ if (other->objectToStringValue())
+ m_objectToStringValue.set(vm, this, other->objectToStringValue());
+}
+
+void StructureRareData::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ StructureRareData* thisObject = jsCast<StructureRareData*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
+ ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+
+ JSCell::visitChildren(thisObject, visitor);
+ visitor.append(&thisObject->m_previous);
+ visitor.append(&thisObject->m_objectToStringValue);
+ visitor.append(&thisObject->m_enumerationCache);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StructureRareData.h b/Source/JavaScriptCore/runtime/StructureRareData.h
new file mode 100644
index 000000000..e5db9e5f4
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StructureRareData.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureRareData_h
+#define StructureRareData_h
+
+#include "ClassInfo.h"
+#include "JSCell.h"
+#include "JSTypeInfo.h"
+
+namespace JSC {
+
+class JSPropertyNameIterator;
+class Structure;
+
+class StructureRareData : public JSCell {
+ friend class Structure;
+public:
+ static StructureRareData* create(VM&, Structure*);
+ static StructureRareData* clone(VM&, const StructureRareData* other);
+
+ static void visitChildren(JSCell*, SlotVisitor&);
+
+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
+
+ // Returns true if this StructureRareData should also be cloned when cloning the owner Structure.
+ bool needsCloning() const { return false; }
+
+ Structure* previousID() const;
+ void setPreviousID(VM&, Structure* transition, Structure*);
+ void clearPreviousID();
+
+ JSString* objectToStringValue() const;
+ void setObjectToStringValue(VM&, const JSCell* owner, JSString* value);
+
+ JSPropertyNameIterator* enumerationCache();
+ void setEnumerationCache(VM&, const Structure* owner, JSPropertyNameIterator* value);
+
+ static JS_EXPORTDATA const ClassInfo s_info;
+
+private:
+ StructureRareData(VM&, Structure*);
+ StructureRareData(VM&, const StructureRareData*);
+
+ static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
+
+ WriteBarrier<Structure> m_previous;
+ WriteBarrier<JSString> m_objectToStringValue;
+ WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
+};
+
+} // namespace JSC
+
+#endif // StructureRareData_h
diff --git a/Source/JavaScriptCore/runtime/StructureRareDataInlines.h b/Source/JavaScriptCore/runtime/StructureRareDataInlines.h
new file mode 100644
index 000000000..20b7f8b12
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/StructureRareDataInlines.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureRareDataInlines_h
+#define StructureRareDataInlines_h
+
+#include "StructureRareData.h"
+
+namespace JSC {
+
+inline Structure* StructureRareData::previousID() const
+{
+ return m_previous.get();
+}
+
+inline void StructureRareData::setPreviousID(VM& vm, Structure* transition, Structure* structure)
+{
+ m_previous.set(vm, transition, structure);
+}
+
+inline void StructureRareData::clearPreviousID()
+{
+ m_previous.clear();
+}
+
+inline JSString* StructureRareData::objectToStringValue() const
+{
+ return m_objectToStringValue.get();
+}
+
+inline void StructureRareData::setObjectToStringValue(VM& vm, const JSCell* owner, JSString* value)
+{
+ m_objectToStringValue.set(vm, owner, value);
+}
+
+} // namespace JSC
+
+#endif // StructureRareDataInlines_h
diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
index 5291ed540..601202017 100644
--- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h
+++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
@@ -85,7 +85,7 @@ inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition
case AddIndexedAccessors:
return oldType | MayHaveIndexedAccessors;
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
return oldType;
}
}
@@ -111,21 +111,7 @@ class StructureTransitionTable {
static const bool safeToCompareToEmptyOrDeleted = true;
};
- struct WeakGCMapFinalizerCallback {
- static void* finalizerContextFor(Hash::Key)
- {
- return 0;
- }
-
- static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
- {
- return keyForWeakGCMapFinalizer(context, structure);
- }
- };
-
- typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash> TransitionMap;
-
- static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
+ typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap;
public:
StructureTransitionTable()
@@ -146,7 +132,7 @@ public:
WeakSet::deallocate(impl);
}
- inline void add(JSGlobalData&, Structure*);
+ inline void add(VM&, Structure*);
inline bool contains(StringImpl* rep, unsigned attributes) const;
inline Structure* get(StringImpl* rep, unsigned attributes) const;
@@ -191,7 +177,7 @@ private:
return 0;
}
- void setSingleTransition(JSGlobalData&, Structure* structure)
+ void setSingleTransition(VM&, Structure* structure)
{
ASSERT(isUsingSingleSlot());
if (WeakImpl* impl = this->weakImpl())
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp
index 1b7fd89c5..8c5a00b03 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp
+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp
@@ -38,7 +38,7 @@ SymbolTableEntry& SymbolTableEntry::copySlow(const SymbolTableEntry& other)
ASSERT(other.isFat());
FatEntry* newFatEntry = new FatEntry(*other.fatEntry());
freeFatEntry();
- m_bits = bitwise_cast<intptr_t>(newFatEntry) | FatFlag;
+ m_bits = bitwise_cast<intptr_t>(newFatEntry);
return *this;
}
@@ -94,7 +94,7 @@ void SymbolTableEntry::notifyWriteSlow()
SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow()
{
FatEntry* entry = new FatEntry(m_bits);
- m_bits = bitwise_cast<intptr_t>(entry) | FatFlag;
+ m_bits = bitwise_cast<intptr_t>(entry);
return entry;
}
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index 87d1c8be5..49a00dd39 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -31,375 +31,374 @@
#include "JSObject.h"
#include "Watchpoint.h"
-#include <wtf/AlwaysInline.h>
#include <wtf/HashTraits.h>
#include <wtf/text/StringImpl.h>
namespace JSC {
- class Watchpoint;
- class WatchpointSet;
+class Watchpoint;
+class WatchpointSet;
- struct SlowArgument {
- enum Status {
- Normal = 0,
- Captured = 1,
- Deleted = 2
- };
-
- SlowArgument()
- : status(Normal)
- , index(0)
- {
- }
-
- Status status;
- int index; // If status is 'Deleted', index is bogus.
+struct SlowArgument {
+ enum Status {
+ Normal = 0,
+ Captured = 1,
+ Deleted = 2
};
- static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
-
- // The bit twiddling in this class assumes that every register index is a
- // reasonably small positive or negative number, and therefore has its high
- // four bits all set or all unset.
-
- // In addition to implementing semantics-mandated variable attributes and
- // implementation-mandated variable indexing, this class also implements
- // watchpoints to be used for JIT optimizations. Because watchpoints are
- // meant to be relatively rare, this class optimizes heavily for the case
- // that they are not being used. To that end, this class uses the thin-fat
- // idiom: either it is thin, in which case it contains an in-place encoded
- // word that consists of attributes, the index, and a bit saying that it is
- // thin; or it is fat, in which case it contains a pointer to a malloc'd
- // data structure and a bit saying that it is fat. The malloc'd data
- // structure will be malloced a second time upon copy, to preserve the
- // property that in-place edits to SymbolTableEntry do not manifest in any
- // copies. However, the malloc'd FatEntry data structure contains a ref-
- // counted pointer to a shared WatchpointSet. Thus, in-place edits of the
- // WatchpointSet will manifest in all copies. Here's a picture:
- //
- // SymbolTableEntry --> FatEntry --> WatchpointSet
- //
- // If you make a copy of a SymbolTableEntry, you will have:
- //
- // original: SymbolTableEntry --> FatEntry --> WatchpointSet
- // copy: SymbolTableEntry --> FatEntry -----^
-
- struct SymbolTableEntry {
- // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling
- // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(),
- // and (2) you are in a hot path where you need to minimize the number of times
- // that you branch on isFat() when getting the bits().
- class Fast {
- public:
- Fast()
- : m_bits(0)
- {
- }
-
- ALWAYS_INLINE Fast(const SymbolTableEntry& entry)
- : m_bits(entry.bits())
- {
- }
-
- bool isNull() const
- {
- return !m_bits;
- }
-
- int getIndex() const
- {
- return static_cast<int>(m_bits >> FlagBits);
- }
-
- bool isReadOnly() const
- {
- return m_bits & ReadOnlyFlag;
- }
-
- unsigned getAttributes() const
- {
- unsigned attributes = 0;
- if (m_bits & ReadOnlyFlag)
- attributes |= ReadOnly;
- if (m_bits & DontEnumFlag)
- attributes |= DontEnum;
- return attributes;
- }
-
- bool isFat() const
- {
- return m_bits & FatFlag;
- }
-
- private:
- friend struct SymbolTableEntry;
- intptr_t m_bits;
- };
-
- SymbolTableEntry()
- : m_bits(0)
- {
- }
-
- SymbolTableEntry(int index)
- : m_bits(0)
- {
- ASSERT(isValidIndex(index));
- pack(index, false, false);
- }
-
- SymbolTableEntry(int index, unsigned attributes)
- : m_bits(0)
- {
- ASSERT(isValidIndex(index));
- pack(index, attributes & ReadOnly, attributes & DontEnum);
- }
-
- ~SymbolTableEntry()
- {
- freeFatEntry();
- }
-
- SymbolTableEntry(const SymbolTableEntry& other)
- : m_bits(0)
+ SlowArgument()
+ : status(Normal)
+ , index(0)
+ {
+ }
+
+ Status status;
+ int index; // If status is 'Deleted', index is bogus.
+};
+
+static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); }
+
+// The bit twiddling in this class assumes that every register index is a
+// reasonably small positive or negative number, and therefore has its high
+// four bits all set or all unset.
+
+// In addition to implementing semantics-mandated variable attributes and
+// implementation-mandated variable indexing, this class also implements
+// watchpoints to be used for JIT optimizations. Because watchpoints are
+// meant to be relatively rare, this class optimizes heavily for the case
+// that they are not being used. To that end, this class uses the thin-fat
+// idiom: either it is thin, in which case it contains an in-place encoded
+// word that consists of attributes, the index, and a bit saying that it is
+// thin; or it is fat, in which case it contains a pointer to a malloc'd
+// data structure and a bit saying that it is fat. The malloc'd data
+// structure will be malloced a second time upon copy, to preserve the
+// property that in-place edits to SymbolTableEntry do not manifest in any
+// copies. However, the malloc'd FatEntry data structure contains a ref-
+// counted pointer to a shared WatchpointSet. Thus, in-place edits of the
+// WatchpointSet will manifest in all copies. Here's a picture:
+//
+// SymbolTableEntry --> FatEntry --> WatchpointSet
+//
+// If you make a copy of a SymbolTableEntry, you will have:
+//
+// original: SymbolTableEntry --> FatEntry --> WatchpointSet
+// copy: SymbolTableEntry --> FatEntry -----^
+
+struct SymbolTableEntry {
+ // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling
+ // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(),
+ // and (2) you are in a hot path where you need to minimize the number of times
+ // that you branch on isFat() when getting the bits().
+ class Fast {
+ public:
+ Fast()
+ : m_bits(SlimFlag)
{
- *this = other;
}
- SymbolTableEntry& operator=(const SymbolTableEntry& other)
+ ALWAYS_INLINE Fast(const SymbolTableEntry& entry)
+ : m_bits(entry.bits())
{
- if (UNLIKELY(other.isFat()))
- return copySlow(other);
- freeFatEntry();
- m_bits = other.m_bits;
- return *this;
}
-
+
bool isNull() const
{
- return !bits();
+ return !(m_bits & ~SlimFlag);
}
int getIndex() const
{
- return static_cast<int>(bits() >> FlagBits);
- }
-
- ALWAYS_INLINE Fast getFast() const
- {
- return Fast(*this);
+ return static_cast<int>(m_bits >> FlagBits);
}
-
- ALWAYS_INLINE Fast getFast(bool& wasFat) const
+
+ bool isReadOnly() const
{
- Fast result;
- wasFat = isFat();
- if (wasFat)
- result.m_bits = fatEntry()->m_bits;
- else
- result.m_bits = m_bits;
- return result;
+ return m_bits & ReadOnlyFlag;
}
unsigned getAttributes() const
{
- return getFast().getAttributes();
- }
-
- void setAttributes(unsigned attributes)
- {
- pack(getIndex(), attributes & ReadOnly, attributes & DontEnum);
+ unsigned attributes = 0;
+ if (m_bits & ReadOnlyFlag)
+ attributes |= ReadOnly;
+ if (m_bits & DontEnumFlag)
+ attributes |= DontEnum;
+ return attributes;
}
- bool isReadOnly() const
- {
- return bits() & ReadOnlyFlag;
- }
-
- bool couldBeWatched();
-
- // Notify an opportunity to create a watchpoint for a variable. This is
- // idempotent and fail-silent. It is idempotent in the sense that if
- // a watchpoint set had already been created, then another one will not
- // be created. Hence two calls to this method have the same effect as
- // one call. It is also fail-silent, in the sense that if a watchpoint
- // set had been created and had already been invalidated, then this will
- // just return. This means that couldBeWatched() may return false even
- // immediately after a call to attemptToWatch().
- void attemptToWatch();
-
- bool* addressOfIsWatched();
-
- void addWatchpoint(Watchpoint*);
-
- WatchpointSet* watchpointSet()
- {
- return fatEntry()->m_watchpoints.get();
- }
-
- ALWAYS_INLINE void notifyWrite()
- {
- if (LIKELY(!isFat()))
- return;
- notifyWriteSlow();
- }
-
- private:
- static const intptr_t FatFlag = 0x1;
- static const intptr_t ReadOnlyFlag = 0x2;
- static const intptr_t DontEnumFlag = 0x4;
- static const intptr_t NotNullFlag = 0x8;
- static const intptr_t FlagBits = 4;
-
- class FatEntry {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- FatEntry(intptr_t bits)
- : m_bits(bits | FatFlag)
- {
- }
-
- intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat.
-
- RefPtr<WatchpointSet> m_watchpoints;
- };
-
- SymbolTableEntry& copySlow(const SymbolTableEntry&);
- JS_EXPORT_PRIVATE void notifyWriteSlow();
-
bool isFat() const
{
- return m_bits & FatFlag;
- }
-
- const FatEntry* fatEntry() const
- {
- ASSERT(isFat());
- return bitwise_cast<const FatEntry*>(m_bits & ~FatFlag);
- }
-
- FatEntry* fatEntry()
- {
- ASSERT(isFat());
- return bitwise_cast<FatEntry*>(m_bits & ~FatFlag);
- }
-
- FatEntry* inflate()
- {
- if (LIKELY(isFat()))
- return fatEntry();
- return inflateSlow();
- }
-
- FatEntry* inflateSlow();
-
- ALWAYS_INLINE intptr_t bits() const
- {
- if (isFat())
- return fatEntry()->m_bits;
- return m_bits;
- }
-
- ALWAYS_INLINE intptr_t& bits()
- {
- if (isFat())
- return fatEntry()->m_bits;
- return m_bits;
- }
-
- void freeFatEntry()
- {
- if (LIKELY(!isFat()))
- return;
- freeFatEntrySlow();
- }
-
- void freeFatEntrySlow();
-
- void pack(int index, bool readOnly, bool dontEnum)
- {
- intptr_t& bitsRef = bits();
- bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag;
- if (readOnly)
- bitsRef |= ReadOnlyFlag;
- if (dontEnum)
- bitsRef |= DontEnumFlag;
+ return !(m_bits & SlimFlag);
}
- bool isValidIndex(int index)
- {
- return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index);
- }
-
+ private:
+ friend struct SymbolTableEntry;
intptr_t m_bits;
};
- struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
- static const bool emptyValueIsZero = true;
- static const bool needsDestruction = true;
- };
-
- typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable;
-
- class SharedSymbolTable : public JSCell, public SymbolTable {
+ SymbolTableEntry()
+ : m_bits(SlimFlag)
+ {
+ }
+
+ SymbolTableEntry(int index)
+ : m_bits(SlimFlag)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, false, false);
+ }
+
+ SymbolTableEntry(int index, unsigned attributes)
+ : m_bits(SlimFlag)
+ {
+ ASSERT(isValidIndex(index));
+ pack(index, attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ ~SymbolTableEntry()
+ {
+ freeFatEntry();
+ }
+
+ SymbolTableEntry(const SymbolTableEntry& other)
+ : m_bits(SlimFlag)
+ {
+ *this = other;
+ }
+
+ SymbolTableEntry& operator=(const SymbolTableEntry& other)
+ {
+ if (UNLIKELY(other.isFat()))
+ return copySlow(other);
+ freeFatEntry();
+ m_bits = other.m_bits;
+ return *this;
+ }
+
+ bool isNull() const
+ {
+ return !(bits() & ~SlimFlag);
+ }
+
+ int getIndex() const
+ {
+ return static_cast<int>(bits() >> FlagBits);
+ }
+
+ ALWAYS_INLINE Fast getFast() const
+ {
+ return Fast(*this);
+ }
+
+ ALWAYS_INLINE Fast getFast(bool& wasFat) const
+ {
+ Fast result;
+ wasFat = isFat();
+ if (wasFat)
+ result.m_bits = fatEntry()->m_bits | SlimFlag;
+ else
+ result.m_bits = m_bits;
+ return result;
+ }
+
+ unsigned getAttributes() const
+ {
+ return getFast().getAttributes();
+ }
+
+ void setAttributes(unsigned attributes)
+ {
+ pack(getIndex(), attributes & ReadOnly, attributes & DontEnum);
+ }
+
+ bool isReadOnly() const
+ {
+ return bits() & ReadOnlyFlag;
+ }
+
+ bool couldBeWatched();
+
+ // Notify an opportunity to create a watchpoint for a variable. This is
+ // idempotent and fail-silent. It is idempotent in the sense that if
+ // a watchpoint set had already been created, then another one will not
+ // be created. Hence two calls to this method have the same effect as
+ // one call. It is also fail-silent, in the sense that if a watchpoint
+ // set had been created and had already been invalidated, then this will
+ // just return. This means that couldBeWatched() may return false even
+ // immediately after a call to attemptToWatch().
+ void attemptToWatch();
+
+ bool* addressOfIsWatched();
+
+ void addWatchpoint(Watchpoint*);
+
+ WatchpointSet* watchpointSet()
+ {
+ return fatEntry()->m_watchpoints.get();
+ }
+
+ ALWAYS_INLINE void notifyWrite()
+ {
+ if (LIKELY(!isFat()))
+ return;
+ notifyWriteSlow();
+ }
+
+private:
+ static const intptr_t SlimFlag = 0x1;
+ static const intptr_t ReadOnlyFlag = 0x2;
+ static const intptr_t DontEnumFlag = 0x4;
+ static const intptr_t NotNullFlag = 0x8;
+ static const intptr_t FlagBits = 4;
+
+ class FatEntry {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- typedef JSCell Base;
-
- static SharedSymbolTable* create(JSGlobalData& globalData)
- {
- SharedSymbolTable* sharedSymbolTable = new (NotNull, allocateCell<SharedSymbolTable>(globalData.heap)) SharedSymbolTable(globalData);
- sharedSymbolTable->finishCreation(globalData);
- return sharedSymbolTable;
- }
- static const bool needsDestruction = true;
- static const bool hasImmortalStructure = true;
- static void destroy(JSCell*);
-
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(LeafType, StructureFlags), &s_info);
- }
-
- bool usesNonStrictEval() { return m_usesNonStrictEval; }
- void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
-
- int captureStart() { return m_captureStart; }
- void setCaptureStart(int captureStart) { m_captureStart = captureStart; }
-
- int captureEnd() { return m_captureEnd; }
- void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; }
-
- int captureCount() { return m_captureEnd - m_captureStart; }
-
- int parameterCount() { return m_parameterCountIncludingThis - 1; }
- int parameterCountIncludingThis() { return m_parameterCountIncludingThis; }
- void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; }
-
- // 0 if we don't capture any arguments; parameterCount() in length if we do.
- const SlowArgument* slowArguments() { return m_slowArguments.get(); }
- void setSlowArguments(PassOwnArrayPtr<SlowArgument> slowArguments) { m_slowArguments = slowArguments; }
-
- static JS_EXPORTDATA const ClassInfo s_info;
-
- private:
- SharedSymbolTable(JSGlobalData& globalData)
- : JSCell(globalData, globalData.sharedSymbolTableStructure.get())
- , m_parameterCountIncludingThis(0)
- , m_usesNonStrictEval(false)
- , m_captureStart(0)
- , m_captureEnd(0)
+ FatEntry(intptr_t bits)
+ : m_bits(bits & ~SlimFlag)
{
}
-
- int m_parameterCountIncludingThis;
- bool m_usesNonStrictEval;
-
- int m_captureStart;
- int m_captureEnd;
-
- OwnArrayPtr<SlowArgument> m_slowArguments;
+
+ intptr_t m_bits; // always has FatFlag set and exactly matches what the bits would have been if this wasn't fat.
+
+ RefPtr<WatchpointSet> m_watchpoints;
};
+
+ SymbolTableEntry& copySlow(const SymbolTableEntry&);
+ JS_EXPORT_PRIVATE void notifyWriteSlow();
+
+ bool isFat() const
+ {
+ return !(m_bits & SlimFlag);
+ }
+
+ const FatEntry* fatEntry() const
+ {
+ ASSERT(isFat());
+ return bitwise_cast<const FatEntry*>(m_bits);
+ }
+
+ FatEntry* fatEntry()
+ {
+ ASSERT(isFat());
+ return bitwise_cast<FatEntry*>(m_bits);
+ }
+
+ FatEntry* inflate()
+ {
+ if (LIKELY(isFat()))
+ return fatEntry();
+ return inflateSlow();
+ }
+
+ FatEntry* inflateSlow();
+
+ ALWAYS_INLINE intptr_t bits() const
+ {
+ if (isFat())
+ return fatEntry()->m_bits;
+ return m_bits;
+ }
+
+ ALWAYS_INLINE intptr_t& bits()
+ {
+ if (isFat())
+ return fatEntry()->m_bits;
+ return m_bits;
+ }
+
+ void freeFatEntry()
+ {
+ if (LIKELY(!isFat()))
+ return;
+ freeFatEntrySlow();
+ }
+
+ JS_EXPORT_PRIVATE void freeFatEntrySlow();
+
+ void pack(int index, bool readOnly, bool dontEnum)
+ {
+ ASSERT(!isFat());
+ intptr_t& bitsRef = bits();
+ bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag | SlimFlag;
+ if (readOnly)
+ bitsRef |= ReadOnlyFlag;
+ if (dontEnum)
+ bitsRef |= DontEnumFlag;
+ }
+
+ bool isValidIndex(int index)
+ {
+ return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index);
+ }
+
+ intptr_t m_bits;
+};
+
+struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
+ static const bool needsDestruction = true;
+};
+
+typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable;
+
+class SharedSymbolTable : public JSCell, public SymbolTable {
+public:
+ typedef JSCell Base;
+
+ static SharedSymbolTable* create(VM& vm)
+ {
+ SharedSymbolTable* sharedSymbolTable = new (NotNull, allocateCell<SharedSymbolTable>(vm.heap)) SharedSymbolTable(vm);
+ sharedSymbolTable->finishCreation(vm);
+ return sharedSymbolTable;
+ }
+ static const bool needsDestruction = true;
+ static const bool hasImmortalStructure = true;
+ static void destroy(JSCell*);
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(LeafType, StructureFlags), &s_info);
+ }
+
+ bool usesNonStrictEval() { return m_usesNonStrictEval; }
+ void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; }
+
+ int captureStart() { return m_captureStart; }
+ void setCaptureStart(int captureStart) { m_captureStart = captureStart; }
+
+ int captureEnd() { return m_captureEnd; }
+ void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; }
+
+ int captureCount() { return m_captureEnd - m_captureStart; }
+
+ int parameterCount() { return m_parameterCountIncludingThis - 1; }
+ int parameterCountIncludingThis() { return m_parameterCountIncludingThis; }
+ void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; }
+
+ // 0 if we don't capture any arguments; parameterCount() in length if we do.
+ const SlowArgument* slowArguments() { return m_slowArguments.get(); }
+ void setSlowArguments(PassOwnArrayPtr<SlowArgument> slowArguments) { m_slowArguments = slowArguments; }
+
+ static JS_EXPORTDATA const ClassInfo s_info;
+
+private:
+ SharedSymbolTable(VM& vm)
+ : JSCell(vm, vm.sharedSymbolTableStructure.get())
+ , m_parameterCountIncludingThis(0)
+ , m_usesNonStrictEval(false)
+ , m_captureStart(0)
+ , m_captureEnd(0)
+ {
+ }
+
+ int m_parameterCountIncludingThis;
+ bool m_usesNonStrictEval;
+
+ int m_captureStart;
+ int m_captureEnd;
+
+ OwnArrayPtr<SlowArgument> m_slowArguments;
+};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Terminator.h b/Source/JavaScriptCore/runtime/Terminator.h
deleted file mode 100644
index 6b0f2366f..000000000
--- a/Source/JavaScriptCore/runtime/Terminator.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Google Inc. ("Google") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Terminator_h
-#define Terminator_h
-
-namespace JSC {
-
-class Terminator {
-public:
- Terminator() : m_shouldTerminate(false) { }
-
- void terminateSoon() { m_shouldTerminate = true; }
- bool shouldTerminate() const { return m_shouldTerminate; }
-
-private:
- bool m_shouldTerminate;
-};
-
-} // namespace JSC
-
-#endif // Terminator_h
diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp
deleted file mode 100644
index 56d6d4b71..000000000
--- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "TimeoutChecker.h"
-
-#include "CallFrame.h"
-#include "JSGlobalObject.h"
-
-#if OS(DARWIN)
-#include <mach/mach.h>
-#elif OS(WINDOWS)
-#include <windows.h>
-#else
-#include <wtf/CurrentTime.h>
-#endif
-
-using namespace std;
-
-namespace JSC {
-
-// Number of ticks before the first timeout check is done.
-static const int ticksUntilFirstCheck = 1024;
-
-// Number of milliseconds between each timeout check.
-static const int intervalBetweenChecks = 1000;
-
-// Returns the time the current thread has spent executing, in milliseconds.
-static inline unsigned getCPUTime()
-{
-#if OS(DARWIN)
- mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
- thread_basic_info_data_t info;
-
- // Get thread information
- mach_port_t threadPort = mach_thread_self();
- thread_info(threadPort, THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
- mach_port_deallocate(mach_task_self(), threadPort);
-
- unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
- time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
-
- return time;
-#elif OS(WINDOWS)
- union {
- FILETIME fileTime;
- unsigned long long fileTimeAsLong;
- } userTime, kernelTime;
-
- // GetThreadTimes won't accept NULL arguments so we pass these even though
- // they're not used.
- FILETIME creationTime, exitTime;
-
- GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
-
- return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
-#elif OS(QNX)
- struct timespec time;
- if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time))
- CRASH();
- return time.tv_sec * 1000.0 + time.tv_nsec / 1.0e6;
-#else
- // FIXME: We should return the time the current thread has spent executing.
-
- // use a relative time from first call in order to avoid an overflow
- static double firstTime = currentTime();
- return static_cast<unsigned> ((currentTime() - firstTime) * 1000);
-#endif
-}
-
-TimeoutChecker::TimeoutChecker()
- : m_timeoutInterval(0)
- , m_startCount(0)
-{
- reset();
-}
-
-void TimeoutChecker::reset()
-{
- m_ticksUntilNextCheck = ticksUntilFirstCheck;
- m_timeAtLastCheck = 0;
- m_timeExecuting = 0;
-}
-
-bool TimeoutChecker::didTimeOut(ExecState* exec)
-{
- unsigned currentTime = getCPUTime();
-
- if (!m_timeAtLastCheck) {
- // Suspicious amount of looping in a script -- start timing it
- m_timeAtLastCheck = currentTime;
- return false;
- }
-
- unsigned timeDiff = currentTime - m_timeAtLastCheck;
-
- if (timeDiff == 0)
- timeDiff = 1;
-
- m_timeExecuting += timeDiff;
- m_timeAtLastCheck = currentTime;
-
- // Adjust the tick threshold so we get the next checkTimeout call in the
- // interval specified in intervalBetweenChecks.
- m_ticksUntilNextCheck = static_cast<unsigned>((static_cast<float>(intervalBetweenChecks) / timeDiff) * m_ticksUntilNextCheck);
- // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
- // preferred script check time interval.
- if (m_ticksUntilNextCheck == 0)
- m_ticksUntilNextCheck = ticksUntilFirstCheck;
-
- if (m_timeoutInterval && m_timeExecuting > m_timeoutInterval) {
- if (exec->dynamicGlobalObject()->globalObjectMethodTable()->shouldInterruptScript(exec->dynamicGlobalObject()))
- return true;
-
- reset();
- }
-
- return false;
-}
-
-} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.h b/Source/JavaScriptCore/runtime/TimeoutChecker.h
deleted file mode 100644
index 89d6158cc..000000000
--- a/Source/JavaScriptCore/runtime/TimeoutChecker.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TimeoutChecker_h
-#define TimeoutChecker_h
-
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
- class ExecState;
-
- class TimeoutChecker {
- public:
- TimeoutChecker();
-
- void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; }
- unsigned timeoutInterval() const { return m_timeoutInterval; }
-
- unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; }
-
- void start()
- {
- if (!m_startCount)
- reset();
- ++m_startCount;
- }
-
- void stop()
- {
- ASSERT(m_startCount);
- --m_startCount;
- }
-
- JS_EXPORT_PRIVATE void reset();
-
- JS_EXPORT_PRIVATE bool didTimeOut(ExecState*);
-
- private:
- unsigned m_timeoutInterval;
- unsigned m_timeAtLastCheck;
- unsigned m_timeExecuting;
- unsigned m_startCount;
- unsigned m_ticksUntilNextCheck;
- };
-
-} // namespace JSC
-
-#endif // TimeoutChecker_h
diff --git a/Source/JavaScriptCore/runtime/Uint16WithFraction.h b/Source/JavaScriptCore/runtime/Uint16WithFraction.h
index 0e5c5f91c..9a30100eb 100644
--- a/Source/JavaScriptCore/runtime/Uint16WithFraction.h
+++ b/Source/JavaScriptCore/runtime/Uint16WithFraction.h
@@ -41,7 +41,7 @@ class Uint16WithFraction {
public:
explicit Uint16WithFraction(double number, uint16_t divideByExponent = 0)
{
- ASSERT(number && isfinite(number) && !signbit(number));
+ ASSERT(number && std::isfinite(number) && !std::signbit(number));
// Check for values out of uint16_t range.
if (number >= oneGreaterThanMaxUInt16) {
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/VM.cpp
index 74429c7a7..3ca134ba2 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/VM.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2011, 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
@@ -27,11 +27,12 @@
*/
#include "config.h"
-#include "JSGlobalData.h"
+#include "VM.h"
#include "ArgList.h"
#include "CodeCache.h"
#include "CommonIdentifiers.h"
+#include "DFGLongLivedState.h"
#include "DebuggerActivation.h"
#include "FunctionConstructor.h"
#include "GCActivityCallback.h"
@@ -43,7 +44,6 @@
#include "JSActivation.h"
#include "JSAPIValueWrapper.h"
#include "JSArray.h"
-#include "JSClassRef.h"
#include "JSFunction.h"
#include "JSLock.h"
#include "JSNameScope.h"
@@ -56,10 +56,13 @@
#include "ParserArena.h"
#include "RegExpCache.h"
#include "RegExpObject.h"
+#include "SourceProviderCache.h"
#include "StrictEvalActivation.h"
#include "StrongInlines.h"
#include "UnlinkedCodeBlock.h"
+#include <wtf/ProcessID.h>
#include <wtf/RetainPtr.h>
+#include <wtf/StringPrintStream.h>
#include <wtf/Threading.h>
#include <wtf/WTFThreadData.h>
@@ -91,12 +94,10 @@ extern const HashTable mathTable;
extern const HashTable numberConstructorTable;
extern const HashTable numberPrototypeTable;
JS_EXPORTDATA extern const HashTable objectConstructorTable;
-extern const HashTable objectPrototypeTable;
extern const HashTable privateNamePrototypeTable;
extern const HashTable regExpTable;
extern const HashTable regExpConstructorTable;
extern const HashTable regExpPrototypeTable;
-extern const HashTable stringTable;
extern const HashTable stringConstructorTable;
// Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
@@ -113,12 +114,12 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator)
#if COMPILER(GCC) && !COMPILER(CLANG)
// FIXME: remove this once the EWS have been upgraded to LLVM.
// Work around a bug of GCC with strict-aliasing.
- RetainPtr<CFStringRef> canUseJITKeyRetain(AdoptCF, CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
+ RetainPtr<CFStringRef> canUseJITKeyRetain = adoptCF(CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
CFStringRef canUseJITKey = canUseJITKeyRetain.get();
#else
CFStringRef canUseJITKey = CFSTR("JavaScriptCoreUseJIT");
#endif // COMPILER(GCC) && !COMPILER(CLANG)
- RetainPtr<CFBooleanRef> canUseJIT(AdoptCF, (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication));
+ RetainPtr<CFTypeRef> canUseJIT = adoptCF(CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication));
if (canUseJIT)
return kCFBooleanTrue == canUseJIT.get();
#endif
@@ -132,13 +133,13 @@ static bool enableAssembler(ExecutableAllocator& executableAllocator)
}
#endif // ENABLE(!ASSEMBLER)
-JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
- :
+VM::VM(VMType vmType, HeapType heapType)
+ : m_apiLock(adoptRef(new JSLock(this)))
#if ENABLE(ASSEMBLER)
- executableAllocator(*this),
+ , executableAllocator(*this)
#endif
- heap(this, heapType)
- , globalDataType(globalDataType)
+ , heap(this, heapType)
+ , vmType(vmType)
, clientData(0)
, topCallFrame(CallFrame::noCaller())
, arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
@@ -153,14 +154,12 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
, numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
, objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
- , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
, privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable))
, regExpTable(fastNew<HashTable>(JSC::regExpTable))
, regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
, regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
- , stringTable(fastNew<HashTable>(JSC::stringTable))
, stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
- , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
+ , identifierTable(vmType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
, propertyNames(new CommonIdentifiers(this))
, emptyList(new MarkedArgumentBuffer)
, parserArena(adoptPtr(new ParserArena))
@@ -172,7 +171,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, sizeOfLastScratchBuffer(0)
#endif
, dynamicGlobalObject(0)
- , cachedUTCOffset(QNaN)
, m_enabledProfiler(0)
, m_regExpCache(new RegExpCache(this))
#if ENABLE(REGEXP_TRACING)
@@ -181,10 +179,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
#ifndef NDEBUG
, exclusiveThread(0)
#endif
-#if CPU(X86) && ENABLE(JIT)
- , m_timeoutCount(512)
-#endif
- , m_newStringsSinceLastHashConst(0)
+ , m_newStringsSinceLastHashCons(0)
#if ENABLE(ASSEMBLER)
, m_canUseAssembler(enableAssembler(executableAllocator))
#endif
@@ -198,7 +193,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, m_initializingObjectClass(0)
#endif
, m_inDefineOwnProperty(false)
- , m_codeCache(CodeCache::create())
+ , m_codeCache(CodeCache::create(CodeCache::GlobalCodeCache))
{
interpreter = new Interpreter(*this);
@@ -206,8 +201,8 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
JSLockHolder lock(this);
IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
structureStructure.set(*this, Structure::createStructure(*this));
+ structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
- interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
@@ -229,11 +224,14 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
+ propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
+ smallStrings.initializeCommonStrings(*this);
wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
#if ENABLE(JIT)
- jitStubs = adoptPtr(new JITThunks(this));
+ jitStubs = adoptPtr(new JITThunks());
+ performPlatformSpecificJITAssertions(this);
#endif
interpreter->initialize(this->canUseJIT());
@@ -243,14 +241,36 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
#endif
heap.notifyIsSafeToCollect();
-
+
LLInt::Data::performAssertions(*this);
+
+ if (Options::enableProfiler()) {
+ m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this));
+
+ StringPrintStream pathOut;
+#if !OS(WINCE)
+ const char* profilerPath = getenv("JSC_PROFILER_PATH");
+ if (profilerPath)
+ pathOut.print(profilerPath, "/");
+#endif
+ pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json");
+ m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data());
+ }
+
+#if ENABLE(DFG_JIT)
+ if (canUseJIT())
+ m_dfgState = adoptPtr(new DFG::LongLivedState());
+#endif
}
-JSGlobalData::~JSGlobalData()
+VM::~VM()
{
- ASSERT(!m_apiLock.currentThreadIsHoldingLock());
- heap.didStartVMShutdown();
+ // Clear this first to ensure that nobody tries to remove themselves from it.
+ m_perBytecodeProfiler.clear();
+
+ ASSERT(m_apiLock->currentThreadIsHoldingLock());
+ m_apiLock->willDestroyVM(this);
+ heap.lastChanceToFinalize();
delete interpreter;
#ifndef NDEBUG
@@ -269,12 +289,10 @@ JSGlobalData::~JSGlobalData()
numberConstructorTable->deleteTable();
numberPrototypeTable->deleteTable();
objectConstructorTable->deleteTable();
- objectPrototypeTable->deleteTable();
privateNamePrototypeTable->deleteTable();
regExpTable->deleteTable();
regExpConstructorTable->deleteTable();
regExpPrototypeTable->deleteTable();
- stringTable->deleteTable();
stringConstructorTable->deleteTable();
fastDelete(const_cast<HashTable*>(arrayConstructorTable));
@@ -289,20 +307,16 @@ JSGlobalData::~JSGlobalData()
fastDelete(const_cast<HashTable*>(numberConstructorTable));
fastDelete(const_cast<HashTable*>(numberPrototypeTable));
fastDelete(const_cast<HashTable*>(objectConstructorTable));
- fastDelete(const_cast<HashTable*>(objectPrototypeTable));
fastDelete(const_cast<HashTable*>(privateNamePrototypeTable));
fastDelete(const_cast<HashTable*>(regExpTable));
fastDelete(const_cast<HashTable*>(regExpConstructorTable));
fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
- fastDelete(const_cast<HashTable*>(stringTable));
fastDelete(const_cast<HashTable*>(stringConstructorTable));
- opaqueJSClassData.clear();
-
delete emptyList;
delete propertyNames;
- if (globalDataType != Default)
+ if (vmType != Default)
deleteIdentifierTable(identifierTable);
delete clientData;
@@ -317,40 +331,40 @@ JSGlobalData::~JSGlobalData()
#endif
}
-PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(HeapType heapType)
+PassRefPtr<VM> VM::createContextGroup(HeapType heapType)
{
- return adoptRef(new JSGlobalData(APIContextGroup, heapType));
+ return adoptRef(new VM(APIContextGroup, heapType));
}
-PassRefPtr<JSGlobalData> JSGlobalData::create(HeapType heapType)
+PassRefPtr<VM> VM::create(HeapType heapType)
{
- return adoptRef(new JSGlobalData(Default, heapType));
+ return adoptRef(new VM(Default, heapType));
}
-PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(HeapType heapType)
+PassRefPtr<VM> VM::createLeaked(HeapType heapType)
{
return create(heapType);
}
-bool JSGlobalData::sharedInstanceExists()
+bool VM::sharedInstanceExists()
{
return sharedInstanceInternal();
}
-JSGlobalData& JSGlobalData::sharedInstance()
+VM& VM::sharedInstance()
{
GlobalJSLock globalLock;
- JSGlobalData*& instance = sharedInstanceInternal();
+ VM*& instance = sharedInstanceInternal();
if (!instance) {
- instance = adoptRef(new JSGlobalData(APIShared, SmallHeap)).leakRef();
+ instance = adoptRef(new VM(APIShared, SmallHeap)).leakRef();
instance->makeUsableFromMultipleThreads();
}
return *instance;
}
-JSGlobalData*& JSGlobalData::sharedInstanceInternal()
+VM*& VM::sharedInstanceInternal()
{
- static JSGlobalData* sharedInstance;
+ static VM* sharedInstance;
return sharedInstance;
}
@@ -380,52 +394,60 @@ static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
return expThunkGenerator;
case LogIntrinsic:
return logThunkGenerator;
+ case IMulIntrinsic:
+ return imulThunkGenerator;
default:
return 0;
}
}
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
+NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor)
{
return jitStubs->hostFunctionStub(this, function, constructor);
}
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic)
+NativeExecutable* VM::getHostFunction(NativeFunction function, Intrinsic intrinsic)
{
ASSERT(canUseJIT());
return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic);
}
#else // !ENABLE(JIT)
-NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
+NativeExecutable* VM::getHostFunction(NativeFunction function, NativeFunction constructor)
{
return NativeExecutable::create(*this, function, constructor);
}
#endif // !ENABLE(JIT)
-JSGlobalData::ClientData::~ClientData()
+VM::ClientData::~ClientData()
{
}
-void JSGlobalData::resetDateCache()
+void VM::resetDateCache()
{
- cachedUTCOffset = QNaN;
- dstOffsetCache.reset();
+ localTimeOffsetCache.reset();
cachedDateString = String();
cachedDateStringValue = QNaN;
dateInstanceCache.reset();
}
-void JSGlobalData::startSampling()
+void VM::startSampling()
{
interpreter->startSampling();
}
-void JSGlobalData::stopSampling()
+void VM::stopSampling()
{
interpreter->stopSampling();
}
-void JSGlobalData::dumpSampleData(ExecState* exec)
+void VM::discardAllCode()
+{
+ m_codeCache->clear();
+ heap.deleteAllCompiledCode();
+ heap.reportAbandonedObjectGraph();
+}
+
+void VM::dumpSampleData(ExecState* exec)
{
interpreter->dumpSampleData(exec);
#if ENABLE(ASSEMBLER)
@@ -433,6 +455,19 @@ void JSGlobalData::dumpSampleData(ExecState* exec)
#endif
}
+SourceProviderCache* VM::addSourceProviderCache(SourceProvider* sourceProvider)
+{
+ SourceProviderCacheMap::AddResult addResult = sourceProviderCacheMap.add(sourceProvider, 0);
+ if (addResult.isNewEntry)
+ addResult.iterator->value = adoptRef(new SourceProviderCache);
+ return addResult.iterator->value.get();
+}
+
+void VM::clearSourceProviderCaches()
+{
+ sourceProviderCacheMap.clear();
+}
+
struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
HashSet<FunctionExecutable*> currentlyExecutingFunctions;
void operator()(JSCell* cell)
@@ -446,11 +481,12 @@ struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
}
};
-void JSGlobalData::releaseExecutableMemory()
+void VM::releaseExecutableMemory()
{
if (dynamicGlobalObject) {
StackPreservingRecompiler recompiler;
HashSet<JSCell*> roots;
+ heap.canonicalizeCellLivenessData();
heap.getConservativeRegisterRoots(roots);
HashSet<JSCell*>::iterator end = roots.end();
for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
@@ -476,14 +512,19 @@ void JSGlobalData::releaseExecutableMemory()
m_regExpCache->invalidateCode();
heap.collectAllGarbage();
}
+
+void VM::clearExceptionStack()
+{
+ m_exceptionStack = RefCountedArray<StackFrame>();
+}
-void releaseExecutableMemory(JSGlobalData& globalData)
+void releaseExecutableMemory(VM& vm)
{
- globalData.releaseExecutableMemory();
+ vm.releaseExecutableMemory();
}
#if ENABLE(DFG_JIT)
-void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+void VM::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
{
for (size_t i = 0; i < scratchBuffers.size(); i++) {
ScratchBuffer* scratchBuffer = scratchBuffers[i];
@@ -496,12 +537,12 @@ void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
#endif
#if ENABLE(REGEXP_TRACING)
-void JSGlobalData::addRegExpToTrace(RegExp* regExp)
+void VM::addRegExpToTrace(RegExp* regExp)
{
m_rtTraceList->add(regExp);
}
-void JSGlobalData::dumpRegExpTrace()
+void VM::dumpRegExpTrace()
{
// The first RegExp object is ignored. It is create by the RegExpPrototype ctor and not used.
RTTraceList::iterator iter = ++m_rtTraceList->begin();
@@ -523,7 +564,7 @@ void JSGlobalData::dumpRegExpTrace()
m_rtTraceList->clear();
}
#else
-void JSGlobalData::dumpRegExpTrace()
+void VM::dumpRegExpTrace()
{
}
#endif
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/VM.h
index 01e6059da..dcd525107 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/VM.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 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
@@ -26,29 +26,35 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSGlobalData_h
-#define JSGlobalData_h
+#ifndef VM_h
+#define VM_h
#include "CachedTranscendentalFunction.h"
#include "DateInstanceCache.h"
#include "ExecutableAllocator.h"
#include "Heap.h"
#include "Intrinsic.h"
-#include "JITStubs.h"
+#include "JITThunks.h"
+#include "JITThunks.h"
+#include "JSCJSValue.h"
#include "JSLock.h"
-#include "JSValue.h"
#include "LLIntData.h"
+#include "MacroAssemblerCodeRef.h"
#include "NumericStrings.h"
+#include "ProfilerDatabase.h"
#include "PrivateName.h"
+#include "PrototypeMap.h"
#include "SmallStrings.h"
#include "Strong.h"
-#include "Terminator.h"
-#include "TimeoutChecker.h"
+#include "ThunkGenerators.h"
#include "TypedArrayDescriptor.h"
+#include "Watchdog.h"
#include "WeakRandom.h"
#include <wtf/BumpPointerAllocator.h>
+#include <wtf/DateMath.h>
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
+#include <wtf/RefCountedArray.h>
#include <wtf/SimpleStats.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/ThreadSpecific.h>
@@ -57,14 +63,12 @@
#include <wtf/ListHashSet.h>
#endif
-struct OpaqueJSClass;
-struct OpaqueJSClassContextData;
-
namespace JSC {
class CodeBlock;
class CodeCache;
class CommonIdentifiers;
+ class ExecState;
class HandleStack;
class IdentifierTable;
class Interpreter;
@@ -72,10 +76,13 @@ namespace JSC {
class JSObject;
class Keywords;
class LLIntOffsetsExtractor;
+ class LegacyProfiler;
class NativeExecutable;
class ParserArena;
- class Profiler;
class RegExpCache;
+ class SourceProvider;
+ class SourceProviderCache;
+ struct StackFrame;
class Stringifier;
class Structure;
#if ENABLE(REGEXP_TRACING)
@@ -86,24 +93,32 @@ namespace JSC {
class UnlinkedFunctionExecutable;
class UnlinkedProgramCodeBlock;
+#if ENABLE(DFG_JIT)
+ namespace DFG {
+ class LongLivedState;
+ }
+#endif // ENABLE(DFG_JIT)
+
struct HashTable;
struct Instruction;
- struct DSTOffsetCache {
- DSTOffsetCache()
+ struct LocalTimeOffsetCache {
+ LocalTimeOffsetCache()
+ : start(0.0)
+ , end(-1.0)
+ , increment(0.0)
{
- reset();
}
void reset()
{
- offset = 0.0;
+ offset = LocalTimeOffset();
start = 0.0;
end = -1.0;
increment = 0.0;
}
- double offset;
+ LocalTimeOffset offset;
double start;
double end;
double increment;
@@ -118,8 +133,8 @@ namespace JSC {
#endif
struct ScratchBuffer {
ScratchBuffer()
- : m_activeLength(0)
{
+ u.m_activeLength = 0;
}
static ScratchBuffer* create(size_t size)
@@ -130,12 +145,15 @@ namespace JSC {
}
static size_t allocationSize(size_t bufferSize) { return sizeof(ScratchBuffer) + bufferSize; }
- void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
- size_t activeLength() const { return m_activeLength; };
- size_t* activeLengthPtr() { return &m_activeLength; };
+ void setActiveLength(size_t activeLength) { u.m_activeLength = activeLength; }
+ size_t activeLength() const { return u.m_activeLength; };
+ size_t* activeLengthPtr() { return &u.m_activeLength; };
void* dataBuffer() { return m_buffer; }
- size_t m_activeLength;
+ union {
+ size_t m_activeLength;
+ double pad; // Make sure m_buffer is double aligned.
+ } u;
#if CPU(MIPS) && (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == 2)
void* m_buffer[0] __attribute__((aligned(8)));
#else
@@ -147,36 +165,36 @@ namespace JSC {
#endif
#endif
- class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
+ class VM : public ThreadSafeRefCounted<VM> {
public:
- // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
+ // WebCore has a one-to-one mapping of threads to VMs;
// either create() or createLeaked() should only be called once
- // on a thread, this is the 'default' JSGlobalData (it uses the
+ // on a thread, this is the 'default' VM (it uses the
// thread's default string uniquing table from wtfThreadData).
// API contexts created using the new context group aware interface
// create APIContextGroup objects which require less locking of JSC
- // than the old singleton APIShared JSGlobalData created for use by
+ // than the old singleton APIShared VM created for use by
// the original API.
- enum GlobalDataType { Default, APIContextGroup, APIShared };
+ enum VMType { Default, APIContextGroup, APIShared };
struct ClientData {
JS_EXPORT_PRIVATE virtual ~ClientData() = 0;
};
- bool isSharedInstance() { return globalDataType == APIShared; }
- bool usingAPI() { return globalDataType != Default; }
+ bool isSharedInstance() { return vmType == APIShared; }
+ bool usingAPI() { return vmType != Default; }
static bool sharedInstanceExists();
- JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance();
+ JS_EXPORT_PRIVATE static VM& sharedInstance();
- JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(HeapType = SmallHeap);
- JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(HeapType = SmallHeap);
- static PassRefPtr<JSGlobalData> createContextGroup(HeapType = SmallHeap);
- JS_EXPORT_PRIVATE ~JSGlobalData();
+ JS_EXPORT_PRIVATE static PassRefPtr<VM> create(HeapType = SmallHeap);
+ JS_EXPORT_PRIVATE static PassRefPtr<VM> createLeaked(HeapType = SmallHeap);
+ static PassRefPtr<VM> createContextGroup(HeapType = SmallHeap);
+ JS_EXPORT_PRIVATE ~VM();
void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
private:
- JSLock m_apiLock;
+ RefPtr<JSLock> m_apiLock;
public:
#if ENABLE(ASSEMBLER)
@@ -188,10 +206,15 @@ namespace JSC {
// The heap should be just after executableAllocator and before other members to ensure that it's
// destructed after all the objects that reference it.
Heap heap;
+
+#if ENABLE(DFG_JIT)
+ OwnPtr<DFG::LongLivedState> m_dfgState;
+#endif // ENABLE(DFG_JIT)
- GlobalDataType globalDataType;
+ VMType vmType;
ClientData* clientData;
- CallFrame* topCallFrame;
+ ExecState* topCallFrame;
+ Watchdog watchdog;
const HashTable* arrayConstructorTable;
const HashTable* arrayPrototypeTable;
@@ -205,17 +228,15 @@ namespace JSC {
const HashTable* numberConstructorTable;
const HashTable* numberPrototypeTable;
const HashTable* objectConstructorTable;
- const HashTable* objectPrototypeTable;
const HashTable* privateNamePrototypeTable;
const HashTable* regExpTable;
const HashTable* regExpConstructorTable;
const HashTable* regExpPrototypeTable;
- const HashTable* stringTable;
const HashTable* stringConstructorTable;
Strong<Structure> structureStructure;
+ Strong<Structure> structureRareDataStructure;
Strong<Structure> debuggerActivationStructure;
- Strong<Structure> interruptedExecutionErrorStructure;
Strong<Structure> terminatedExecutionErrorStructure;
Strong<Structure> stringStructure;
Strong<Structure> notAnObjectStructure;
@@ -237,6 +258,7 @@ namespace JSC {
Strong<Structure> unlinkedProgramCodeBlockStructure;
Strong<Structure> unlinkedEvalCodeBlockStructure;
Strong<Structure> unlinkedFunctionCodeBlockStructure;
+ Strong<Structure> propertyTableStructure;
IdentifierTable* identifierTable;
CommonIdentifiers* propertyNames;
@@ -267,7 +289,7 @@ namespace JSC {
return m_inDefineOwnProperty;
}
- Profiler* enabledProfiler()
+ LegacyProfiler* enabledProfiler()
{
return m_enabledProfiler;
}
@@ -286,9 +308,14 @@ namespace JSC {
bool canUseRegExpJIT() { return false; } // interpreter only
#endif
- PrivateName m_inheritorIDKey;
+ SourceProviderCache* addSourceProviderCache(SourceProvider*);
+ void clearSourceProviderCaches();
+
+ PrototypeMap prototypeMap;
OwnPtr<ParserArena> parserArena;
+ typedef HashMap<RefPtr<SourceProvider>, RefPtr<SourceProviderCache> > SourceProviderCacheMap;
+ SourceProviderCacheMap sourceProviderCacheMap;
OwnPtr<Keywords> keywords;
Interpreter* interpreter;
#if ENABLE(JIT)
@@ -301,17 +328,16 @@ namespace JSC {
#endif
NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor);
- TimeoutChecker timeoutChecker;
- Terminator terminator;
-
JSValue exception;
+ JS_EXPORT_PRIVATE void clearExceptionStack();
+ RefCountedArray<StackFrame>& exceptionStack() { return m_exceptionStack; }
const ClassInfo* const jsArrayClassInfo;
const ClassInfo* const jsFinalObjectClassInfo;
ReturnAddressPtr exceptionLocation;
JSValue hostCallReturnValue;
- CallFrame* callFrameForThrow;
+ ExecState* callFrameForThrow;
void* targetMachinePCForThrow;
Instruction* targetInterpreterPCForThrow;
#if ENABLE(DFG_JIT)
@@ -343,19 +369,17 @@ namespace JSC {
void gatherConservativeRoots(ConservativeRoots&);
#endif
- HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
-
JSGlobalObject* dynamicGlobalObject;
HashSet<JSObject*> stringRecursionCheckVisitedObjects;
- double cachedUTCOffset;
- DSTOffsetCache dstOffsetCache;
+ LocalTimeOffsetCache localTimeOffsetCache;
String cachedDateString;
double cachedDateStringValue;
- Profiler* m_enabledProfiler;
+ LegacyProfiler* m_enabledProfiler;
+ OwnPtr<Profiler::Database> m_perBytecodeProfiler;
RegExpCache* m_regExpCache;
BumpPointerAllocator m_regExpAllocator;
@@ -368,7 +392,7 @@ namespace JSC {
ThreadIdentifier exclusiveThread;
#endif
- CachedTranscendentalFunction<sin> cachedSin;
+ CachedTranscendentalFunction<std::sin> cachedSin;
JS_EXPORT_PRIVATE void resetDateCache();
@@ -389,16 +413,12 @@ namespace JSC {
void setInitializingObjectClass(const ClassInfo*);
#endif
-#if CPU(X86) && ENABLE(JIT)
- unsigned m_timeoutCount;
-#endif
-
- unsigned m_newStringsSinceLastHashConst;
+ unsigned m_newStringsSinceLastHashCons;
- static const unsigned s_minNumberOfNewStringsToHashConst = 100;
+ static const unsigned s_minNumberOfNewStringsToHashCons = 100;
- bool haveEnoughNewStringsToHashConst() { return m_newStringsSinceLastHashConst > s_minNumberOfNewStringsToHashConst; }
- void resetNewStringsSinceLastHashConst() { m_newStringsSinceLastHashConst = 0; }
+ bool haveEnoughNewStringsToHashCons() { return m_newStringsSinceLastHashCons > s_minNumberOfNewStringsToHashCons; }
+ void resetNewStringsSinceLastHashCons() { m_newStringsSinceLastHashCons = 0; }
#define registerTypedArrayFunction(type, capitalizedType) \
void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
@@ -449,14 +469,16 @@ namespace JSC {
}
}
- JSLock& apiLock() { return m_apiLock; }
+ JSLock& apiLock() { return *m_apiLock; }
CodeCache* codeCache() { return m_codeCache.get(); }
+ JS_EXPORT_PRIVATE void discardAllCode();
+
private:
friend class LLIntOffsetsExtractor;
- JSGlobalData(GlobalDataType, HeapType);
- static JSGlobalData*& sharedInstanceInternal();
+ VM(VMType, HeapType);
+ static VM*& sharedInstanceInternal();
void createNativeThunk();
#if ENABLE(ASSEMBLER)
bool m_canUseAssembler;
@@ -471,7 +493,8 @@ namespace JSC {
const ClassInfo* m_initializingObjectClass;
#endif
bool m_inDefineOwnProperty;
- OwnPtr<CodeCache> m_codeCache;
+ RefPtr<CodeCache> m_codeCache;
+ RefCountedArray<StackFrame> m_exceptionStack;
TypedArrayDescriptor m_int8ArrayDescriptor;
TypedArrayDescriptor m_int16ArrayDescriptor;
@@ -485,12 +508,12 @@ namespace JSC {
};
#if ENABLE(GC_VALIDATION)
- inline bool JSGlobalData::isInitializingObject() const
+ inline bool VM::isInitializingObject() const
{
return !!m_initializingObjectClass;
}
- inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
+ inline void VM::setInitializingObjectClass(const ClassInfo* initializingObjectClass)
{
m_initializingObjectClass = initializingObjectClass;
}
@@ -498,9 +521,9 @@ namespace JSC {
inline Heap* WeakSet::heap() const
{
- return &m_globalData->heap;
+ return &m_vm->heap;
}
} // namespace JSC
-#endif // JSGlobalData_h
+#endif // VM_h
diff --git a/Source/JavaScriptCore/runtime/VMStackBounds.h b/Source/JavaScriptCore/runtime/VMStackBounds.h
new file mode 100644
index 000000000..76a3ebd30
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/VMStackBounds.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VMStackBounds_h
+#define VMStackBounds_h
+
+#include "VM.h"
+#include <wtf/StackBounds.h>
+
+namespace JSC {
+
+class VMStackBounds {
+public:
+ VMStackBounds(VM& vm, const StackBounds& bounds)
+ : m_vm(vm)
+ , m_bounds(bounds)
+ {
+ }
+
+ bool isSafeToRecurse() const { return m_bounds.isSafeToRecurse(requiredCapacity()); }
+
+private:
+ inline size_t requiredCapacity() const
+ {
+ Interpreter* interpreter = m_vm.interpreter;
+
+ // We have two separate stack limits, one for regular JS execution, and one
+ // for when we're handling errors. We need the error stack to be smaller
+ // otherwise there would obviously not be any stack left to execute JS in when
+ // there's a stack overflow.
+ //
+ // These sizes were derived from the stack usage of a number of sites when
+ // layout occurs when we've already consumed most of the C stack.
+ const size_t requiredStack = 128 * KB;
+ const size_t errorModeRequiredStack = 64 * KB;
+
+ size_t requiredCapacity = interpreter->isInErrorHandlingMode() ? errorModeRequiredStack : requiredStack;
+ RELEASE_ASSERT(m_bounds.size() >= requiredCapacity);
+ return requiredCapacity;
+ }
+
+ VM& m_vm;
+ const StackBounds& m_bounds;
+};
+
+} // namespace JSC
+
+#endif // VMStackBounds_h
+
diff --git a/Source/JavaScriptCore/runtime/Watchdog.cpp b/Source/JavaScriptCore/runtime/Watchdog.cpp
new file mode 100644
index 000000000..573260b16
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/Watchdog.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Watchdog.h"
+
+#include "CallFrame.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/MathExtras.h>
+
+namespace JSC {
+
+#define NO_LIMIT std::numeric_limits<double>::infinity()
+
+Watchdog::Watchdog()
+ : m_timerDidFire(false)
+ , m_didFire(false)
+ , m_limit(NO_LIMIT)
+ , m_startTime(0)
+ , m_elapsedTime(0)
+ , m_reentryCount(0)
+ , m_isStopped(true)
+ , m_callback(0)
+ , m_callbackData1(0)
+ , m_callbackData2(0)
+{
+ initTimer();
+}
+
+Watchdog::~Watchdog()
+{
+ ASSERT(!isArmed());
+ stopCountdown();
+ destroyTimer();
+}
+
+void Watchdog::setTimeLimit(VM& vm, double limit,
+ ShouldTerminateCallback callback, void* data1, void* data2)
+{
+ bool wasEnabled = isEnabled();
+
+ if (!m_isStopped)
+ stopCountdown();
+
+ m_didFire = false; // Reset the watchdog.
+
+ m_limit = limit;
+ m_callback = callback;
+ m_callbackData1 = data1;
+ m_callbackData2 = data2;
+
+ // If this is the first time that timeout is being enabled, then any
+ // previously JIT compiled code will not have the needed polling checks.
+ // Hence, we need to flush all the pre-existing compiled code.
+ //
+ // However, if the timeout is already enabled, and we're just changing the
+ // timeout value, then any existing JITted code will have the appropriate
+ // polling checks. Hence, there is no need to re-do this flushing.
+ if (!wasEnabled) {
+ // And if we've previously compiled any functions, we need to revert
+ // them because they don't have the needed polling checks yet.
+ vm.releaseExecutableMemory();
+ }
+
+ startCountdownIfNeeded();
+}
+
+bool Watchdog::didFire(ExecState* exec)
+{
+ if (m_didFire)
+ return true;
+
+ if (!m_timerDidFire)
+ return false;
+ m_timerDidFire = false;
+ stopCountdown();
+
+ double currentTime = currentCPUTime();
+ double deltaTime = currentTime - m_startTime;
+ double totalElapsedTime = m_elapsedTime + deltaTime;
+ if (totalElapsedTime > m_limit) {
+ // Case 1: the allowed CPU time has elapsed.
+
+ // If m_callback is not set, then we terminate by default.
+ // Else, we let m_callback decide if we should terminate or not.
+ bool needsTermination = !m_callback
+ || m_callback(exec, m_callbackData1, m_callbackData2);
+ if (needsTermination) {
+ m_didFire = true;
+ return true;
+ }
+
+ // The m_callback may have set a new limit. So, we may need to restart
+ // the countdown.
+ startCountdownIfNeeded();
+
+ } else {
+ // Case 2: the allowed CPU time has NOT elapsed.
+
+ // Tell the timer to alarm us again when it thinks we've reached the
+ // end of the allowed time.
+ double remainingTime = m_limit - totalElapsedTime;
+ m_elapsedTime = totalElapsedTime;
+ m_startTime = currentTime;
+ startCountdown(remainingTime);
+ }
+
+ return false;
+}
+
+bool Watchdog::isEnabled()
+{
+ return (m_limit != NO_LIMIT);
+}
+
+void Watchdog::fire()
+{
+ m_didFire = true;
+}
+
+void Watchdog::arm()
+{
+ m_reentryCount++;
+ if (m_reentryCount == 1)
+ startCountdownIfNeeded();
+}
+
+void Watchdog::disarm()
+{
+ ASSERT(m_reentryCount > 0);
+ if (m_reentryCount == 1)
+ stopCountdown();
+ m_reentryCount--;
+}
+
+void Watchdog::startCountdownIfNeeded()
+{
+ if (!m_isStopped)
+ return; // Already started.
+
+ if (!isArmed())
+ return; // Not executing JS script. No need to start.
+
+ if (isEnabled()) {
+ m_elapsedTime = 0;
+ m_startTime = currentCPUTime();
+ startCountdown(m_limit);
+ }
+}
+
+void Watchdog::startCountdown(double limit)
+{
+ ASSERT(m_isStopped);
+ m_isStopped = false;
+ startTimer(limit);
+}
+
+void Watchdog::stopCountdown()
+{
+ if (m_isStopped)
+ return;
+ stopTimer();
+ m_isStopped = true;
+}
+
+Watchdog::Scope::Scope(Watchdog& watchdog)
+ : m_watchdog(watchdog)
+{
+ m_watchdog.arm();
+}
+
+Watchdog::Scope::~Scope()
+{
+ m_watchdog.disarm();
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Watchdog.h b/Source/JavaScriptCore/runtime/Watchdog.h
new file mode 100644
index 000000000..08c0ccb95
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/Watchdog.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Watchdog_h
+#define Watchdog_h
+
+#if PLATFORM(MAC) || PLATFORM(IOS)
+#include <dispatch/dispatch.h>
+#endif
+
+namespace JSC {
+
+class ExecState;
+class VM;
+
+class Watchdog {
+public:
+ class Scope;
+
+ Watchdog();
+ ~Watchdog();
+
+ typedef bool (*ShouldTerminateCallback)(ExecState*, void* data1, void* data2);
+ void setTimeLimit(VM&, double seconds, ShouldTerminateCallback = 0, void* data1 = 0, void* data2 = 0);
+
+ // This version of didFire() will check the elapsed CPU time and call the
+ // callback (if needed) to determine if the watchdog should fire.
+ bool didFire(ExecState*);
+
+ bool isEnabled();
+
+ // This version of didFire() is a more efficient version for when we want
+ // to know if the watchdog has fired in the past, and not whether it should
+ // fire right now.
+ JS_EXPORT_PRIVATE bool didFire() { return m_didFire; }
+ JS_EXPORT_PRIVATE void fire();
+
+ void* timerDidFireAddress() { return &m_timerDidFire; }
+
+private:
+ void arm();
+ void disarm();
+ void startCountdownIfNeeded();
+ void startCountdown(double limit);
+ void stopCountdown();
+ bool isArmed() { return !!m_reentryCount; }
+
+ // Platform specific timer implementation:
+ void initTimer();
+ void destroyTimer();
+ void startTimer(double limit);
+ void stopTimer();
+
+ // m_timerDidFire (above) indicates whether the timer fired. The Watchdog
+ // still needs to check if the allowed CPU time has elapsed. If so, then
+ // the Watchdog fires and m_didFire will be set.
+ // NOTE: m_timerDidFire is only set by the platform specific timer
+ // (probably from another thread) but is only cleared in the script thread.
+ bool m_timerDidFire;
+ bool m_didFire;
+
+ // All time units are in seconds.
+ double m_limit;
+ double m_startTime;
+ double m_elapsedTime;
+
+ int m_reentryCount;
+ bool m_isStopped;
+
+ ShouldTerminateCallback m_callback;
+ void* m_callbackData1;
+ void* m_callbackData2;
+
+#if PLATFORM(MAC) || PLATFORM(IOS)
+ dispatch_queue_t m_queue;
+ dispatch_source_t m_timer;
+#endif
+
+ friend class Watchdog::Scope;
+ friend class LLIntOffsetsExtractor;
+};
+
+class Watchdog::Scope {
+public:
+ Scope(Watchdog&);
+ ~Scope();
+
+private:
+ Watchdog& m_watchdog;
+};
+
+} // namespace JSC
+
+#endif // Watchdog_h
diff --git a/Source/JavaScriptCore/runtime/WatchdogMac.cpp b/Source/JavaScriptCore/runtime/WatchdogMac.cpp
new file mode 100644
index 000000000..ca474df2f
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/WatchdogMac.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Watchdog.h"
+
+namespace JSC {
+
+void Watchdog::initTimer()
+{
+ m_queue = 0;
+ m_timer = 0;
+}
+
+void Watchdog::destroyTimer()
+{
+ ASSERT(!m_timer);
+ if (m_queue)
+ dispatch_release(m_queue);
+}
+
+void Watchdog::startTimer(double limit)
+{
+ ASSERT(!m_timer);
+ if (!m_queue)
+ m_queue = dispatch_queue_create("jsc.watchdog.queue", 0);
+ m_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_queue);
+
+ dispatch_source_set_timer(m_timer,
+ dispatch_time(DISPATCH_TIME_NOW, limit * NSEC_PER_SEC),
+ DISPATCH_TIME_FOREVER, 0);
+
+ dispatch_source_set_event_handler(m_timer, ^{
+ m_timerDidFire = true;
+ });
+
+ dispatch_resume(m_timer);
+}
+
+void Watchdog::stopTimer()
+{
+ ASSERT(m_queue);
+ dispatch_sync(m_queue, ^{
+ dispatch_source_cancel(m_timer);
+ });
+ dispatch_release(m_timer);
+ m_timer = 0;
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/WatchdogNone.cpp b/Source/JavaScriptCore/runtime/WatchdogNone.cpp
new file mode 100644
index 000000000..615314bb3
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/WatchdogNone.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Watchdog.h"
+
+namespace JSC {
+
+// This is a stub for platforms that have not implemented this functionality.
+// In this case, the platform timer here never fires.
+
+void Watchdog::initTimer()
+{
+}
+
+void Watchdog::destroyTimer()
+{
+}
+
+void Watchdog::startTimer(double)
+{
+}
+
+void Watchdog::stopTimer()
+{
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h
index 52e5e2946..f741fa4c4 100644
--- a/Source/JavaScriptCore/runtime/WeakGCMap.h
+++ b/Source/JavaScriptCore/runtime/WeakGCMap.h
@@ -26,88 +26,104 @@
#ifndef WeakGCMap_h
#define WeakGCMap_h
-#include "Handle.h"
-#include "JSGlobalData.h"
+#include <heap/Weak.h>
+#include <heap/WeakInlines.h>
#include <wtf/HashMap.h>
namespace JSC {
-// A HashMap for GC'd values that removes entries when the associated value
-// dies.
-template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback {
- static void* finalizerContextFor(KeyType key)
- {
- return reinterpret_cast<void*>(key);
- }
+// A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected.
- static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType)
- {
- return reinterpret_cast<KeyType>(context);
- }
-};
-
-template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> >
-class WeakGCMap : private WeakHandleOwner {
- WTF_MAKE_FAST_ALLOCATED;
- WTF_MAKE_NONCOPYABLE(WeakGCMap);
-
- typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType;
- typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
+template<typename KeyArg, typename RawMappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
+ typename KeyTraitsArg = HashTraits<KeyArg> >
+class WeakGCMap : public HashMap<KeyArg, Weak<RawMappedArg>, HashArg, KeyTraitsArg> {
+ typedef Weak<RawMappedArg> MappedType;
+ typedef HashMap<KeyArg, MappedType, HashArg, KeyTraitsArg> Base;
+ typedef WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg> Self;
+ typedef HashTraits<MappedType> MappedTraits;
+ typedef typename MappedTraits::PassInType MappedPassInType;
public:
+ typedef typename Base::KeyType KeyType;
+ typedef typename Base::AddResult AddResult;
+ typedef typename Base::iterator iterator;
+ typedef typename Base::const_iterator const_iterator;
+ using Base::begin;
+ using Base::end;
+ using Base::size;
+ using Base::remove;
+
WeakGCMap()
+ : m_gcThreshold(minGCThreshold)
{
}
- void clear()
+ AddResult set(const KeyType& key, MappedPassInType value)
{
- typename MapType::iterator end = m_map.end();
- for (typename MapType::iterator ptr = m_map.begin(); ptr != end; ++ptr)
- WeakSet::deallocate(ptr->value);
- m_map.clear();
+ gcMapIfNeeded();
+ return Base::set(key, value);
}
- ExternalType get(const KeyType& key) const
+ AddResult add(const KeyType& key, MappedPassInType value)
{
- WeakImpl* impl = m_map.get(key);
- if (!impl || impl->state() != WeakImpl::Live)
- return ExternalType();
- return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue()));
+ gcMapIfNeeded();
+ AddResult addResult = Base::add(key, nullptr);
+ if (!addResult.iterator->value) { // New value or found a zombie value.
+ addResult.isNewEntry = true;
+ addResult.iterator->value = value;
+ }
+ return addResult;
}
- void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+ iterator find(const KeyType& key)
{
- ASSERT_UNUSED(globalData, globalData.apiLock().currentThreadIsHoldingLock());
- typename MapType::AddResult result = m_map.add(key, 0);
- if (!result.isNewEntry)
- WeakSet::deallocate(result.iterator->value);
- result.iterator->value = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key));
+ iterator it = Base::find(key);
+ iterator end = Base::end();
+ if (it != end && !it->value) // Found a zombie value.
+ return end;
+ return it;
}
- void remove(const KeyType& key)
+ const_iterator find(const KeyType& key) const
{
- WeakImpl* impl = m_map.take(key);
- if (!impl)
- return;
- WeakSet::deallocate(impl);
+ return const_cast<Self*>(this)->find(key);
}
- ~WeakGCMap()
+ bool contains(const KeyType& key) const
{
- clear();
+ return find(key) != end();
}
-
+
private:
- virtual void finalize(Handle<Unknown> handle, void* context)
+ static const int minGCThreshold = 3;
+
+ void gcMap()
+ {
+ Vector<KeyType, 4> zombies;
+ iterator end = this->end();
+ for (iterator it = begin(); it != end; ++it) {
+ if (!it->value)
+ zombies.append(it->key);
+ }
+ for (size_t i = 0; i < zombies.size(); ++i)
+ remove(zombies[i]);
+ }
+
+ void gcMapIfNeeded()
{
- WeakImpl* impl = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
- ASSERT(impl);
- WeakSet::deallocate(impl);
+ if (size() < m_gcThreshold)
+ return;
+
+ gcMap();
+ m_gcThreshold = std::max(minGCThreshold, size() * 2 - 1);
}
- MapType m_map;
+ int m_gcThreshold;
};
+template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg>
+const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold;
+
} // namespace JSC
#endif // WeakGCMap_h
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index ef8c3aff8..fe07cf532 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -35,7 +35,7 @@
namespace JSC {
class JSCell;
-class JSGlobalData;
+class VM;
class JSGlobalObject;
template<class T> class WriteBarrierBase;
@@ -68,11 +68,11 @@ template<class T> inline void validateCell(T)
// We have a separate base class with no constructors for use in Unions.
template <typename T> class WriteBarrierBase {
public:
- void set(JSGlobalData& globalData, const JSCell* owner, T* value)
+ void set(VM& vm, const JSCell* owner, T* value)
{
ASSERT(value);
validateCell(value);
- setEarlyValue(globalData, owner, value);
+ setEarlyValue(vm, owner, value);
}
// This is meant to be used like operator=, but is called copyFrom instead, in
@@ -82,16 +82,16 @@ public:
m_cell = other.m_cell;
}
- void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
+ void setMayBeNull(VM& vm, const JSCell* owner, T* value)
{
if (value)
validateCell(value);
- setEarlyValue(globalData, owner, value);
+ setEarlyValue(vm, owner, value);
}
// Should only be used by JSCell during early initialisation
// when some basic types aren't yet completely instantiated
- void setEarlyValue(JSGlobalData&, const JSCell* owner, T* value)
+ void setEarlyValue(VM&, const JSCell* owner, T* value)
{
this->m_cell = reinterpret_cast<JSCell*>(value);
Heap::writeBarrier(owner, this->m_cell);
@@ -99,9 +99,11 @@ public:
T* get() const
{
- if (m_cell)
- validateCell(m_cell);
- return reinterpret_cast<T*>(static_cast<void*>(m_cell));
+ // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>)
+ JSCell* cell = m_cell;
+ if (cell)
+ validateCell(cell);
+ return reinterpret_cast<T*>(static_cast<void*>(cell));
}
T* operator*() const
@@ -145,7 +147,7 @@ private:
template <> class WriteBarrierBase<Unknown> {
public:
- void set(JSGlobalData&, const JSCell* owner, JSValue value)
+ void set(VM&, const JSCell* owner, JSValue value)
{
m_value = JSValue::encode(value);
Heap::writeBarrier(owner, value);
@@ -195,15 +197,15 @@ public:
this->setWithoutWriteBarrier(0);
}
- WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
+ WriteBarrier(VM& vm, const JSCell* owner, T* value)
{
- this->set(globalData, owner, value);
+ this->set(vm, owner, value);
}
enum MayBeNullTag { MayBeNull };
- WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value, MayBeNullTag)
+ WriteBarrier(VM& vm, const JSCell* owner, T* value, MayBeNullTag)
{
- this->setMayBeNull(globalData, owner, value);
+ this->setMayBeNull(vm, owner, value);
}
};
@@ -214,9 +216,9 @@ public:
this->setWithoutWriteBarrier(JSValue());
}
- WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
+ WriteBarrier(VM& vm, const JSCell* owner, JSValue value)
{
- this->set(globalData, owner, value);
+ this->set(vm, owner, value);
}
};