Diff
Modified: releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog 2017-07-24 10:28:02 UTC (rev 219806)
@@ -1,3 +1,31 @@
+2017-05-05 Saam Barati <[email protected]>
+
+ putDirectIndex does not properly do defineOwnProperty
+ https://bugs.webkit.org/show_bug.cgi?id=171591
+ <rdar://problem/31735695>
+
+ Reviewed by Geoffrey Garen.
+
+ * stress/array-prototype-splice-making-typed-array.js:
+ (test):
+ * stress/array-species-config-array-constructor.js:
+ (shouldThrow):
+ (test):
+ * stress/put-direct-index-broken-2.js: Added.
+ (assert):
+ (test):
+ (makeLengthWritable):
+ (set get restoreOldDesc):
+ * stress/put-direct-index-broken.js: Added.
+ (whatToTest):
+ (tryRunning):
+ (tryItOut):
+ * stress/put-indexed-getter-setter.js: Added.
+ (foo.X.prototype.set 7):
+ (foo.X.prototype.get 7):
+ (foo.X):
+ (foo):
+
2017-05-17 Filip Pizlo <[email protected]>
Unreviewed, address mlam's review feedback.
Modified: releases/WebKitGTK/webkit-2.16/JSTests/stress/array-prototype-splice-making-typed-array.js (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/array-prototype-splice-making-typed-array.js 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/array-prototype-splice-making-typed-array.js 2017-07-24 10:28:02 UTC (rev 219806)
@@ -10,24 +10,30 @@
test(function() {
// This should not crash.
-
- // FIXME: this might need to be updated as we make our splice implementation
- // more ES6 compliant: https://bugs.webkit.org/show_bug.cgi?id=159645
let x = [1,2,3,4,5];
x.constructor = Uint8Array;
delete x[2];
assert(!(2 in x));
- let removed = x.splice(1,3);
- assert(removed instanceof Uint8Array);
- assert(removed.length === 3);
- assert(removed[0] === 2);
- assert(removed[1] === 0);
- assert(removed[2] === 4);
+ let err = null;
+ try {
+ let removed = x.splice(1,3);
+ assert(removed instanceof Uint8Array);
+ assert(removed.length === 3);
+ assert(removed[0] === 2);
+ assert(removed[1] === 0);
+ assert(removed[2] === 4);
+ } catch(e) {
+ err = e;
+ }
+ assert(err.toString() === "TypeError: Attempting to configure non-configurable property on a typed array at index: 0");
assert(x instanceof Array);
- assert(x.length === 2);
+ assert(x.length === 5);
assert(x[0] === 1);
- assert(x[1] === 5);
+ assert(x[1] === 2);
+ assert(x[2] === undefined);
+ assert(x[3] === 4);
+ assert(x[4] === 5);
});
test(function() {
Modified: releases/WebKitGTK/webkit-2.16/JSTests/stress/array-species-config-array-constructor.js (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/array-species-config-array-constructor.js 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/array-species-config-array-constructor.js 2017-07-24 10:28:02 UTC (rev 219806)
@@ -19,14 +19,31 @@
// We can't write to the length property on a typed array by default.
Object.defineProperty(Int32Array.prototype, "length", { value: 0, writable: true });
-result = foo.concat([1]);
-if (!(result instanceof Int32Array))
- throw "concat failed";
+function shouldThrow(f, m) {
+ let err;
+ try {
+ f();
+ } catch(e) {
+ err = e;
+ }
+ if (err.toString() !== m)
+ throw new Error("Wrong error: " + err);
+}
-result = foo.splice();
-if (!(result instanceof Int32Array))
- throw "splice failed";
-
-result = foo.slice();
-if (!(result instanceof Int32Array))
- throw "slice failed";
+function test() {
+ const message = "TypeError: Attempting to configure non-configurable property on a typed array at index: 0";
+ shouldThrow(() => foo.concat([1]), message);
+ foo = [1,2,3,4];
+ shouldThrow(() => foo.slice(0), message);
+ foo = [1,2,3,4];
+ let r = foo.splice();
+ if (!(r instanceof Int32Array))
+ throw "Bad";
+ if (r.length !== 0)
+ throw "Bad";
+ foo = [1,2,3,4];
+ shouldThrow(() => foo.splice(0), message);
+}
+noInline(test);
+for (let i = 0; i < 3000; ++i)
+ test();
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken-2.js (0 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken-2.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken-2.js 2017-07-24 10:28:02 UTC (rev 219806)
@@ -0,0 +1,247 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion");
+}
+
+function test(f) {
+ for (let i = 0; i < 1000; ++i) {
+ f();
+ }
+}
+
+let __oldDesc = null;
+let __localLength;
+function makeLengthWritable() {
+ assert(__oldDesc === null);
+ __oldDesc = Object.getOwnPropertyDescriptor(Uint8ClampedArray.prototype.__proto__, "length");
+ assert(typeof __oldDesc.get === "function");
+ Reflect.defineProperty(Uint8ClampedArray.prototype.__proto__, "length", {configurable:true, get() { return __localLength; }, set(x) { __localLength = x; }});
+}
+
+function restoreOldDesc() {
+ assert(__oldDesc !== null);
+ Reflect.defineProperty(Uint8ClampedArray.prototype.__proto__, "length", __oldDesc);
+ __oldDesc = null;
+}
+
+test(function() {
+ "use strict";
+ let a = [];
+ a.push(300);
+ a.length = 4277;
+
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+ let err = null;
+ try {
+ let y = Array.prototype.map.call(a, x => x);
+ } catch(e) {
+ err = e;
+ }
+ assert(!!err);
+ assert(err.toString() === "TypeError: Attempting to configure non-configurable property on a typed array at index: 0");
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+ let err = null;
+ try {
+ let y = Array.prototype.filter.call(a, x => true);
+ } catch(e) {
+ err = e;
+ }
+ assert(err.toString() === "TypeError: Attempting to configure non-configurable property on a typed array at index: 0");
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+ let err = null;
+ let y = Array.prototype.filter.call(a, x => false);
+ assert(y instanceof Uint8ClampedArray);
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+
+ let err = null;
+ try {
+ let y = Array.prototype.slice.call(a, 0);
+ } catch(e) {
+ err = e;
+ }
+ assert(err.toString() === "TypeError: Attempting to configure non-configurable property on a typed array at index: 0");
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+
+ makeLengthWritable();
+ let y = Array.prototype.slice.call(a, 100);
+ assert(y.length === 4277 - 100);
+ assert(y.length === __localLength);
+ assert(y instanceof Uint8ClampedArray);
+ restoreOldDesc();
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+
+ makeLengthWritable();
+ let y = Array.prototype.splice.call(a);
+ assert(y.length === __localLength);
+ assert(y.length === 0);
+ restoreOldDesc();
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+
+ let err = null;
+ try {
+ let y = Array.prototype.splice.call(a, 0);
+ } catch(e) {
+ err = e;
+ }
+ assert(err.toString() === "TypeError: Attempting to configure non-configurable property on a typed array at index: 0");
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let x = new Uint8ClampedArray;
+ a.__proto__ = x;
+
+ makeLengthWritable();
+ let y = Array.prototype.slice.call(a, 100);
+ assert(y.length === 4277 - 100);
+ assert(y.length === __localLength);
+ assert(y instanceof Uint8ClampedArray);
+ restoreOldDesc();
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let calls = 0;
+ let target = {};
+ a.__proto__ = {
+ constructor: {
+ [Symbol.species]: function(length) {
+ assert(length === 4277)
+ return new Proxy(target, {
+ defineProperty(...args) {
+ ++calls;
+ return Reflect.defineProperty(...args);
+ }
+ });
+ }
+ }
+ };
+ let y = Array.prototype.map.call(a, x => x);
+ assert(calls === 100);
+ for (let i = 0; i < 100; ++i)
+ assert(target[i] === i);
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let calls = 0;
+ let target = {};
+ a.__proto__ = {
+ constructor: {
+ [Symbol.species]: function(length) {
+ assert(length === 0)
+ return new Proxy(target, {
+ defineProperty(...args) {
+ ++calls;
+ return Reflect.defineProperty(...args);
+ }
+ });
+ }
+ }
+ };
+ let y = Array.prototype.filter.call(a, x => true);
+ assert(calls === 100);
+ for (let i = 0; i < 100; ++i)
+ assert(target[i] === i);
+});
+
+test(function() {
+ let a = [];
+ for (let i = 0; i < 100; i++) {
+ a.push(i);
+ }
+ a.length = 4277;
+ let calls = 0;
+ let target = {};
+ let keys = [];
+ a.__proto__ = {
+ constructor: {
+ [Symbol.species]: function(length) {
+ assert(length === 4277)
+ return new Proxy(target, {
+ defineProperty(...args) {
+ keys.push(args[1])
+ ++calls;
+ return Reflect.defineProperty(...args);
+ }
+ });
+ }
+ }
+ };
+ let y = Array.prototype.slice.call(a, 0);
+ assert(calls === 101); // length gets defined too.
+ assert(keys.length === 101);
+ for (let i = 0; i < 100; ++i) {
+ assert(parseInt(keys[i]) === i);
+ assert(target[i] === i);
+ }
+ assert(keys[keys.length - 1] === "length");
+ assert(target.length === 4277);
+});
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken.js (0 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/put-direct-index-broken.js 2017-07-24 10:28:02 UTC (rev 219806)
@@ -0,0 +1,25 @@
+function whatToTest(code){return {allowExec: true,};}
+function tryRunning(f, code, wtt)
+{
+ uneval = true
+ try {var rv = f();} catch(runError) {}
+ try {if ('__defineSetter__' in this) {delete this.uneval;} } catch(e) {}
+}
+function tryItOut(code)
+{
+ var wtt = true;
+ var f;
+ try {f = new Function(code);} catch(compileError) {}
+ tryRunning(f, code, wtt);
+}
+tryItOut(`a0 = [];
+ r0 = /x/;
+ t0 = new Uint8ClampedArray;
+ o1 = {};
+ g1 = this;
+ v2 = null;`);
+
+tryItOut("func = (function(x, y) {});");
+tryItOut("for (var p in g1) { this.a0[new func([].map(q => q, null), x)]; }");
+tryItOut("a0.push(o1.m1);a0.length = (4277);a0.__proto__ = this.t0;");
+tryItOut("\"use strict\"; a0 = Array.prototype.map.call(a0, (function() {}));");
Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/put-indexed-getter-setter.js (0 => 219806)
--- releases/WebKitGTK/webkit-2.16/JSTests/stress/put-indexed-getter-setter.js (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/put-indexed-getter-setter.js 2017-07-24 10:28:02 UTC (rev 219806)
@@ -0,0 +1,18 @@
+function foo() {
+ let setterValue = 0;
+ class X {
+ static set 7(x) { setterValue = x; }
+ static get 7() { }
+ };
+ X[7] = 27;
+ if (setterValue !== 27)
+ throw new Error("Bad")
+}
+noInline(foo);
+
+for (let i = 0; i < 10000; ++i)
+ foo();
+
+Object.defineProperty(Object.prototype, "7", {get() { return 500; }, set(x) { }}); // this shouldn't change the test at all, it should be doing defineOwnProperty.
+for (let i = 0; i < 10000; ++i)
+ foo();
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog 2017-07-24 10:28:02 UTC (rev 219806)
@@ -1,3 +1,50 @@
+2017-05-05 Saam Barati <[email protected]>
+
+ putDirectIndex does not properly do defineOwnProperty
+ https://bugs.webkit.org/show_bug.cgi?id=171591
+ <rdar://problem/31735695>
+
+ Reviewed by Geoffrey Garen.
+
+ This patch fixes putDirectIndex and its JIT implementations to be
+ compatible with the ES6 spec. I think our code became out of date
+ when we implemented ArraySpeciesCreate since ArraySpeciesCreate may
+ return arbitrary objects. We perform putDirectIndex on that arbitrary
+ object. The behavior we want is as if we performed defineProperty({configurable:true, enumerable:true, writable:true}).
+ However, we weren't doing this. putDirectIndex assumed it could just splat
+ data into any descendent of JSObject's butterfly. For example, this means
+ we'd just splat into the butterfly of a typed array, even though a typed
+ array doesn't use its butterfly to store its indexed properties in the usual
+ way. Also, typed array properties are non-configurable, so this operation
+ should throw. This also means if we saw a ProxyObject, we'd just splat
+ into its butterfly, but this is obviously wrong because ProxyObject should
+ intercept the defineProperty operation.
+
+ This patch fixes this issue by adding a whitelist of cell types that can
+ go down putDirectIndex's fast path. Anything not in that whitelist will
+ simply call into defineOwnProperty.
+
+ * bytecode/ByValInfo.h:
+ (JSC::jitArrayModePermitsPutDirect):
+ * dfg/DFGArrayMode.cpp:
+ (JSC::DFG::ArrayMode::refine):
+ * jit/JITOperations.cpp:
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncSplice):
+ * runtime/ClonedArguments.cpp:
+ (JSC::ClonedArguments::createStructure):
+ * runtime/JSGenericTypedArrayViewInlines.h:
+ (JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):
+ * runtime/JSObject.cpp:
+ (JSC::canDoFastPutDirectIndex):
+ (JSC::JSObject::defineOwnIndexedProperty):
+ (JSC::JSObject::putDirectIndexSlowOrBeyondVectorLength):
+ (JSC::JSObject::putDirectIndexBeyondVectorLength): Deleted.
+ * runtime/JSObject.h:
+ (JSC::JSObject::putDirectIndex):
+ (JSC::JSObject::canSetIndexQuicklyForPutDirect): Deleted.
+ * runtime/JSType.h:
+
2017-05-17 Filip Pizlo <[email protected]>
JSC: Incorrect LoadVarargs handling in ArgumentsEliminationPhase::transform
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ByValInfo.h (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ByValInfo.h 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/bytecode/ByValInfo.h 2017-07-24 10:28:02 UTC (rev 219806)
@@ -164,6 +164,26 @@
}
}
+inline bool jitArrayModePermitsPutDirect(JITArrayMode mode)
+{
+ // We don't allow typed array putDirect here since putDirect has
+ // defineOwnProperty({configurable: true, writable:true, enumerable:true})
+ // semantics. Typed array indexed properties are non-configurable by
+ // default, so we can't simply store to a typed array for putDirect.
+ //
+ // We could model putDirect on ScopedArguments and DirectArguments, but we
+ // haven't found any performance incentive to do it yet.
+ switch (mode) {
+ case JITInt32:
+ case JITDouble:
+ case JITContiguous:
+ case JITArrayStorage:
+ return true;
+ default:
+ return false;
+ }
+}
+
inline TypedArrayType typedArrayTypeForJITArrayMode(JITArrayMode mode)
{
switch (mode) {
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGArrayMode.cpp (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2017-07-24 10:28:02 UTC (rev 219806)
@@ -186,6 +186,16 @@
// don't want to). So, for now, we assume that if the base is not a cell according
// to value profiling, but the array profile tells us something else, then we
// should just trust the array profile.
+
+ auto typedArrayResult = [&] (ArrayMode result) -> ArrayMode {
+ if (node->op() == PutByValDirect) {
+ // This is semantically identical to defineOwnProperty({configurable: true, writable:true, enumerable:true}),
+ // which we can't model as a simple store to the typed array since typed array indexed properties
+ // are non-configurable.
+ return ArrayMode(Array::Generic);
+ }
+ return result;
+ };
switch (type()) {
case Array::SelectUsingArguments:
@@ -235,15 +245,11 @@
case Array::Uint32Array:
case Array::Float32Array:
case Array::Float64Array:
- switch (node->op()) {
- case PutByVal:
+ if (node->op() == PutByVal) {
if (graph.hasExitSite(node->origin.semantic, OutOfBounds) || !isInBounds())
- return withSpeculation(Array::OutOfBounds);
- return withSpeculation(Array::InBounds);
- default:
- return withSpeculation(Array::InBounds);
+ return typedArrayResult(withSpeculation(Array::OutOfBounds));
}
- return *this;
+ return typedArrayResult(withSpeculation(Array::InBounds));
case Array::Unprofiled:
case Array::SelectUsingPredictions: {
base &= ~SpecOther;
@@ -274,33 +280,33 @@
result = withSpeculation(Array::InBounds);
break;
}
-
+
if (isInt8ArraySpeculation(base))
- return result.withType(Array::Int8Array);
+ return typedArrayResult(result.withType(Array::Int8Array));
if (isInt16ArraySpeculation(base))
- return result.withType(Array::Int16Array);
+ return typedArrayResult(result.withType(Array::Int16Array));
if (isInt32ArraySpeculation(base))
- return result.withType(Array::Int32Array);
+ return typedArrayResult(result.withType(Array::Int32Array));
if (isUint8ArraySpeculation(base))
- return result.withType(Array::Uint8Array);
+ return typedArrayResult(result.withType(Array::Uint8Array));
if (isUint8ClampedArraySpeculation(base))
- return result.withType(Array::Uint8ClampedArray);
+ return typedArrayResult(result.withType(Array::Uint8ClampedArray));
if (isUint16ArraySpeculation(base))
- return result.withType(Array::Uint16Array);
+ return typedArrayResult(result.withType(Array::Uint16Array));
if (isUint32ArraySpeculation(base))
- return result.withType(Array::Uint32Array);
+ return typedArrayResult(result.withType(Array::Uint32Array));
if (isFloat32ArraySpeculation(base))
- return result.withType(Array::Float32Array);
+ return typedArrayResult(result.withType(Array::Float32Array));
if (isFloat64ArraySpeculation(base))
- return result.withType(Array::Float64Array);
+ return typedArrayResult(result.withType(Array::Float64Array));
if (type() == Array::Unprofiled)
return ArrayMode(Array::ForceExit);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.cpp (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.cpp 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.cpp 2017-07-24 10:28:02 UTC (rev 219806)
@@ -547,15 +547,20 @@
byValInfo->tookSlowPath = true;
uint32_t index = subscript.asUInt32();
ASSERT(isIndex(index));
- if (baseObject->canSetIndexQuicklyForPutDirect(index)) {
- baseObject->setIndexQuickly(callFrame->vm(), index, value);
- return;
+
+ switch (baseObject->indexingType()) {
+ case ALL_INT32_INDEXING_TYPES:
+ case ALL_DOUBLE_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ if (index < baseObject->butterfly()->vectorLength())
+ break;
+ FALLTHROUGH;
+ default:
+ byValInfo->arrayProfile->setOutOfBounds();
+ break;
}
- // FIXME: This will make us think that in-bounds typed array accesses are actually
- // out-of-bounds.
- // https://bugs.webkit.org/show_bug.cgi?id=149886
- byValInfo->arrayProfile->setOutOfBounds();
baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
return;
}
@@ -695,7 +700,7 @@
if (hasOptimizableIndexing(structure)) {
// Attempt to optimize.
JITArrayMode arrayMode = jitArrayModeForStructure(structure);
- if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
+ if (jitArrayModePermitsPutDirect(arrayMode) && arrayMode != byValInfo->arrayMode) {
CodeBlock* codeBlock = exec->codeBlock();
ConcurrentJSLocker locker(codeBlock->m_lock);
byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ArrayPrototype.cpp (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-07-24 10:28:02 UTC (rev 219806)
@@ -1029,33 +1029,23 @@
result = asArray(thisObj)->fastSlice(*exec, actualStart, actualDeleteCount);
if (!result) {
- if (speciesResult.first == SpeciesConstructResult::CreatedObject) {
+ if (speciesResult.first == SpeciesConstructResult::CreatedObject)
result = speciesResult.second;
-
- for (unsigned k = 0; k < actualDeleteCount; ++k) {
- JSValue v = getProperty(exec, thisObj, k + actualStart);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (UNLIKELY(!v))
- continue;
- result->putByIndexInline(exec, k, v, true);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
- } else {
+ else {
result = JSArray::tryCreate(vm, exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), actualDeleteCount);
if (UNLIKELY(!result)) {
throwOutOfMemoryError(exec, scope);
return encodedJSValue();
}
-
- for (unsigned k = 0; k < actualDeleteCount; ++k) {
- JSValue v = getProperty(exec, thisObj, k + actualStart);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (UNLIKELY(!v))
- continue;
- result->putDirectIndex(exec, k, v);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
}
+ for (unsigned k = 0; k < actualDeleteCount; ++k) {
+ JSValue v = getProperty(exec, thisObj, k + actualStart);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ if (UNLIKELY(!v))
+ continue;
+ result->putDirectIndex(exec, k, v, 0, PutDirectIndexShouldThrow);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ }
}
unsigned itemCount = std::max<int>(exec->argumentCount() - 2, 0);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ClonedArguments.cpp (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ClonedArguments.cpp 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/ClonedArguments.cpp 2017-07-24 10:28:02 UTC (rev 219806)
@@ -153,7 +153,7 @@
Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
{
- Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), indexingType);
+ Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ClonedArgumentsType, StructureFlags), info(), indexingType);
PropertyOffset offset;
structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->length, DontEnum, offset);
ASSERT(offset == clonedArgumentsLengthPropertyOffset);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h 2017-07-24 10:28:02 UTC (rev 219806)
@@ -394,15 +394,21 @@
auto scope = DECLARE_THROW_SCOPE(vm);
JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
- if (parseIndex(propertyName)) {
+ if (std::optional<uint32_t> index = parseIndex(propertyName)) {
+ auto throwTypeErrorIfNeeded = [&] (const char* errorMessage) -> bool {
+ if (shouldThrow)
+ throwTypeError(exec, scope, makeString(errorMessage, String::number(*index)));
+ return false;
+ };
+
if (descriptor.isAccessorDescriptor())
- return typeError(exec, scope, shouldThrow, ASCIILiteral("Attempting to store accessor indexed property on a typed array."));
+ return throwTypeErrorIfNeeded("Attempting to store accessor property on a typed array at index: ");
if (descriptor.configurable())
- return typeError(exec, scope, shouldThrow, ASCIILiteral("Attempting to configure non-configurable property."));
+ return throwTypeErrorIfNeeded("Attempting to configure non-configurable property on a typed array at index: ");
if (!descriptor.enumerable() || !descriptor.writable())
- return typeError(exec, scope, shouldThrow, ASCIILiteral("Attempting to store non-enumerable or non-writable indexed property on a typed array."));
+ return throwTypeErrorIfNeeded("Attempting to store non-enumerable or non-writable property on a typed array at index: ");
if (descriptor.value()) {
PutPropertySlot unused(JSValue(thisObject), shouldThrow);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.cpp (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.cpp 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.cpp 2017-07-24 10:28:02 UTC (rev 219806)
@@ -2344,6 +2344,15 @@
return true;
}
+ALWAYS_INLINE static bool canDoFastPutDirectIndex(JSObject* object)
+{
+ return isJSArray(object)
+ || isJSFinalObject(object)
+ || object->type() == DirectArgumentsType
+ || object->type() == ScopedArgumentsType
+ || object->type() == ClonedArgumentsType;
+}
+
// Defined in ES5.1 8.12.9
bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const PropertyDescriptor& descriptor, bool throwException)
{
@@ -2357,7 +2366,7 @@
// FIXME: this will pessimistically assume that if attributes are missing then they'll default to false
// however if the property currently exists missing attributes will override from their current 'true'
// state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode').
- if (!descriptor.attributes() && descriptor.value()) {
+ if (!descriptor.attributes() && descriptor.value() && canDoFastPutDirectIndex(this)) {
ASSERT(!descriptor.isAccessorDescriptor());
return putDirectIndex(exec, index, descriptor.value(), 0, throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
}
@@ -2796,9 +2805,15 @@
return true;
}
-bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
+bool JSObject::putDirectIndexSlowOrBeyondVectorLength(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
{
VM& vm = exec->vm();
+
+ if (!canDoFastPutDirectIndex(this)) {
+ PropertyDescriptor descriptor;
+ descriptor.setDescriptor(value, attributes);
+ return methodTable(vm)->defineOwnProperty(this, exec, Identifier::from(exec, i), descriptor, mode == PutDirectIndexShouldThrow);
+ }
// i should be a valid array index that is outside of the current vector.
ASSERT(i <= MAX_ARRAY_INDEX);
@@ -2842,7 +2857,7 @@
}
if (!value.isInt32()) {
convertInt32ForValue(vm, value);
- return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
+ return putDirectIndexSlowOrBeyondVectorLength(exec, i, value, attributes, mode);
}
putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value);
return true;
@@ -2856,12 +2871,12 @@
}
if (!value.isNumber()) {
convertDoubleToContiguous(vm);
- return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
+ return putDirectIndexSlowOrBeyondVectorLength(exec, i, value, attributes, mode);
}
double valueAsDouble = value.asNumber();
if (valueAsDouble != valueAsDouble) {
convertDoubleToContiguous(vm);
- return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode);
+ return putDirectIndexSlowOrBeyondVectorLength(exec, i, value, attributes, mode);
}
putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value);
return true;
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.h (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.h 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSObject.h 2017-07-24 10:28:02 UTC (rev 219806)
@@ -195,6 +195,7 @@
// putByIndex assumes that the receiver is this JSCell object.
JS_EXPORT_PRIVATE static bool putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ // This performs the ECMAScript Set() operation.
ALWAYS_INLINE bool putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
{
if (canSetIndexQuickly(propertyName)) {
@@ -208,21 +209,44 @@
// - the prototype chain is not consulted
// - accessors are not called.
// - it will ignore extensibility and read-only properties if PutDirectIndexLikePutDirect is passed as the mode (the default).
- // This method creates a property with attributes writable, enumerable and configurable all set to true.
+ // This method creates a property with attributes writable, enumerable and configurable all set to true if attributes is zero,
+ // otherwise, it creates a property with the provided attributes. Semantically, this is performing defineOwnProperty.
bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
{
- if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) {
+ auto canSetIndexQuicklyForPutDirect = [&] () -> bool {
+ switch (indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_UNDECIDED_INDEXING_TYPES:
+ return false;
+ case ALL_INT32_INDEXING_TYPES:
+ case ALL_DOUBLE_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return propertyName < m_butterfly.get()->vectorLength();
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
+ }
+ };
+
+ if (!attributes && canSetIndexQuicklyForPutDirect()) {
setIndexQuickly(exec->vm(), propertyName, value);
return true;
}
- return putDirectIndexBeyondVectorLength(exec, propertyName, value, attributes, mode);
+ return putDirectIndexSlowOrBeyondVectorLength(exec, propertyName, value, attributes, mode);
}
+ // This is semantically equivalent to performing defineOwnProperty(propertyName, {configurable:true, writable:true, enumerable:true, value:value}).
bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value)
{
return putDirectIndex(exec, propertyName, value, 0, PutDirectIndexLikePutDirect);
}
- // A non-throwing version of putDirect and putDirectIndex.
+ // A generally non-throwing version of putDirect and putDirectIndex.
+ // However, it's only guaranteed to not throw based on what the receiver is.
+ // For example, if the receiver is a ProxyObject, this is not guaranteed, since
+ // it may call into arbitrary JS code. It's the responsibility of the user of
+ // this API to ensure that the receiver object is a well known type if they
+ // want to ensure that this won't throw an exception.
JS_EXPORT_PRIVATE bool putDirectMayBeIndex(ExecState*, PropertyName, JSValue);
bool hasIndexingHeader() const
@@ -351,23 +375,6 @@
}
}
- bool canSetIndexQuicklyForPutDirect(unsigned i)
- {
- switch (indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_UNDECIDED_INDEXING_TYPES:
- return false;
- case ALL_INT32_INDEXING_TYPES:
- case ALL_DOUBLE_INDEXING_TYPES:
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return i < m_butterfly.get()->vectorLength();
- default:
- RELEASE_ASSERT_NOT_REACHED();
- return false;
- }
- }
-
void setIndexQuickly(VM& vm, unsigned i, JSValue v)
{
Butterfly* butterfly = m_butterfly.get();
@@ -1013,7 +1020,7 @@
bool putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
bool putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode, ArrayStorage*);
- JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode);
+ JS_EXPORT_PRIVATE bool putDirectIndexSlowOrBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode);
unsigned getNewVectorLength(unsigned indexBias, unsigned currentVectorLength, unsigned currentLength, unsigned desiredLength);
unsigned getNewVectorLength(unsigned desiredLength);
Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSType.h (219805 => 219806)
--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSType.h 2017-07-24 09:54:44 UTC (rev 219805)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/JSType.h 2017-07-24 10:28:02 UTC (rev 219806)
@@ -97,7 +97,9 @@
WebAssemblyFunctionType,
- LastJSCObjectType = JSSetType,
+ ClonedArgumentsType,
+
+ LastJSCObjectType = ClonedArgumentsType,
MaxJSType = 0b11111111,
};