summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
commitdd91e772430dc294e3bf478c119ef8d43c0a3358 (patch)
tree6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/runtime
parentad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff)
downloadqtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h2
-rw-r--r--Source/JavaScriptCore/runtime/ArrayPrototype.cpp236
-rw-r--r--Source/JavaScriptCore/runtime/ClassInfo.h2
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h5
-rw-r--r--Source/JavaScriptCore/runtime/Completion.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp20
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp43
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h41
-rw-r--r--Source/JavaScriptCore/runtime/ExecutionHarness.h4
-rw-r--r--Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.h2
-rw-r--r--Source/JavaScriptCore/runtime/InitializeThreading.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp220
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h61
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSByteArray.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.cpp13
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSDateMath.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp77
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h1
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h6
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSNotAnObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp17
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h13
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/JSStringBuilder.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.cpp82
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/NumberPrototype.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp61
-rw-r--r--Source/JavaScriptCore/runtime/Options.h16
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.cpp16
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.h1
-rw-r--r--Source/JavaScriptCore/runtime/PropertySlot.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp28
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpMatchesArray.h4
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp121
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.h48
-rw-r--r--Source/JavaScriptCore/runtime/RegExpPrototype.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.cpp48
-rw-r--r--Source/JavaScriptCore/runtime/StringObject.h1
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp48
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.h2
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h2
53 files changed, 873 insertions, 469 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index a099adb75..7a53ec1a4 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -196,7 +196,7 @@ void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyN
JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
}
-void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value)
+void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
{
Arguments* thisObject = jsCast<Arguments*>(cell);
if (i < static_cast<unsigned>(thisObject->d->numArguments) && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) {
@@ -204,7 +204,7 @@ void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue va
return;
}
- PutPropertySlot slot;
+ PutPropertySlot slot(shouldThrow);
JSObject::put(thisObject, exec, Identifier(exec, UString::number(i)), value, slot);
}
@@ -320,12 +320,15 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Ident
if (descriptor.isAccessorDescriptor()) {
// i. Call the [[Delete]] internal method of map passing P, and false as the arguments.
thisObject->d->deletedArguments[i] = true;
- } else if (descriptor.value()) { // b. Else i. If Desc.[[Value]] is present, then
+ } else { // b. Else
+ // 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->argument(i).set(exec->globalData(), thisObject, descriptor.value());
// ii. If Desc.[[Writable]] is present and its value is false, then
- thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value());
+ // 1. Call the [[Delete]] internal method of map passing P and false as arguments.
if (descriptor.writablePresent() && !descriptor.writable())
- thisObject->d->deletedArguments[i] = true; // 1. Call the [[Delete]] internal method of map passing P and false as arguments.
+ thisObject->d->deletedArguments[i] = true;
}
}
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h
index ee54a49eb..8e7af1844 100644
--- a/Source/JavaScriptCore/runtime/Arguments.h
+++ b/Source/JavaScriptCore/runtime/Arguments.h
@@ -114,7 +114,7 @@ namespace JSC {
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index cb9b12a59..2f000fc74 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -166,6 +166,90 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument
return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
}
+
+// The shift/unshift function implement the shift/unshift behaviour required
+// by the corresponding array prototype methods, and by splice. In both cases,
+// the methods are operating an an array or array like object.
+//
+// header currentCount (remainder)
+// [------][------------][-----------]
+// header resultCount (remainder)
+// [------][-----------][-----------]
+//
+// The set of properties in the range 'header' must be unchanged. The set of
+// properties in the range 'remainder' (where remainder = length - header -
+// currentCount) will be shifted to the left or right as appropriate; in the
+// case of shift this must be removing values, in the case of unshift this
+// must be introducing new values.
+static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+{
+ ASSERT(currentCount > resultCount);
+ unsigned count = currentCount - resultCount;
+
+ ASSERT(header <= length);
+ ASSERT(currentCount <= (length - header));
+
+ if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count))
+ return;
+
+ for (unsigned k = header; k < length - currentCount; ++k) {
+ unsigned from = k + currentCount;
+ unsigned to = k + resultCount;
+ PropertySlot slot(thisObj);
+ if (thisObj->getPropertySlot(exec, from, slot)) {
+ JSValue value = slot.getValue(exec, from);
+ if (exec->hadException())
+ return;
+ thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
+ if (exec->hadException())
+ return;
+ } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return;
+ }
+ }
+ for (unsigned k = length; k > length - count; --k) {
+ if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return;
+ }
+ }
+}
+static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+{
+ ASSERT(resultCount > currentCount);
+ unsigned count = resultCount - currentCount;
+
+ ASSERT(header <= length);
+ ASSERT(currentCount <= (length - header));
+
+ // Guard against overflow.
+ if (count > (UINT_MAX - length)) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+
+ if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count))
+ return;
+
+ for (unsigned k = length - currentCount; k > header; --k) {
+ unsigned from = k + currentCount - 1;
+ unsigned to = k + resultCount - 1;
+ PropertySlot slot(thisObj);
+ if (thisObj->getPropertySlot(exec, from, slot)) {
+ JSValue value = slot.getValue(exec, from);
+ if (exec->hadException())
+ return;
+ thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true);
+ } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return;
+ }
+ if (exec->hadException())
+ return;
+ }
+}
+
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
@@ -265,9 +349,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
strBuffer.append(',');
JSValue element = thisObj->get(exec, k);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
if (!element.isUndefinedOrNull()) {
JSObject* o = element.toObject(exec);
JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
UString str;
CallData callData;
CallType callType = getCallData(conversionFunction, callData);
@@ -275,6 +363,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
else
str = element.toString(exec)->value(exec);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
strBuffer.append(str);
}
}
@@ -368,11 +458,11 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (v)
- arr->methodTable()->putByIndex(arr, exec, n, v);
+ arr->putDirectIndex(exec, n, v);
n++;
}
} else {
- arr->methodTable()->putByIndex(arr, exec, n, curArg);
+ arr->putDirectIndex(exec, n, curArg);
n++;
}
if (i == argCount)
@@ -402,7 +492,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
result = jsUndefined();
} else {
result = thisObj->get(exec, length - 1);
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return JSValue::encode(jsUndefined());
+ }
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
}
return JSValue::encode(result);
@@ -426,12 +521,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
for (unsigned n = 0; n < exec->argumentCount(); n++) {
// Check for integer overflow; where safe we can do a fast put by index.
if (length + n >= length)
- thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n));
+ thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true);
else {
PutPropertySlot slot;
Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
}
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
}
JSValue newLength(static_cast<int64_t>(length) + static_cast<int64_t>(exec->argumentCount()));
putProperty(exec, thisObj, exec->propertyNames().length, newLength);
@@ -455,15 +552,23 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
- if (obj2)
- thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k);
+ if (obj2) {
+ thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2, true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return JSValue::encode(jsUndefined());
+ }
- if (obj)
- thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1);
+ if (obj) {
+ thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj, true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) {
+ throwTypeError(exec, "Unable to delete property.");
+ return JSValue::encode(jsUndefined());
+ }
}
return JSValue::encode(thisObj);
}
@@ -481,20 +586,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
result = jsUndefined();
} else {
result = thisObj->get(exec, 0);
- if (isJSArray(thisObj))
- ((JSArray *)thisObj)->shiftCount(exec, 1);
- else {
- for (unsigned k = 1; k < length; k++) {
- JSValue obj = getProperty(exec, thisObj, k);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- if (obj)
- thisObj->methodTable()->putByIndex(thisObj, exec, k - 1, obj);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
- }
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1);
- }
+ shift(exec, thisObj, 0, 1, 0, length);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
}
return JSValue::encode(result);
@@ -521,7 +615,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
if (exec->hadException())
return JSValue::encode(jsUndefined());
if (v)
- resObj->methodTable()->putByIndex(resObj, exec, n, v);
+ resObj->putDirectIndex(exec, n, v);
}
resObj->setLength(exec, n);
return JSValue::encode(result);
@@ -580,8 +674,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
}
// Swap themin and i
if (themin > i) {
- thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj);
- thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj);
+ thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
}
}
return JSValue::encode(thisObj);
@@ -627,41 +725,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
resObj->completeInitialization(deleteCount);
unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
- if (additionalArgs != deleteCount) {
- if (additionalArgs < deleteCount) {
- if ((!begin) && (isJSArray(thisObj)))
- ((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs);
- else {
- for (unsigned k = begin; k < length - deleteCount; ++k) {
- JSValue v = getProperty(exec, thisObj, k + deleteCount);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- if (v)
- thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs, v);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs);
- }
- for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
- }
- } else {
- if ((!begin) && (isJSArray(thisObj)))
- ((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount);
- else {
- for (unsigned k = length - deleteCount; k > begin; --k) {
- JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- if (obj)
- thisObj->methodTable()->putByIndex(thisObj, exec, k + additionalArgs - 1, obj);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + additionalArgs - 1);
- }
- }
- }
+ if (additionalArgs < deleteCount) {
+ shift(exec, thisObj, begin, deleteCount, additionalArgs, length);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ } else if (additionalArgs > deleteCount) {
+ unshift(exec, thisObj, begin, deleteCount, additionalArgs, length);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ }
+ for (unsigned k = 0; k < additionalArgs; ++k) {
+ thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2), true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
}
- for (unsigned k = 0; k < additionalArgs; ++k)
- thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2));
putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
return JSValue::encode(result);
@@ -677,23 +754,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
return JSValue::encode(jsUndefined());
unsigned nrArgs = exec->argumentCount();
- if ((nrArgs) && (length)) {
- if (isJSArray(thisObj))
- ((JSArray *)thisObj)->unshiftCount(exec, nrArgs);
- else {
- for (unsigned k = length; k > 0; --k) {
- JSValue v = getProperty(exec, thisObj, k - 1);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- if (v)
- thisObj->methodTable()->putByIndex(thisObj, exec, k + nrArgs - 1, v);
- else
- thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k + nrArgs - 1);
- }
- }
+ if (nrArgs) {
+ unshift(exec, thisObj, 0, 0, nrArgs, length);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ }
+ for (unsigned k = 0; k < nrArgs; ++k) {
+ thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k), true);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
}
- for (unsigned k = 0; k < nrArgs; ++k)
- thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k));
JSValue result = jsNumber(length + nrArgs);
putProperty(exec, thisObj, exec->propertyNames().length, result);
return JSValue::encode(result);
@@ -732,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
JSValue result = cachedCall.call();
if (result.toBoolean(exec))
- resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v);
+ resultArray->putDirectIndex(exec, filterIndex++, v);
}
if (k == length)
return JSValue::encode(resultArray);
@@ -753,7 +823,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
if (result.toBoolean(exec))
- resultArray->methodTable()->putByIndex(resultArray, exec, filterIndex++, v);
+ resultArray->putDirectIndex(exec, filterIndex++, v);
}
return JSValue::encode(resultArray);
}
@@ -788,7 +858,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
cachedCall.setArgument(1, jsNumber(k));
cachedCall.setArgument(2, thisObj);
- JSArray::putByIndex(resultArray, exec, k, cachedCall.call());
+ resultArray->putDirectIndex(exec, k, cachedCall.call());
}
}
for (; k < length && !exec->hadException(); ++k) {
@@ -809,7 +879,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
return JSValue::encode(jsUndefined());
JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
- resultArray->methodTable()->putByIndex(resultArray, exec, k, result);
+ resultArray->putDirectIndex(exec, k, result);
}
return JSValue::encode(resultArray);
diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h
index 9ebb33a74..214258cc6 100644
--- a/Source/JavaScriptCore/runtime/ClassInfo.h
+++ b/Source/JavaScriptCore/runtime/ClassInfo.h
@@ -48,7 +48,7 @@ namespace JSC {
typedef void (*PutFunctionPtr)(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
PutFunctionPtr put;
- typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
PutByIndexFunctionPtr putByIndex;
typedef bool (*DeletePropertyFunctionPtr)(JSCell*, ExecState*, const Identifier&);
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index d79e5c783..0d9580197 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -27,10 +27,6 @@
// 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(__defineGetter__) \
- macro(__defineSetter__) \
- macro(__lookupGetter__) \
- macro(__lookupSetter__) \
macro(apply) \
macro(arguments) \
macro(bind) \
@@ -52,6 +48,7 @@
macro(input) \
macro(isArray) \
macro(isPrototypeOf) \
+ macro(lastIndex) \
macro(length) \
macro(message) \
macro(multiline) \
diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp
index 98a66589a..ce620245b 100644
--- a/Source/JavaScriptCore/runtime/Completion.cpp
+++ b/Source/JavaScriptCore/runtime/Completion.cpp
@@ -30,7 +30,7 @@
#include "Interpreter.h"
#include "Parser.h"
#include "Debugger.h"
-#include "WTFThreadData.h"
+#include <wtf/WTFThreadData.h>
#include <stdio.h>
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index 243dc8856..5266c1ebe 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -36,6 +36,8 @@
#include "NativeErrorConstructor.h"
#include "SourceCode.h"
+#include <wtf/text/StringBuilder.h>
+
namespace JSC {
static const char* linePropertyName = "line";
@@ -132,20 +134,14 @@ JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, cons
globalObject = globalData->dynamicGlobalObject;
else
globalObject = error->globalObject();
- // We use the tryCreateUninitialized creation mechanism and related initialization
- // functions as they're the only mechanism we currently have that will guarantee we
- // don't call setters on the prototype. Technically it's faster than the alternative,
- // but the numerous allocations that take place in this loop makes that last bit
- // somewhat moot.
- JSArray* stackTraceArray = JSArray::tryCreateUninitialized(*globalData, globalObject->arrayStructure(), stackTrace.size());
- if (!stackTraceArray)
- return error;
+ StringBuilder builder;
for (unsigned i = 0; i < stackTrace.size(); i++) {
- UString stackLevel = stackTrace[i].toString(globalObject->globalExec());
- stackTraceArray->initializeIndex(*globalData, i, jsString(globalData, stackLevel));
+ builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
+ if (i != stackTrace.size() - 1)
+ builder.append('\n');
}
- stackTraceArray->completeInitialization(stackTrace.size());
- error->putDirect(*globalData, globalData->propertyNames->stack, stackTraceArray, ReadOnly | DontDelete);
+
+ error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
}
return error;
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 25ddf764a..ea40447e4 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -34,7 +34,7 @@
#include "JITDriver.h"
#include "Parser.h"
#include "UStringBuilder.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
namespace JSC {
@@ -177,10 +177,9 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scop
}
#if ENABLE(JIT)
-void EvalExecutable::jitCompile(JSGlobalData& globalData)
+bool EvalExecutable::jitCompile(JSGlobalData& globalData)
{
- bool result = jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
+ return jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
}
#endif
@@ -210,8 +209,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- if (!!m_evalCodeBlock && m_evalCodeBlock->canProduceCopyWithBytecode()) {
- BytecodeDestructionBlocker blocker(m_evalCodeBlock.get());
+ if (!!m_evalCodeBlock) {
OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
m_evalCodeBlock = newCodeBlock.release();
@@ -223,7 +221,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
ASSERT(exception);
return exception;
}
- recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
+ recordParse(evalNode->scopeFlags(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
@@ -328,10 +326,9 @@ JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* s
}
#if ENABLE(JIT)
-void ProgramExecutable::jitCompile(JSGlobalData& globalData)
+bool ProgramExecutable::jitCompile(JSGlobalData& globalData)
{
- bool result = jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
+ return jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT(), JITCompilationCanFail);
}
#endif
@@ -346,8 +343,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- if (!!m_programCodeBlock && m_programCodeBlock->canProduceCopyWithBytecode()) {
- BytecodeDestructionBlocker blocker(m_programCodeBlock.get());
+ if (!!m_programCodeBlock) {
OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
m_programCodeBlock = newCodeBlock.release();
@@ -357,7 +353,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
ASSERT(exception);
return exception;
}
- recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
+ recordParse(programNode->scopeFlags(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
@@ -479,33 +475,26 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, Scop
}
#if ENABLE(JIT)
-void FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
+bool FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
{
- bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
+ return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
}
-void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
+bool FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
{
- bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
- ASSERT_UNUSED(result, result);
+ return jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), JITCompilationCanFail);
}
#endif
FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
{
- FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);
- if (codeBlock->canProduceCopyWithBytecode())
- return codeBlock;
- return 0;
+ return baselineCodeBlockFor(kind);
}
PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChainNode* scopeChainNode, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
{
- if (!!codeBlockFor(specializationKind) && codeBlockFor(specializationKind)->canProduceCopyWithBytecode()) {
- BytecodeDestructionBlocker blocker(codeBlockFor(specializationKind).get());
+ if (!!codeBlockFor(specializationKind))
return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
- }
exception = 0;
JSGlobalData* globalData = scopeChainNode->globalData;
@@ -519,7 +508,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChain
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
- recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
+ recordParse(body->scopeFlags(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
OwnPtr<FunctionCodeBlock> result;
ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 69e80b28e..08b39fcf0 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -180,13 +180,14 @@ namespace JSC {
class NativeExecutable : public ExecutableBase {
friend class JIT;
+ friend class LLIntOffsetsExtractor;
public:
typedef ExecutableBase Base;
#if ENABLE(JIT)
static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic)
{
- ASSERT(globalData.canUseJIT());
+ ASSERT(!globalData.interpreter->classicEnabled());
NativeExecutable* executable;
if (!callThunk) {
executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
@@ -228,7 +229,7 @@ namespace JSC {
#if ENABLE(JIT)
void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic)
{
- ASSERT(globalData.canUseJIT());
+ ASSERT(!globalData.interpreter->classicEnabled());
Base::finishCreation(globalData);
m_jitCodeForCall = callThunk;
m_jitCodeForConstruct = constructThunk;
@@ -270,14 +271,14 @@ namespace JSC {
ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
: ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
- , m_features(isInStrictContext ? StrictModeFeature : 0)
+ , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags)
{
}
ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
: ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
- , m_features(isInStrictContext ? StrictModeFeature : 0)
+ , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags)
{
}
@@ -291,10 +292,10 @@ namespace JSC {
int lineNo() const { return m_firstLine; }
int lastLine() const { return m_lastLine; }
- 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; }
+ bool usesEval() const { return m_scopeFlags & UsesEvalFlag; }
+ bool usesArguments() const { return m_scopeFlags & UsesArgumentsFlag; }
+ bool needsActivation() const { return m_hasCapturedVariables || m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); }
+ bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; }
void unlinkCalls();
@@ -310,16 +311,16 @@ namespace JSC {
#endif
}
- void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+ void recordParse(ScopeFlags scopeFlags, bool hasCapturedVariables, int firstLine, int lastLine)
{
- m_features = features;
+ m_scopeFlags = scopeFlags;
m_hasCapturedVariables = hasCapturedVariables;
m_firstLine = firstLine;
m_lastLine = lastLine;
}
SourceCode m_source;
- CodeFeatures m_features;
+ ScopeFlags m_scopeFlags;
bool m_hasCapturedVariables;
int m_firstLine;
int m_lastLine;
@@ -346,7 +347,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
- void jitCompile(JSGlobalData&);
+ bool jitCompile(JSGlobalData&);
#endif
EvalCodeBlock& generatedBytecode()
@@ -421,7 +422,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
- void jitCompile(JSGlobalData&);
+ bool jitCompile(JSGlobalData&);
#endif
ProgramCodeBlock& generatedBytecode()
@@ -520,7 +521,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCodeForCall(JSGlobalData&);
- void jitCompileForCall(JSGlobalData&);
+ bool jitCompileForCall(JSGlobalData&);
#endif
bool isGeneratedForCall() const
@@ -548,7 +549,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCodeForConstruct(JSGlobalData&);
- void jitCompileForConstruct(JSGlobalData&);
+ bool jitCompileForConstruct(JSGlobalData&);
#endif
bool isGeneratedForConstruct() const
@@ -597,14 +598,12 @@ namespace JSC {
}
}
- void jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
+ bool jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
{
- if (kind == CodeForCall) {
- jitCompileForCall(globalData);
- return;
- }
+ if (kind == CodeForCall)
+ return jitCompileForCall(globalData);
ASSERT(kind == CodeForConstruct);
- jitCompileForConstruct(globalData);
+ return jitCompileForConstruct(globalData);
}
#endif
diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h
index 774c5bf6b..e58e6fc74 100644
--- a/Source/JavaScriptCore/runtime/ExecutionHarness.h
+++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h
@@ -46,7 +46,7 @@ inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>&
return true;
}
#endif // ENABLE(LLINT)
- return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType);
+ return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
@@ -61,7 +61,7 @@ inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<Functio
#else
UNUSED_PARAM(kind);
#endif // ENABLE(LLINT)
- return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType);
+ return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
index 2e878bfe3..7f45f0746 100644
--- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
+++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp
@@ -53,7 +53,6 @@ struct DefaultGCActivityCallbackPlatformData {
};
const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
-const CFTimeInterval triggerInterval = 2; // seconds
void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info)
{
@@ -95,6 +94,7 @@ void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLo
void DefaultGCActivityCallback::operator()()
{
+ CFTimeInterval triggerInterval = static_cast<Heap*>(d->context.info)->lastGCLength() * 100.0;
CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval);
}
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index 0d233e355..fbc5787ce 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -36,20 +36,6 @@ using WTF::ThreadSpecific;
namespace JSC {
-IdentifierTable::~IdentifierTable()
-{
- HashSet<StringImpl*>::iterator end = m_table.end();
- for (HashSet<StringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter)
- (*iter)->setIsIdentifier(false);
-}
-
-std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(StringImpl* value)
-{
- std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add(value);
- (*result.first)->setIsIdentifier(true);
- return result;
-}
-
IdentifierTable* createIdentifierTable()
{
return new IdentifierTable;
diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h
index 947c95b33..b9e5a1854 100644
--- a/Source/JavaScriptCore/runtime/Identifier.h
+++ b/Source/JavaScriptCore/runtime/Identifier.h
@@ -22,7 +22,7 @@
#define Identifier_h
#include "JSGlobalData.h"
-#include "ThreadSpecific.h"
+#include <wtf/ThreadSpecific.h>
#include "UString.h"
#include <wtf/WTFThreadData.h>
#include <wtf/text/CString.h>
diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
index 2b874c708..b6fd6ce1f 100644
--- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp
+++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
@@ -37,7 +37,7 @@
#include "JSGlobalObject.h"
#include "UString.h"
#include "WriteBarrier.h"
-#include "dtoa.h"
+#include <wtf/dtoa.h>
#include <wtf/Threading.h>
#include <wtf/dtoa/cached-powers.h>
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index 71d520018..4244bc31c 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -41,6 +41,7 @@ using namespace WTF;
namespace JSC {
+
ASSERT_CLASS_FITS_IN_CELL(JSArray);
ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray);
@@ -104,23 +105,16 @@ const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0, CRE
// This value is capped by the constant FIRST_VECTOR_GROW defined above.
static unsigned lastArraySize = 0;
-static inline size_t storageSize(unsigned vectorLength)
+static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
{
- ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);
-
- // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
- // - as asserted above - the following calculation cannot overflow.
- size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>));
- // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
- // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
- ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))));
-
- return size;
+ return length <= MIN_SPARSE_ARRAY_INDEX || length / minDensityMultiplier <= numValues;
}
-static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
+static bool reject(ExecState* exec, bool throwException, const char* message)
{
- return length <= MIN_SPARSE_ARRAY_INDEX || length / minDensityMultiplier <= numValues;
+ if (throwException)
+ throwTypeError(exec, message);
+ return false;
}
#if !CHECK_ARRAY_CONSISTENCY
@@ -213,7 +207,7 @@ inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(J
return result;
}
-inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value)
+inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow)
{
std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i);
SparseArrayEntry& entry = result.first->second;
@@ -223,14 +217,15 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
// extensible, this is not the right thing to have done - so remove again.
if (result.second && !array->isExtensible()) {
remove(result.first);
- // FIXME: should throw in strict mode.
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
if (!(entry.attributes & Accessor)) {
if (entry.attributes & ReadOnly) {
- // FIXME: should throw if being called from strict mode.
- // throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
@@ -243,8 +238,8 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
JSObject* setter = asGetterSetter(accessor)->setter();
if (!setter) {
- // FIXME: should throw if being called from strict mode.
- // throwTypeError(exec, "setting a property that has only a getter");
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
@@ -255,6 +250,24 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
call(exec, setter, callType, callData, array, args);
}
+inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow)
+{
+ std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i);
+ SparseArrayEntry& entry = result.first->second;
+
+ // To save a separate find & add, we first always add to the sparse map.
+ // In the uncommon case that this is a new property, and the array is not
+ // extensible, this is not the right thing to have done - so remove again.
+ if (result.second && !array->isExtensible()) {
+ remove(result.first);
+ return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
+ }
+
+ entry.attributes = 0;
+ entry.set(exec->globalData(), array, value);
+ return true;
+}
+
inline void SparseArrayEntry::get(PropertySlot& slot) const
{
JSValue value = Base::get();
@@ -395,13 +408,6 @@ void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, Prope
entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor);
}
-static bool reject(ExecState* exec, bool throwException, const char* message)
-{
- if (throwException)
- throwTypeError(exec, message);
- return false;
-}
-
// Defined in ES5.1 8.12.9
bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, PropertyDescriptor& descriptor, bool throwException)
{
@@ -414,8 +420,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
// state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode').
if (!descriptor.attributes()) {
ASSERT(!descriptor.isAccessorDescriptor());
- putByIndex(this, exec, index, descriptor.value());
- return true;
+ return putDirectIndex(exec, index, descriptor.value(), throwException);
}
enterDictionaryMode(exec->globalData());
@@ -721,7 +726,7 @@ void JSArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName,
bool isArrayIndex;
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex) {
- putByIndex(thisObject, exec, i, value);
+ putByIndex(thisObject, exec, i, value, slot.isStrictMode());
return;
}
@@ -738,7 +743,7 @@ void JSArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName,
JSObject::put(thisObject, exec, propertyName, value, slot);
}
-void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value)
+void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
{
JSArray* thisObject = jsCast<JSArray*>(cell);
thisObject->checkConsistency();
@@ -765,17 +770,17 @@ void JSArray::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue valu
// Handle 2^32-1 - this is not an array index (see ES5.1 15.4), and is treated as a regular property.
if (UNLIKELY(i > MAX_ARRAY_INDEX)) {
- PutPropertySlot slot;
+ PutPropertySlot slot(shouldThrow);
thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, i), value, slot);
return;
}
// For all other cases, call putByIndexBeyondVectorLength.
- thisObject->putByIndexBeyondVectorLength(exec, i, value);
+ thisObject->putByIndexBeyondVectorLength(exec, i, value, shouldThrow);
thisObject->checkConsistency();
}
-NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value)
+void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
{
JSGlobalData& globalData = exec->globalData();
@@ -806,7 +811,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
// We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
allocateSparseMap(exec->globalData());
map = m_sparseValueMap;
- map->put(exec, this, i, value);
+ map->put(exec, this, i, value, shouldThrow);
return;
}
@@ -815,7 +820,8 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
if (i >= length) {
// Prohibit growing the array if length is not writable.
if (map->lengthIsReadOnly() || !isExtensible()) {
- // FIXME: should throw in strict mode.
+ if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
}
length = i + 1;
@@ -826,7 +832,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
// 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)) {
- map->put(exec, this, i, value);
+ map->put(exec, this, i, value, shouldThrow);
return;
}
@@ -848,6 +854,77 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
valueSlot.set(globalData, this, value);
}
+bool JSArray::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, bool shouldThrow)
+{
+ JSGlobalData& globalData = exec->globalData();
+
+ // i should be a valid array index that is outside of the current vector.
+ ASSERT(i >= m_vectorLength);
+ ASSERT(i <= MAX_ARRAY_INDEX);
+
+ ArrayStorage* storage = m_storage;
+ SparseArrayValueMap* map = m_sparseValueMap;
+
+ // First, handle cases where we don't currently have a sparse map.
+ if (LIKELY(!map)) {
+ // If the array is not extensible, we should have entered dictionary mode, and created the spare map.
+ ASSERT(isExtensible());
+
+ // Update m_length if necessary.
+ if (i >= storage->m_length)
+ storage->m_length = 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))) {
+ // success! - reread m_storage since it has likely been reallocated, and store to the vector.
+ storage = m_storage;
+ storage->m_vector[i].set(globalData, 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.
+ allocateSparseMap(exec->globalData());
+ map = m_sparseValueMap;
+ return map->putDirect(exec, this, i, value, shouldThrow);
+ }
+
+ // Update m_length if necessary.
+ unsigned length = storage->m_length;
+ if (i >= length) {
+ // Prohibit growing the array if length is not writable.
+ if (map->lengthIsReadOnly())
+ return reject(exec, shouldThrow, StrictModeReadonlyPropertyWriteError);
+ if (!isExtensible())
+ return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible.");
+ length = i + 1;
+ storage->m_length = length;
+ }
+
+ // 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))
+ return map->putDirect(exec, this, i, value, shouldThrow);
+
+ // Reread m_storage afterincreaseVectorLength, update m_numValuesInVector.
+ storage = m_storage;
+ storage->m_numValuesInVector = numValuesInArray;
+
+ // Copy all values from the map into the vector, and delete the map.
+ WriteBarrier<Unknown>* vector = storage->m_vector;
+ SparseArrayValueMap::const_iterator end = map->end();
+ for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
+ vector[it->first].set(globalData, this, it->second.getNonSparseMode());
+ deallocateSparseMap();
+
+ // Store the new property into the vector.
+ WriteBarrier<Unknown>& valueSlot = vector[i];
+ if (!valueSlot)
+ ++storage->m_numValuesInVector;
+ valueSlot.set(globalData, this, value);
+ return true;
+}
+
bool JSArray::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
JSArray* thisObject = jsCast<JSArray*>(cell);
@@ -1220,18 +1297,19 @@ void JSArray::push(ExecState* exec, JSValue value)
// Pushing to an array of length 2^32-1 stores the property, but throws a range error.
if (UNLIKELY(storage->m_length == 0xFFFFFFFFu)) {
- methodTable()->putByIndex(this, exec, storage->m_length, value);
+ methodTable()->putByIndex(this, exec, storage->m_length, value, true);
// Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d.
- throwError(exec, createRangeError(exec, "Invalid array length"));
+ if (!exec->hadException())
+ throwError(exec, createRangeError(exec, "Invalid array length"));
return;
}
// Handled the same as putIndex.
- putByIndexBeyondVectorLength(exec, storage->m_length, value);
+ putByIndexBeyondVectorLength(exec, storage->m_length, value, true);
checkConsistency();
}
-void JSArray::shiftCount(ExecState* exec, unsigned count)
+bool JSArray::shiftCount(ExecState*, unsigned count)
{
ASSERT(count > 0);
@@ -1239,32 +1317,15 @@ void JSArray::shiftCount(ExecState* exec, unsigned count)
unsigned oldLength = storage->m_length;
- if (!oldLength)
- return;
-
- if (oldLength != storage->m_numValuesInVector) {
- // If m_length and m_numValuesInVector aren't the same, we have a sparse vector
- // which means we need to go through each entry looking for the the "empty"
- // slots and then fill them with possible properties. See ECMA spec.
- // 15.4.4.9 steps 11 through 13.
- for (unsigned i = count; i < oldLength; ++i) {
- if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
- PropertySlot slot(this);
- JSValue p = prototype();
- if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
- methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i));
- }
- }
-
- storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
+ // If the array contains holes or is otherwise in an abnormal state,
+ // use the generic algorithm in ArrayPrototype.
+ if (oldLength != storage->m_numValuesInVector || inSparseMode())
+ return false;
- // Need to decrement numValuesInvector based on number of real entries
- for (unsigned i = 0; i < (unsigned)count; ++i)
- if ((i < m_vectorLength) && (storage->m_vector[i]))
- --storage->m_numValuesInVector;
- } else
- storage->m_numValuesInVector -= count;
+ if (!oldLength)
+ return true;
+ storage->m_numValuesInVector -= count;
storage->m_length -= count;
if (m_vectorLength) {
@@ -1280,30 +1341,20 @@ void JSArray::shiftCount(ExecState* exec, unsigned count)
m_indexBias += count;
}
}
+ return true;
}
-
-void JSArray::unshiftCount(ExecState* exec, unsigned count)
+
+// Returns true if the unshift can be handled, false to fallback.
+bool JSArray::unshiftCount(ExecState* exec, unsigned count)
{
ArrayStorage* storage = m_storage;
unsigned length = storage->m_length;
- if (length != storage->m_numValuesInVector) {
- // If m_length and m_numValuesInVector aren't the same, we have a sparse vector
- // which means we need to go through each entry looking for the the "empty"
- // slots and then fill them with possible properties. See ECMA spec.
- // 15.4.4.13 steps 8 through 10.
- for (unsigned i = 0; i < length; ++i) {
- if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
- PropertySlot slot(this);
- JSValue p = prototype();
- if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
- methodTable()->putByIndex(this, exec, i, slot.getValue(exec, i));
- }
- }
- }
-
- storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
-
+ // If the array contains holes or is otherwise in an abnormal state,
+ // use the generic algorithm in ArrayPrototype.
+ if (length != storage->m_numValuesInVector || inSparseMode())
+ return false;
+
if (m_indexBias >= count) {
m_indexBias -= count;
char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(WriteBarrier<Unknown>);
@@ -1312,12 +1363,13 @@ void JSArray::unshiftCount(ExecState* exec, unsigned count)
m_vectorLength += count;
} else if (!unshiftCountSlowCase(exec->globalData(), count)) {
throwOutOfMemoryError(exec);
- return;
+ return true;
}
WriteBarrier<Unknown>* vector = m_storage->m_vector;
for (unsigned i = 0; i < count; i++)
vector[i].clear();
+ return true;
}
void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index 3bb4c6320..ad98d6619 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -85,7 +85,8 @@ namespace JSC {
}
// These methods may mutate the contents of the map
- void put(ExecState*, JSArray*, unsigned, JSValue);
+ void put(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
+ bool putDirect(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow);
std::pair<iterator, bool> add(JSArray*, unsigned);
iterator find(unsigned i) { return m_map.find(i); }
// This should ASSERT the remove is valid (check the result of the find).
@@ -122,11 +123,17 @@ namespace JSC {
uintptr_t m_padding;
#endif
WriteBarrier<Unknown> m_vector[1];
+
+ static ptrdiff_t lengthOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_length); }
+ static ptrdiff_t numValuesInVectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector); }
+ static ptrdiff_t allocBaseOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_allocBase); }
+ static ptrdiff_t vectorOffset() { return OBJECT_OFFSETOF(ArrayStorage, m_vector); }
};
class JSArray : public JSNonFinalObject {
friend class LLIntOffsetsExtractor;
friend class Walker;
+ friend class JIT;
protected:
JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*);
@@ -153,7 +160,19 @@ namespace JSC {
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ // This is similar to the JSObject::putDirect* methods:
+ // - the prototype chain is not consulted
+ // - accessors are not called.
+ // This method creates a property with attributes writable, enumerable and configurable all set to true.
+ bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow = true)
+ {
+ if (canSetIndex(propertyName)) {
+ setIndex(exec->globalData(), propertyName, value);
+ return true;
+ }
+ return putDirectIndexBeyondVectorLength(exec, propertyName, value, shouldThrow);
+ }
static JS_EXPORTDATA const ClassInfo s_info;
@@ -168,8 +187,8 @@ namespace JSC {
void push(ExecState*, JSValue);
JSValue pop(ExecState*);
- void shiftCount(ExecState*, unsigned count);
- void unshiftCount(ExecState*, unsigned count);
+ bool shiftCount(ExecState*, unsigned count);
+ bool unshiftCount(ExecState*, unsigned count);
bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
JSValue getIndex(unsigned i)
@@ -262,6 +281,7 @@ namespace JSC {
JS_EXPORT_PRIVATE void setSubclassData(void*);
private:
+ static size_t storageSize(unsigned vectorLength);
bool isLengthWritable()
{
SparseArrayValueMap* map = m_sparseValueMap;
@@ -275,7 +295,8 @@ namespace JSC {
void deallocateSparseMap();
bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
- void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue);
+ void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
unsigned getNewVectorLength(unsigned desiredLength);
bool increaseVectorLength(JSGlobalData&, unsigned newLength);
@@ -293,6 +314,10 @@ namespace JSC {
// FIXME: Maybe SparseArrayValueMap should be put into its own JSCell?
SparseArrayValueMap* m_sparseValueMap;
void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily.
+
+ static ptrdiff_t sparseValueMapOffset() { return OBJECT_OFFSETOF(JSArray, m_sparseValueMap); }
+ static ptrdiff_t subclassDataOffset() { return OBJECT_OFFSETOF(JSArray, m_subclassData); }
+ static ptrdiff_t indexBiasOffset() { return OBJECT_OFFSETOF(JSArray, m_indexBias); }
};
inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
@@ -334,6 +359,30 @@ namespace JSC {
return i;
}
-} // namespace JSC
+// The definition of MAX_STORAGE_VECTOR_LENGTH is dependant on the definition storageSize
+// function below - the MAX_STORAGE_VECTOR_LENGTH limit is defined such that the storage
+// size calculation cannot overflow. (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) +
+// (vectorLength * sizeof(WriteBarrier<Unknown>)) must be <= 0xFFFFFFFFU (which is maximum value of size_t).
+#define MAX_STORAGE_VECTOR_LENGTH static_cast<unsigned>((0xFFFFFFFFU - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>))
+
+// These values have to be macros to be used in max() and min() without introducing
+// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
+#define MIN_SPARSE_ARRAY_INDEX 10000U
+#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
+ inline size_t JSArray::storageSize(unsigned vectorLength)
+ {
+ ASSERT(vectorLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+ // MAX_STORAGE_VECTOR_LENGTH is defined such that provided (vectorLength <= MAX_STORAGE_VECTOR_LENGTH)
+ // - as asserted above - the following calculation cannot overflow.
+ size_t size = (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>)) + (vectorLength * sizeof(WriteBarrier<Unknown>));
+ // Assertion to detect integer overflow in previous calculation (should not be possible, provided that
+ // MAX_STORAGE_VECTOR_LENGTH is correctly defined).
+ ASSERT(((size - (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))) / sizeof(WriteBarrier<Unknown>) == vectorLength) && (size >= (sizeof(ArrayStorage) - sizeof(WriteBarrier<Unknown>))));
+
+ return size;
+ }
+
+ } // namespace JSC
#endif // JSArray_h
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp
index 3df21e6f5..39ea4d0b9 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp
@@ -102,7 +102,7 @@ void JSByteArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyN
JSObject::put(thisObject, exec, propertyName, value, slot);
}
-void JSByteArray::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value)
+void JSByteArray::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool)
{
jsCast<JSByteArray*>(cell)->setIndex(exec, propertyName, value);
}
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h
index d1f4ad630..06181d901 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.h
+++ b/Source/JavaScriptCore/runtime/JSByteArray.h
@@ -92,7 +92,7 @@ namespace JSC {
JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
- JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue);
+ JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow);
JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode);
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 4703b681b..f08d0260a 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -97,14 +97,23 @@ bool JSCell::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i
void JSCell::put(JSCell* cell, ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
{
+ if (cell->isString()) {
+ JSValue(cell).putToPrimitive(exec, identifier, value, slot);
+ return;
+ }
JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
thisObject->methodTable()->put(thisObject, exec, identifier, value, slot);
}
-void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value)
+void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow)
{
+ if (cell->isString()) {
+ PutPropertySlot slot(shouldThrow);
+ JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot);
+ return;
+ }
JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject());
- thisObject->methodTable()->putByIndex(thisObject, exec, identifier, value);
+ thisObject->methodTable()->putByIndex(thisObject, exec, identifier, value, shouldThrow);
}
bool JSCell::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& identifier)
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 78d2d0801..2ef359b76 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -107,7 +107,7 @@ namespace JSC {
const ClassInfo* validatedClassInfo() const;
const MethodTable* methodTable() const;
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index 863073338..882f86fa0 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -72,8 +72,6 @@
#include "config.h"
#include "JSDateMath.h"
-#include "Assertions.h"
-#include "ASCIICType.h"
#include "CurrentTime.h"
#include "JSObject.h"
#include "MathExtras.h"
@@ -86,6 +84,8 @@
#include <limits>
#include <stdint.h>
#include <time.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Assertions.h>
#include <wtf/text/StringBuilder.h>
#if HAVE(ERRNO_H)
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 253128279..fa798f41a 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -181,7 +181,15 @@ JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identi
{
JSFunction* thisObj = asFunction(slotBase);
ASSERT(!thisObj->isHostFunction());
- return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+ JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
+
+ // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
+ if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
+ return caller;
+ JSFunction* function = asFunction(caller);
+ if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
+ return caller;
+ return throwTypeError(exec, "Function.caller used to retrieve strict caller");
}
JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
@@ -329,21 +337,80 @@ void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyNa
Base::put(thisObject, exec, propertyName, value, slot);
return;
}
- if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) {
+ if (slot.isStrictMode())
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
+ }
Base::put(thisObject, exec, propertyName, value, slot);
}
bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
JSFunction* thisObject = jsCast<JSFunction*>(cell);
- if (thisObject->isHostFunction())
- return Base::deleteProperty(thisObject, exec, propertyName);
- if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
+ // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
+ if (!thisObject->isHostFunction() && !exec->globalData().isInDefineOwnProperty()
+ && (propertyName == exec->propertyNames().arguments
+ || propertyName == exec->propertyNames().length
+ || propertyName == exec->propertyNames().prototype
+ || propertyName == exec->propertyNames().caller))
return false;
return Base::deleteProperty(thisObject, exec, propertyName);
}
+bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+ JSFunction* thisObject = jsCast<JSFunction*>(object);
+ if (thisObject->isHostFunction())
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+
+ if (propertyName == exec->propertyNames().prototype) {
+ // Make sure prototype has been reified, such that it can only be overwritten
+ // following the rules set out in ECMA-262 8.12.9.
+ PropertySlot slot;
+ thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ } else if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) {
+ if (!object->isExtensible()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
+ return false;
+ }
+ if (descriptor.configurablePresent() && descriptor.configurable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.enumerablePresent() && descriptor.enumerable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.isAccessorDescriptor()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
+ return false;
+ }
+ if (descriptor.writablePresent() && descriptor.writable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
+ return false;
+ }
+ if (!descriptor.value())
+ return true;
+ if (propertyName == exec->propertyNames().arguments && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject)))
+ return true;
+ if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount())))
+ return true;
+ if (propertyName == exec->propertyNames().caller && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject)))
+ return true;
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
+ return false;
+ }
+
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+}
+
// ECMA 13.2.2 [[Construct]]
ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
{
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index 6e8557f59..288181060 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -133,6 +133,7 @@ namespace JSC {
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties);
+ static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index 2bdc28ab7..f138e75fb 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -193,7 +193,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
-#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
+#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
#if USE(CF)
CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
@@ -213,13 +213,16 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#endif
#endif
#if ENABLE(JIT)
-#if ENABLE(CLASSIC_INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)
if (m_canUseJIT)
m_canUseJIT = executableAllocator.isValid();
+
+ if (!Options::useJIT)
+ m_canUseJIT = false;
#endif
jitStubs = adoptPtr(new JITThunks(this));
#endif
-
+
interpreter->initialize(&llintData, this->canUseJIT());
initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 7e54c00db..acbcee816 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -47,6 +47,7 @@
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
+#include <wtf/SimpleStats.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/WTFThreadData.h>
#if ENABLE(REGEXP_TRACING)
@@ -201,6 +202,7 @@ namespace JSC {
SmallStrings smallStrings;
NumericStrings numericStrings;
DateInstanceCache dateInstanceCache;
+ WTF::SimpleStats machineCodeBytesPerBytecodeWordForBaselineJIT;
Vector<CodeBlock*> codeBlocksBeingCompiled;
void startedCompiling(CodeBlock* codeBlock)
{
@@ -229,7 +231,7 @@ namespace JSC {
#if !ENABLE(JIT)
bool canUseJIT() { return false; } // interpreter only
-#elif !ENABLE(CLASSIC_INTERPRETER)
+#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT)
bool canUseJIT() { return true; } // jit only
#else
bool canUseJIT() { return m_canUseJIT; }
@@ -367,7 +369,7 @@ namespace JSC {
JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
static JSGlobalData*& sharedInstanceInternal();
void createNativeThunk();
-#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
+#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT))
bool m_canUseJIT;
#endif
#if ENABLE(GC_VALIDATION)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index db8ee1d85..75789e602 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -35,7 +35,7 @@
#include "Nodes.h"
#include "Parser.h"
#include "UStringBuilder.h"
-#include "dtoa.h"
+#include <wtf/dtoa.h>
#include <stdio.h>
#include <stdlib.h>
#include <wtf/ASCIICType.h>
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
index 682400292..337e3a70c 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -70,7 +70,7 @@ void JSNotAnObject::put(JSCell*, ExecState* exec, const Identifier& , JSValue, P
ASSERT_UNUSED(exec, exec->hadException());
}
-void JSNotAnObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue)
+void JSNotAnObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue, bool)
{
ASSERT_UNUSED(exec, exec->hadException());
}
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h
index 51ba456e1..5f80688b0 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h
@@ -73,7 +73,7 @@ namespace JSC {
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index 83b118429..436e78353 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -704,12 +704,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue);
if (filteredValue.isUndefined())
array->methodTable()->deletePropertyByIndex(array, m_exec, indexStack.last());
- else {
- if (isJSArray(array) && array->canSetIndex(indexStack.last()))
- array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue);
- else
- array->methodTable()->putByIndex(array, m_exec, indexStack.last(), filteredValue);
- }
+ else
+ array->putDirectIndex(m_exec, indexStack.last(), filteredValue, false);
if (m_exec->hadException())
return jsNull();
indexStack.last()++;
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index acc4a181e..1bdb90ff6 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -119,11 +119,6 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned
return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot);
}
-static void throwSetterError(ExecState* exec)
-{
- throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
-}
-
// ECMA 8.6.2.2
void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
@@ -161,7 +156,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
if (slot.isStrictMode())
- throwSetterError(exec);
+ throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
return;
}
@@ -190,9 +185,9 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName
return;
}
-void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value)
+void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
{
- PutPropertySlot slot;
+ PutPropertySlot slot(shouldThrow);
JSObject* thisObject = jsCast<JSObject*>(cell);
thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot);
}
@@ -707,7 +702,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
if (descriptor.isGenericDescriptor()) {
if (!current.attributesEqual(descriptor)) {
object->methodTable()->deleteProperty(object, exec, propertyName);
- return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+ return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
}
return true;
}
@@ -720,7 +715,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
return false;
}
object->methodTable()->deleteProperty(object, exec, propertyName);
- return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+ return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
}
// Changing the value and attributes of an existing property
@@ -742,7 +737,7 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
if (current.attributesEqual(descriptor) && !descriptor.value())
return true;
object->methodTable()->deleteProperty(object, exec, propertyName);
- return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
+ return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
}
// Changing the accessor functions of an existing accessor property
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index c117cffaf..3f3d281cf 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -109,7 +109,7 @@ namespace JSC {
bool allowsAccessFrom(ExecState*);
JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
+ JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
// putDirect is effectively an unchecked vesion of 'defineOwnProperty':
// - the prototype chain is not consulted
@@ -834,21 +834,20 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot
inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (UNLIKELY(!isCell())) {
- JSObject* thisObject = synthesizeObject(exec);
- thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot);
+ putToPrimitive(exec, propertyName, value, slot);
return;
}
asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
}
-inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
+inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
{
if (UNLIKELY(!isCell())) {
- JSObject* thisObject = synthesizeObject(exec);
- thisObject->methodTable()->putByIndex(thisObject, exec, propertyName, value);
+ PutPropertySlot slot(shouldThrow);
+ putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot);
return;
}
- asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value);
+ asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
}
// --- JSValue inlines ----------------------------
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index cfa7d03b4..e84ce3620 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -65,9 +65,10 @@ void JSString::resolveRope(ExecState* exec) const
if (is8Bit()) {
LChar* buffer;
- if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
+ if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
+ Heap::heap(this)->reportExtraMemoryCost(newImpl->cost());
m_value = newImpl.release();
- else {
+ } else {
outOfMemory(exec);
return;
}
@@ -92,9 +93,10 @@ void JSString::resolveRope(ExecState* exec) const
}
UChar* buffer;
- if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
+ if (RefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer)) {
+ Heap::heap(this)->reportExtraMemoryCost(newImpl->cost());
m_value = newImpl.release();
- else {
+ } else {
outOfMemory(exec);
return;
}
diff --git a/Source/JavaScriptCore/runtime/JSStringBuilder.h b/Source/JavaScriptCore/runtime/JSStringBuilder.h
index b7e7e781e..1a2b812f0 100644
--- a/Source/JavaScriptCore/runtime/JSStringBuilder.h
+++ b/Source/JavaScriptCore/runtime/JSStringBuilder.h
@@ -29,7 +29,7 @@
#include "ExceptionHelpers.h"
#include "JSString.h"
#include "UStringConcatenate.h"
-#include "Vector.h"
+#include <wtf/Vector.h>
namespace JSC {
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index e3843f02b..36697c60c 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -27,6 +27,7 @@
#include "BooleanPrototype.h"
#include "Error.h"
#include "ExceptionHelpers.h"
+#include "GetterSetter.h"
#include "JSGlobalObject.h"
#include "JSFunction.h"
#include "JSNotAnObject.h"
@@ -90,30 +91,85 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
return exec->globalThisValue();
}
-JSObject* JSValue::synthesizeObject(ExecState* exec) const
+JSObject* JSValue::synthesizePrototype(ExecState* exec) const
{
- ASSERT(!isCell());
+ if (isCell()) {
+ ASSERT(isString());
+ return exec->lexicalGlobalObject()->stringPrototype();
+ }
+
if (isNumber())
- return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
+ return exec->lexicalGlobalObject()->numberPrototype();
if (isBoolean())
- return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
+ return exec->lexicalGlobalObject()->booleanPrototype();
ASSERT(isUndefinedOrNull());
throwError(exec, createNotAnObjectError(exec, *this));
return JSNotAnObject::create(exec);
}
-JSObject* JSValue::synthesizePrototype(ExecState* exec) const
+// ECMA 8.7.2
+void JSValue::putToPrimitive(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
- ASSERT(!isCell());
- if (isNumber())
- return exec->lexicalGlobalObject()->numberPrototype();
- if (isBoolean())
- return exec->lexicalGlobalObject()->booleanPrototype();
+ JSGlobalData& globalData = exec->globalData();
- ASSERT(isUndefinedOrNull());
- throwError(exec, createNotAnObjectError(exec, *this));
- return JSNotAnObject::create(exec);
+ // Check if there are any setters or getters in the prototype chain
+ JSObject* obj = synthesizePrototype(exec);
+ JSValue prototype;
+ if (propertyName != exec->propertyNames().underscoreProto) {
+ for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
+ prototype = obj->prototype();
+ if (prototype.isNull()) {
+ if (slot.isStrictMode())
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ return;
+ }
+ }
+ }
+
+ for (; ; obj = asObject(prototype)) {
+ unsigned attributes;
+ JSCell* specificValue;
+ size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+ if (offset != WTF::notFound) {
+ if (attributes & ReadOnly) {
+ if (slot.isStrictMode())
+ throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+ return;
+ }
+
+ JSValue gs = obj->getDirectOffset(offset);
+ if (gs.isGetterSetter()) {
+ JSObject* setterFunc = asGetterSetter(gs)->setter();
+ if (!setterFunc) {
+ if (slot.isStrictMode())
+ throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
+ return;
+ }
+
+ CallData callData;
+ CallType callType = setterFunc->methodTable()->getCallData(setterFunc, callData);
+ MarkedArgumentBuffer args;
+ args.append(value);
+
+ // If this is WebCore's global object then we need to substitute the shell.
+ call(exec, setterFunc, callType, callData, *this, args);
+ return;
+ }
+
+ // If there's an existing property on the object or one of its
+ // prototypes it should be replaced, so break here.
+ break;
+ }
+
+ prototype = obj->prototype();
+ if (prototype.isNull())
+ break;
+ }
+
+ if (slot.isStrictMode())
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ return;
}
char* JSValue::description()
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index 9f797e05d..a6f359360 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -221,7 +221,8 @@ namespace JSC {
JSValue get(ExecState*, unsigned propertyName) const;
JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- void put(ExecState*, unsigned propertyName, JSValue);
+ void putToPrimitive(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
JSObject* toThisObject(ExecState*) const;
@@ -252,8 +253,6 @@ namespace JSC {
JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
- JSObject* synthesizeObject(ExecState*) const;
-
#if USE(JSVALUE32_64)
/*
* On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index 8d058f1fc..bcfe4ab89 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -32,7 +32,7 @@
#include "JSObject.h"
#include "Register.h"
#include "SymbolTable.h"
-#include "UnusedParam.h"
+#include <wtf/UnusedParam.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/UnusedParam.h>
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index fb90bcd17..8f8c3c00f 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -29,7 +29,7 @@
#include "JSString.h"
#include "Operations.h"
#include "Uint16WithFraction.h"
-#include "dtoa.h"
+#include <wtf/dtoa.h>
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
#include <wtf/Vector.h>
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index 5500508cf..c4bf39db4 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -45,6 +45,8 @@
namespace JSC { namespace Options {
+bool useJIT;
+
unsigned maximumOptimizationCandidateInstructionCount;
unsigned maximumFunctionForCallInlineCandidateInstructionCount;
@@ -52,15 +54,12 @@ unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
unsigned maximumInliningDepth;
-int32_t executionCounterValueForJITAfterWarmUp;
-int32_t executionCounterValueForDontJITAnytimeSoon;
-int32_t executionCounterValueForJITSoon;
+int32_t thresholdForJITAfterWarmUp;
+int32_t thresholdForJITSoon;
-int32_t executionCounterValueForOptimizeAfterWarmUp;
-int32_t executionCounterValueForOptimizeAfterLongWarmUp;
-int32_t executionCounterValueForDontOptimizeAnytimeSoon;
-int32_t executionCounterValueForOptimizeSoon;
-int32_t executionCounterValueForOptimizeNextInvocation;
+int32_t thresholdForOptimizeAfterWarmUp;
+int32_t thresholdForOptimizeAfterLongWarmUp;
+int32_t thresholdForOptimizeSoon;
int32_t executionCounterIncrementForLoop;
int32_t executionCounterIncrementForReturn;
@@ -96,6 +95,19 @@ unsigned numberOfGCMarkers;
unsigned opaqueRootMergeThreshold;
#if ENABLE(RUN_TIME_HEURISTICS)
+static bool parse(const char* string, bool& value)
+{
+ if (!strcasecmp(string, "true") || !strcasecmp(string, "yes") || !strcmp(string, "1")) {
+ value = true;
+ return true;
+ }
+ if (!strcasecmp(string, "false") || !strcasecmp(string, "no") || !strcmp(string, "0")) {
+ value = false;
+ return true;
+ }
+ return false;
+}
+
static bool parse(const char* string, int32_t& value)
{
return sscanf(string, "%d", &value) == 1;
@@ -134,22 +146,21 @@ void setHeuristic(T& variable, const char* name, U value)
void initializeOptions()
{
- SET(maximumOptimizationCandidateInstructionCount, 1100);
+ SET(useJIT, true);
+
+ SET(maximumOptimizationCandidateInstructionCount, 10000);
SET(maximumFunctionForCallInlineCandidateInstructionCount, 180);
SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100);
SET(maximumInliningDepth, 5);
- SET(executionCounterValueForJITAfterWarmUp, -100);
- SET(executionCounterValueForDontJITAnytimeSoon, std::numeric_limits<int32_t>::min());
- SET(executionCounterValueForJITSoon, -100);
+ SET(thresholdForJITAfterWarmUp, 100);
+ SET(thresholdForJITSoon, 100);
- SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
- SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
- SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());
- SET(executionCounterValueForOptimizeSoon, -1000);
- SET(executionCounterValueForOptimizeNextInvocation, 0);
+ SET(thresholdForOptimizeAfterWarmUp, 1000);
+ SET(thresholdForOptimizeAfterLongWarmUp, 5000);
+ SET(thresholdForOptimizeSoon, 1000);
SET(executionCounterIncrementForLoop, 1);
SET(executionCounterIncrementForReturn, 15);
@@ -193,15 +204,11 @@ void initializeOptions()
if (cpusToUse < 1)
cpusToUse = 1;
- cpusToUse = 1;
-
SET(numberOfGCMarkers, cpusToUse);
- ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
- ASSERT(executionCounterValueForOptimizeAfterLongWarmUp <= executionCounterValueForOptimizeAfterWarmUp);
- ASSERT(executionCounterValueForOptimizeAfterWarmUp <= executionCounterValueForOptimizeSoon);
- ASSERT(executionCounterValueForOptimizeAfterWarmUp < 0);
- ASSERT(executionCounterValueForOptimizeSoon <= executionCounterValueForOptimizeNextInvocation);
+ ASSERT(thresholdForOptimizeAfterLongWarmUp >= thresholdForOptimizeAfterWarmUp);
+ ASSERT(thresholdForOptimizeAfterWarmUp >= thresholdForOptimizeSoon);
+ ASSERT(thresholdForOptimizeAfterWarmUp >= 0);
// Compute the maximum value of the reoptimization retry counter. This is simply
// the largest value at which we don't overflow the execute counter, when using it
@@ -209,11 +216,11 @@ void initializeOptions()
// up being 18, so this loop is not so terrible; it probably takes up ~100 cycles
// total on a 32-bit processor.
reoptimizationRetryCounterMax = 0;
- while ((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()))
+ while ((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << (reoptimizationRetryCounterMax + 1)) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()))
reoptimizationRetryCounterMax++;
- ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) < 0);
- ASSERT((static_cast<int64_t>(executionCounterValueForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) >= static_cast<int64_t>(std::numeric_limits<int32_t>::min()));
+ ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) > 0);
+ ASSERT((static_cast<int64_t>(thresholdForOptimizeAfterLongWarmUp) << reoptimizationRetryCounterMax) <= static_cast<int64_t>(std::numeric_limits<int32_t>::max()));
}
} } // namespace JSC::Options
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index b9e68f90c..fae6a7376 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -30,6 +30,8 @@
namespace JSC { namespace Options {
+extern bool useJIT;
+
extern unsigned maximumOptimizationCandidateInstructionCount;
extern unsigned maximumFunctionForCallInlineCandidateInstructionCount;
@@ -37,15 +39,13 @@ extern unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc.
-extern int32_t executionCounterValueForJITAfterWarmUp;
-extern int32_t executionCounterValueForDontJITAnytimeSoon;
-extern int32_t executionCounterValueForJITSoon;
+extern int32_t thresholdForJITAfterWarmUp;
+extern int32_t thresholdForJITSoon;
-extern int32_t executionCounterValueForOptimizeAfterWarmUp;
-extern int32_t executionCounterValueForOptimizeAfterLongWarmUp;
-extern int32_t executionCounterValueForDontOptimizeAnytimeSoon;
-extern int32_t executionCounterValueForOptimizeSoon;
-extern int32_t executionCounterValueForOptimizeNextInvocation;
+extern int32_t thresholdForOptimizeAfterWarmUp;
+extern int32_t thresholdForOptimizeAfterLongWarmUp;
+extern int32_t thresholdForOptimizeSoon;
+extern int32_t thresholdForOptimizeNextInvocation;
extern int32_t executionCounterIncrementForLoop;
extern int32_t executionCounterIncrementForReturn;
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
index 0cb629584..236a8e5ae 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -206,22 +206,6 @@ bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
return true;
}
-unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
-{
- unsigned mismatch = other.m_attributes ^ m_attributes;
- unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
- unsigned newAttributes = m_attributes & defaultAttributes;
- if (sharedSeen & WritablePresent && mismatch & ReadOnly)
- newAttributes ^= ReadOnly;
- if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
- newAttributes ^= DontDelete;
- if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
- newAttributes ^= DontEnum;
- if (isAccessorDescriptor() && other.isDataDescriptor())
- newAttributes |= ReadOnly;
- return newAttributes;
-}
-
unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
{
unsigned currentAttributes = current.m_attributes;
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.h b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
index 98af02e66..2c3878f57 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.h
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.h
@@ -70,7 +70,6 @@ namespace JSC {
bool getterPresent() const { return m_getter; }
bool equalTo(ExecState* exec, const PropertyDescriptor& other) const;
bool attributesEqual(const PropertyDescriptor& other) const;
- unsigned attributesWithOverride(const PropertyDescriptor& other) const;
unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const;
private:
diff --git a/Source/JavaScriptCore/runtime/PropertySlot.cpp b/Source/JavaScriptCore/runtime/PropertySlot.cpp
index edabd7a6e..8ac874115 100644
--- a/Source/JavaScriptCore/runtime/PropertySlot.cpp
+++ b/Source/JavaScriptCore/runtime/PropertySlot.cpp
@@ -34,11 +34,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec) const
CallData callData;
CallType callType = m_data.getterFunc->methodTable()->getCallData(m_data.getterFunc, callData);
-
- // Only objects can have accessor properties.
- // If the base is WebCore's global object then we need to substitute the shell.
- ASSERT(m_slotBase.isObject());
- return call(exec, m_data.getterFunc, callType, callData, m_thisValue.toThisObject(exec), exec->emptyList());
+ return call(exec, m_data.getterFunc, callType, callData, m_thisValue.isObject() ? m_thisValue.toThisObject(exec) : m_thisValue, exec->emptyList());
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 2b7feb4b5..1a3362b2d 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -363,7 +363,33 @@ int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffs
#endif
} else
#endif
- result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector);
+ result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector));
+
+ // FIXME: The YARR engine should handle unsigned or size_t length matches.
+ // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed.
+ // The offset vector handling needs to change as well.
+ // Right now we convert a match where the offsets overflowed into match failure.
+ // There are two places in WebCore that call the interpreter directly that need to
+ // have their offsets changed to int as well. They are platform/text/RegularExpression.cpp
+ // and inspector/ContentSearchUtils.cpp.
+ if (s.length() > INT_MAX) {
+ bool overflowed = false;
+
+ if (result < -1)
+ overflowed = true;
+
+ for (unsigned i = 0; i <= m_numSubpatterns; i++) {
+ if ((offsetVector[i*2] < -1) || ((offsetVector[i*2] >= 0) && (offsetVector[i*2+1] < -1))) {
+ overflowed = true;
+ offsetVector[i*2] = -1;
+ offsetVector[i*2+1] = -1;
+ }
+ }
+
+ if (overflowed)
+ result = -1;
+ }
+
ASSERT(result >= -1);
#if REGEXP_FUNC_TEST_DATA_GEN
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 53e880e70..90082f07e 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -153,9 +153,9 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
int start = m_regExpResult.ovector[2 * i];
if (start >= 0)
- JSArray::putByIndex(this, exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start));
+ putDirectIndex(exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start), false);
else
- JSArray::putByIndex(this, exec, i, jsUndefined());
+ putDirectIndex(exec, i, jsUndefined(), false);
}
PutPropertySlot slot;
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
index c34920d8d..a3c4497fc 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -82,12 +82,12 @@ namespace JSC {
JSArray::put(thisObject, exec, propertyName, v, slot);
}
- static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v)
+ static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow)
{
RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell);
if (!thisObject->m_didFillArrayInstance)
thisObject->fillArrayInstance(exec);
- JSArray::putByIndex(thisObject, exec, propertyName, v);
+ JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow);
}
static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 4c192ff90..a81799c46 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 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
@@ -40,8 +40,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
-static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&);
-static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
} // namespace JSC
@@ -59,14 +57,15 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0,
ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum
multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum
source regExpObjectSource DontDelete|ReadOnly|DontEnum
- lastIndex regExpObjectLastIndex DontDelete|DontEnum
@end
*/
RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
: JSNonFinalObject(globalObject->globalData(), structure)
- , d(adoptPtr(new RegExpObjectData(globalObject->globalData(), this, regExp)))
+ , m_regExp(globalObject->globalData(), this, regExp)
+ , m_lastIndexIsWritable(true)
{
+ m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
}
void RegExpObject::finishCreation(JSGlobalObject* globalObject)
@@ -75,11 +74,6 @@ void RegExpObject::finishCreation(JSGlobalObject* globalObject)
ASSERT(inherits(&s_info));
}
-void RegExpObject::destroy(JSCell* cell)
-{
- jsCast<RegExpObject*>(cell)->RegExpObject::~RegExpObject();
-}
-
void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
RegExpObject* thisObject = jsCast<RegExpObject*>(cell);
@@ -87,22 +81,87 @@ void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
- if (thisObject->d->regExp)
- visitor.append(&thisObject->d->regExp);
- if (UNLIKELY(!thisObject->d->lastIndex.get().isInt32()))
- visitor.append(&thisObject->d->lastIndex);
+ if (thisObject->m_regExp)
+ visitor.append(&thisObject->m_regExp);
+ if (UNLIKELY(!thisObject->m_lastIndex.get().isInt32()))
+ visitor.append(&thisObject->m_lastIndex);
}
bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ RegExpObject* regExp = asRegExpObject(cell);
+ slot.setValue(regExp, regExp->getLastIndex());
+ return true;
+ }
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot);
}
bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ RegExpObject* regExp = asRegExpObject(object);
+ descriptor.setDescriptor(regExp->getLastIndex(), regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
+ return true;
+ }
return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor);
}
+bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().lastIndex)
+ return false;
+ return Base::deleteProperty(cell, exec, propertyName);
+}
+
+void RegExpObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ if (mode == IncludeDontEnumProperties)
+ propertyNames.add(exec->propertyNames().lastIndex);
+ Base::getOwnPropertyNames(object, exec, propertyNames, mode);
+}
+
+void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ if (mode == IncludeDontEnumProperties)
+ propertyNames.add(exec->propertyNames().lastIndex);
+ Base::getPropertyNames(object, exec, propertyNames, mode);
+}
+
+static bool reject(ExecState* exec, bool throwException, const char* message)
+{
+ if (throwException)
+ throwTypeError(exec, message);
+ return false;
+}
+
+bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ RegExpObject* regExp = asRegExpObject(object);
+ if (descriptor.configurablePresent() && descriptor.configurable())
+ return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
+ if (descriptor.enumerablePresent() && descriptor.enumerable())
+ return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
+ if (descriptor.isAccessorDescriptor())
+ return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property.");
+ if (!regExp->m_lastIndexIsWritable) {
+ if (descriptor.writablePresent() && descriptor.writable())
+ return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
+ if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
+ return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
+ return true;
+ }
+ if (descriptor.writablePresent() && !descriptor.writable())
+ regExp->m_lastIndexIsWritable = false;
+ if (descriptor.value())
+ regExp->setLastIndex(exec, descriptor.value(), false);
+ return true;
+ }
+
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
+}
+
JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
{
return jsBoolean(asRegExpObject(slotBase)->regExp()->global());
@@ -127,6 +186,14 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
bool inBrackets = false;
bool shouldEscape = false;
+ // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
+ // and also states that the result must be a valid RegularExpressionLiteral. '//' is
+ // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
+ // source cannot ever validly be "". If the source is empty, return a different Pattern
+ // that would match the same thing.
+ if (!length)
+ return jsString(exec, "(?:)");
+
// early return for strings that don't contain a forwards slash and LineTerminator
for (unsigned i = 0; i < length; ++i) {
UChar ch = characters[i];
@@ -200,21 +267,15 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
return jsString(exec, result.toUString());
}
-JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
-{
- return asRegExpObject(slotBase)->getLastIndex();
-}
-
void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode());
+ return;
+ }
lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot);
}
-void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
-{
- asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
-}
-
JSValue RegExpObject::test(ExecState* exec)
{
return jsBoolean(match(exec));
@@ -236,7 +297,7 @@ bool RegExpObject::match(ExecState* exec)
if (!regExp()->global()) {
int position;
int length;
- regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length);
+ regExpConstructor->performMatch(*globalData, m_regExp.get(), input, 0, position, length);
return position >= 0;
}
@@ -245,13 +306,13 @@ bool RegExpObject::match(ExecState* exec)
if (LIKELY(jsLastIndex.isUInt32())) {
lastIndex = jsLastIndex.asUInt32();
if (lastIndex > input.length()) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
} else {
double doubleLastIndex = jsLastIndex.toInteger(exec);
if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
lastIndex = static_cast<unsigned>(doubleLastIndex);
@@ -259,13 +320,13 @@ bool RegExpObject::match(ExecState* exec)
int position;
int length = 0;
- regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
+ regExpConstructor->performMatch(*globalData, m_regExp.get(), input, lastIndex, position, length);
if (position < 0) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
- setLastIndex(position + length);
+ setLastIndex(exec, position + length);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index 081a7f111..456cfa683 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003, 2007, 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
@@ -44,20 +44,27 @@ namespace JSC {
return object;
}
- void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
- RegExp* regExp() const { return d->regExp.get(); }
+ void setRegExp(JSGlobalData& globalData, RegExp* r) { m_regExp.set(globalData, this, r); }
+ RegExp* regExp() const { return m_regExp.get(); }
- void setLastIndex(size_t lastIndex)
+ void setLastIndex(ExecState* exec, size_t lastIndex)
{
- d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+ m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+ if (LIKELY(m_lastIndexIsWritable))
+ m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+ else
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
}
- void setLastIndex(JSGlobalData& globalData, JSValue lastIndex)
+ void setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow)
{
- d->lastIndex.set(globalData, this, lastIndex);
+ if (LIKELY(m_lastIndexIsWritable))
+ m_lastIndex.set(exec->globalData(), this, lastIndex);
+ else if (shouldThrow)
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
}
JSValue getLastIndex() const
{
- return d->lastIndex.get();
+ return m_lastIndex.get();
}
JSValue test(ExecState*);
@@ -77,31 +84,22 @@ namespace JSC {
protected:
JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*);
JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*);
- static void destroy(JSCell*);
static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
+
private:
bool match(ExecState*);
- struct RegExpObjectData {
- WTF_MAKE_FAST_ALLOCATED;
- public:
- RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp)
- : regExp(globalData, owner, regExp)
- {
- lastIndex.setWithoutWriteBarrier(jsNumber(0));
- }
-
- WriteBarrier<RegExp> regExp;
- WriteBarrier<Unknown> lastIndex;
- };
-#if COMPILER(MSVC)
- friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
-#endif
- OwnPtr<RegExpObjectData> d;
+ WriteBarrier<RegExp> m_regExp;
+ WriteBarrier<Unknown> m_lastIndex;
+ bool m_lastIndexIsWritable;
};
RegExpObject* asRegExpObject(JSValue);
diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
index 9074e97c3..8e4b5a9d5 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -129,7 +129,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
- asRegExpObject(thisValue)->setLastIndex(0);
+ asRegExpObject(thisValue)->setLastIndex(exec, 0);
return JSValue::encode(jsUndefined());
}
@@ -155,7 +155,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
postfix[index] = 'm';
UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec);
// If source is empty, use "/(?:)/" to avoid colliding with comment syntax
- return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
+ return JSValue::encode(jsMakeNontrivialString(exec, "/", source, postfix));
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp
index 4a24698fb..d7e1c8a17 100644
--- a/Source/JavaScriptCore/runtime/StringObject.cpp
+++ b/Source/JavaScriptCore/runtime/StringObject.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "StringObject.h"
+#include "Error.h"
#include "PropertyNameArray.h"
namespace JSC {
@@ -68,11 +69,56 @@ bool StringObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, c
void StringObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
- if (propertyName == exec->propertyNames().length)
+ if (propertyName == exec->propertyNames().length) {
+ if (slot.isStrictMode())
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
return;
+ }
JSObject::put(cell, exec, propertyName, value, slot);
}
+bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+ StringObject* thisObject = jsCast<StringObject*>(object);
+
+ if (propertyName == exec->propertyNames().length) {
+ if (!object->isExtensible()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
+ return false;
+ }
+ if (descriptor.configurablePresent() && descriptor.configurable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.enumerablePresent() && descriptor.enumerable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
+ return false;
+ }
+ if (descriptor.isAccessorDescriptor()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
+ return false;
+ }
+ if (descriptor.writablePresent() && descriptor.writable()) {
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
+ return false;
+ }
+ if (!descriptor.value())
+ return true;
+ if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length())))
+ return true;
+ if (throwException)
+ throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
+ return false;
+ }
+
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
+}
+
bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
StringObject* thisObject = jsCast<StringObject*>(cell);
diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h
index 248c71601..bad5595c3 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -53,6 +53,7 @@ namespace JSC {
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
static const JS_EXPORTDATA ClassInfo s_info;
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 63c00e27e..708c1fb77 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -455,11 +455,19 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS
unsigned sourceLen = source.length();
if (exec->hadException())
return JSValue::encode(JSValue());
- RegExp* regExp = asRegExpObject(searchValue)->regExp();
+ RegExpObject* regExpObject = asRegExpObject(searchValue);
+ RegExp* regExp = regExpObject->regExp();
bool global = regExp->global();
- if (global && callType == CallTypeNone && !replacementString.length())
- return removeUsingRegExpSearch(exec, string, source, regExp);
+ if (global) {
+ // ES5.1 15.5.4.10 step 8.a.
+ regExpObject->setLastIndex(exec, 0);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+
+ if (callType == CallTypeNone && !replacementString.length())
+ return removeUsingRegExpSearch(exec, string, source, regExp);
+ }
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
@@ -808,9 +816,17 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
JSValue a0 = exec->argument(0);
RegExp* reg;
- if (a0.inherits(&RegExpObject::s_info))
- reg = asRegExpObject(a0)->regExp();
- else {
+ bool global = false;
+ if (a0.inherits(&RegExpObject::s_info)) {
+ RegExpObject* regExpObject = asRegExpObject(a0);
+ reg = regExpObject->regExp();
+ if ((global = reg->global())) {
+ // ES5.1 15.5.4.10 step 8.a.
+ regExpObject->setLastIndex(exec, 0);
+ if (exec->hadException())
+ return JSValue::encode(JSValue());
+ }
+ } else {
/*
* ECMA 15.5.4.12 String.prototype.search (regexp)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
@@ -825,7 +841,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
int pos;
int matchLength = 0;
regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength);
- if (!(reg->global())) {
+ if (!global) {
// case without 'g' flag is handled like RegExp.prototype.exec
if (pos < 0)
return JSValue::encode(jsNull());
@@ -948,7 +964,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
if (separatorValue.isUndefined()) {
// a. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
- result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input));
+ result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
// b. Return A.
return JSValue::encode(result);
}
@@ -961,7 +977,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
if (reg->match(*globalData, input, 0) < 0)
- result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input));
+ result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
return JSValue::encode(result);
}
@@ -992,7 +1008,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through q (exclusive).
// 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
// Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
- result->methodTable()->putByIndex(result, exec, resultLength, jsSubstring(exec, input, position, matchPosition - position));
+ result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
// 3. Increment lengthA by 1.
// 4. If lengthA == lim, return A.
if (++resultLength == limit)
@@ -1011,7 +1027,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// ToString(lengthA), Property Descriptor {[[Value]]: cap[i], [[Writable]]:
// true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
int sub = ovector[i * 2];
- result->methodTable()->putByIndex(result, exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub));
+ result->putDirectIndex(exec, resultLength, sub < 0 ? jsUndefined() : jsSubstring(exec, input, sub, ovector[i * 2 + 1] - sub), false);
// c Increment lengthA by 1.
// d If lengthA == lim, return A.
if (++resultLength == limit)
@@ -1030,7 +1046,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
if (separatorValue.isUndefined()) {
// a. Call the [[DefineOwnProperty]] internal method of A with arguments "0",
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
- result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input));
+ result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
// b. Return A.
return JSValue::encode(result);
}
@@ -1043,7 +1059,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
// d. Return A.
if (!separator.isEmpty())
- result->methodTable()->putByIndex(result, exec, 0, jsStringWithReuse(exec, thisValue, input));
+ result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false);
return JSValue::encode(result);
}
@@ -1054,7 +1070,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
ASSERT(limit);
do {
- result->methodTable()->putByIndex(result, exec, position, jsSingleCharacterSubstring(exec, input, position));
+ result->putDirectIndex(exec, position, jsSingleCharacterSubstring(exec, input, position), false);
} while (++position < limit);
return JSValue::encode(result);
@@ -1071,7 +1087,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through q (exclusive).
// 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA),
// Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
- result->methodTable()->putByIndex(result, exec, resultLength, jsSubstring(exec, input, position, matchPosition - position));
+ result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false);
// 3. Increment lengthA by 1.
// 4. If lengthA == lim, return A.
if (++resultLength == limit)
@@ -1087,7 +1103,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
// through s (exclusive).
// 15. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), Property Descriptor
// {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false.
- result->methodTable()->putByIndex(result, exec, resultLength++, jsSubstring(exec, input, position, input.length() - position));
+ result->putDirectIndex(exec, resultLength++, jsSubstring(exec, input, position, input.length() - position), false);
// 16. Return A.
return JSValue::encode(result);
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index 81731222b..f540a12c7 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -125,7 +125,7 @@ namespace JSC {
public:
static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
private:
- SharedSymbolTable() { deprecatedTurnOffVerifier(); }
+ SharedSymbolTable() { turnOffVerifier(); }
};
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index 7e9db12fb..05f3bc5bb 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -30,7 +30,7 @@
#include "HandleTypes.h"
#include "Heap.h"
#include "SamplingCounter.h"
-#include "TypeTraits.h"
+#include <wtf/TypeTraits.h>
namespace JSC {