Diff
Modified: trunk/JSTests/ChangeLog (268488 => 268489)
--- trunk/JSTests/ChangeLog 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/JSTests/ChangeLog 2020-10-14 21:48:50 UTC (rev 268489)
@@ -1,3 +1,13 @@
+2020-10-14 Alexey Shvayka <[email protected]>
+
+ Use @putByValDirect instead of Array.prototype.@push in built-ins
+ https://bugs.webkit.org/show_bug.cgi?id=175432
+
+ Reviewed by Yusuke Suzuki.
+
+ * stress/array-push-intrinsic.js: Added.
+ * test262/expectations.yaml: Mark 2 test cases as passing.
+
2020-10-13 Saam Barati <[email protected]>
JSObject::getPropertyNames should have a stack overflow check
Added: trunk/JSTests/stress/array-push-intrinsic.js (0 => 268489)
--- trunk/JSTests/stress/array-push-intrinsic.js (rev 0)
+++ trunk/JSTests/stress/array-push-intrinsic.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -0,0 +1,76 @@
+"use strict";
+
+const arrayPush = $vm.createBuiltin("(function (a, v) { @arrayPush(a, v); })");
+noInline(arrayPush);
+
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error(`Bad value: ${actual}.`);
+}
+
+function shouldThrow(func, errorMessage)
+{
+ var errorThrown = false;
+ try {
+ func();
+ } catch (error) {
+ errorThrown = true;
+ if (String(error) !== errorMessage)
+ throw new Error(`Bad error: ${error}`);
+ }
+ if (!errorThrown)
+ throw new Error("Didn't throw!");
+}
+
+shouldThrow(
+ () => arrayPush(x, y),
+ "ReferenceError: Can't find variable: x",
+);
+
+shouldThrow(
+ () => arrayPush({ get length() { throw new Error("'length' should be unreachable."); } }, y),
+ "ReferenceError: Can't find variable: y",
+);
+
+for (let i = 0; i < 5; ++i) {
+ Object.defineProperty(Object.prototype, i, {
+ get() { throw new Error(i + " getter should be unreachable."); },
+ set(_value) { throw new Error(i + " setter should be unreachable."); },
+ });
+}
+
+(() => {
+ const arr = [];
+ for (let i = 0; i < 1e5; ++i) {
+ arrayPush(arr, i);
+ shouldBe(arr[i], i);
+ shouldBe(arr.length, i + 1);
+ }
+})();
+
+(() => {
+ const maxLength = 2 ** 32 - 1;
+ const startIndex = maxLength - 1e4;
+ const arr = new Array(startIndex);
+
+ for (let i = 0; i < 1e4; ++i) {
+ arrayPush(arr, i);
+ shouldBe(arr[startIndex + i], i);
+ shouldBe(arr.length, startIndex + i + 1);
+ }
+
+ shouldBe(arr.length, maxLength);
+
+ for (let i = 0; i < 5; ++i) {
+ Object.defineProperty(Object.prototype, maxLength + i, {
+ get() { throw new Error(i + " getter should be unreachable."); },
+ set(_value) { throw new Error(i + " setter should be unreachable."); },
+ });
+ }
+
+ for (let i = 1; i < 1e4; ++i) {
+ arrayPush(arr, i);
+ shouldBe(arr.hasOwnProperty(maxLength + i), false);
+ shouldBe(arr.length, maxLength);
+ }
+})();
Modified: trunk/JSTests/test262/expectations.yaml (268488 => 268489)
--- trunk/JSTests/test262/expectations.yaml 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/JSTests/test262/expectations.yaml 2020-10-14 21:48:50 UTC (rev 268489)
@@ -1231,9 +1231,6 @@
test/built-ins/RegExp/prototype/Symbol.match/builtin-infer-unicode.js:
default: 'Test262Error: Expected SameValue(«�», «null») to be true'
strict mode: 'Test262Error: Expected SameValue(«�», «null») to be true'
-test/built-ins/RegExp/prototype/Symbol.replace/poisoned-stdlib.js:
- default: 'Test262Error: 0 setter should be unreachable.'
- strict mode: 'Test262Error: 0 setter should be unreachable.'
test/built-ins/RegExp/prototype/Symbol.search/u-lastindex-advance.js:
default: 'Test262Error: Expected SameValue(«1», «-1») to be true'
strict mode: 'Test262Error: Expected SameValue(«1», «-1») to be true'
Modified: trunk/Source/_javascript_Core/ChangeLog (268488 => 268489)
--- trunk/Source/_javascript_Core/ChangeLog 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-10-14 21:48:50 UTC (rev 268489)
@@ -1,3 +1,42 @@
+2020-10-14 Alexey Shvayka <[email protected]>
+
+ Use @putByValDirect instead of Array.prototype.@push in built-ins
+ https://bugs.webkit.org/show_bug.cgi?id=175432
+
+ Reviewed by Yusuke Suzuki.
+
+ Before this patch, Array.prototype.@push was used to implement List spec type,
+ stacks / queues, and in place of CreateDataProperty [1].
+ It's undesirably observable since elements are pushed using [[Set]],
+ affecting indexed properties on prototypes [2].
+
+ This change introduces @arrayPush() intrinsic to use with lists / stacks / queues.
+ @arrayPush() should only be used with JSArray receivers because "length" isn't
+ incremented. Unlike Array.prototype.@push, it doesn't grow arrays beyond UINT_MAX,
+ which is OK for current use cases. Object.entries microbenchmark is neutral.
+
+ Despite Array.prototype.@shift also performing [[Set]], it's safe to use with
+ non-sparse receivers.
+
+ [1]: https://tc39.es/ecma262/#sec-createarrayfromlist (step 4.a)
+ [2]: https://tc39.es/ecma262/#sec-array.prototype.push (step 5.a)
+
+ * builtins/ArrayPrototype.js:
+ (globalPrivate.sortBucketSort):
+ * builtins/ObjectConstructor.js:
+ (entries):
+ * builtins/RegExpPrototype.js:
+ (globalPrivate.matchSlow):
+ (Symbol.replace):
+ (Symbol.split):
+ * builtins/TypedArrayPrototype.js:
+ (filter):
+ * bytecode/BytecodeIntrinsicRegistry.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::BytecodeIntrinsicNode::emit_intrinsic_arrayPush):
+ * runtime/ArrayPrototype.cpp:
+ (JSC::ArrayPrototype::finishCreation):
+
2020-10-14 Don Olmstead <[email protected]>
Non-unified build fixes, mid October 2020
Modified: trunk/Source/_javascript_Core/builtins/ArrayPrototype.js (268488 => 268489)
--- trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -463,7 +463,7 @@
var c = string.@charCodeAt(depth);
var cBucket = buckets[c];
if (cBucket)
- @putByValDirect(cBucket, cBucket.length, entry);
+ @arrayPush(cBucket, entry);
else
@putByValDirect(buckets, c, [ entry ]);
}
Modified: trunk/Source/_javascript_Core/builtins/ObjectConstructor.js (268488 => 268489)
--- trunk/Source/_javascript_Core/builtins/ObjectConstructor.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/builtins/ObjectConstructor.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -35,7 +35,7 @@
for (var i = 0, length = names.length; i < length; ++i) {
var name = names[i];
if (@propertyIsEnumerable(obj, name))
- properties.@push([name, obj[name]]);
+ @putByValDirect(properties, i, [name, obj[name]]);
}
return properties;
Modified: trunk/Source/_javascript_Core/builtins/RegExpPrototype.js (268488 => 268489)
--- trunk/Source/_javascript_Core/builtins/RegExpPrototype.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/builtins/RegExpPrototype.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -132,7 +132,7 @@
if (!resultString.length)
regexp.lastIndex = @advanceStringIndex(str, regexp.lastIndex, unicode);
- resultList.@push(resultString);
+ @arrayPush(resultList, resultString);
}
}
@@ -307,7 +307,7 @@
if (result === null)
done = true;
else {
- resultList.@push(result);
+ @arrayPush(resultList, result);
if (!global)
done = true;
else {
@@ -340,7 +340,7 @@
var capN = result[n];
if (capN !== @undefined)
capN = @toString(capN);
- captures.@push(capN);
+ @arrayPush(captures, capN);
}
var replacement;
@@ -349,13 +349,13 @@
if (functionalReplace) {
var replacerArgs = [ matched ];
for (var j = 0; j < captures.length; j++)
- replacerArgs.@push(captures[j]);
+ @arrayPush(replacerArgs, captures[j]);
- replacerArgs.@push(position);
- replacerArgs.@push(str);
+ @arrayPush(replacerArgs, position);
+ @arrayPush(replacerArgs, str);
if (namedCaptures !== @undefined)
- replacerArgs.@push(namedCaptures);
+ @arrayPush(replacerArgs, namedCaptures);
var replValue = replace.@apply(@undefined, replacerArgs);
replacement = @toString(replValue);
@@ -566,7 +566,7 @@
var subStr = @stringSubstringInternal.@call(str, position, matchPosition);
// 2. Perform ! CreateDataProperty(A, ! ToString(lengthA), T).
// 3. Let lengthA be lengthA + 1.
- @putByValDirect(result, result.length, subStr);
+ @arrayPush(result, subStr);
// 4. If lengthA = lim, return A.
if (result.length == limit)
return result;
@@ -585,7 +585,7 @@
var nextCapture = matches[i];
// b. Perform ! CreateDataProperty(A, ! ToString(lengthA), nextCapture).
// d. Let lengthA be lengthA + 1.
- @putByValDirect(result, result.length, nextCapture);
+ @arrayPush(result, nextCapture);
// e. If lengthA = lim, return A.
if (result.length == limit)
return result;
@@ -600,7 +600,7 @@
// 20. Let T be a String value equal to the substring of S consisting of the elements at indices p (inclusive) through size (exclusive).
var remainingStr = @stringSubstringInternal.@call(str, position, size);
// 21. Perform ! CreateDataProperty(A, ! ToString(lengthA), T).
- @putByValDirect(result, result.length, remainingStr);
+ @arrayPush(result, remainingStr);
// 22. Return A.
return result;
}
Modified: trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js (268488 => 268489)
--- trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/builtins/TypedArrayPrototype.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -340,7 +340,7 @@
for (var i = 0; i < length; i++) {
var value = this[i];
if (callback.@call(thisArg, value, i, this))
- kept.@push(value);
+ @arrayPush(kept, value);
}
var length = kept.length;
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (268488 => 268489)
--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h 2020-10-14 21:48:50 UTC (rev 268489)
@@ -40,6 +40,7 @@
#define JSC_COMMON_BYTECODE_INTRINSIC_FUNCTIONS_EACH_NAME(macro) \
macro(argument) \
macro(argumentCount) \
+ macro(arrayPush) \
macro(getByIdDirect) \
macro(getByIdDirectPrivate) \
macro(getPrototypeOf) \
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (268488 => 268489)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2020-10-14 21:48:50 UTC (rev 268489)
@@ -1388,6 +1388,19 @@
return generator.emitArgumentCount(generator.finalDestination(dst));
}
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_arrayPush(BytecodeGenerator& generator, RegisterID* dst)
+{
+ ArgumentListNode* node = m_args->m_listNode;
+ RefPtr<RegisterID> base = generator.emitNode(node);
+ node = node->m_next;
+ RefPtr<RegisterID> value = generator.emitNode(node);
+
+ ASSERT(!node->m_next);
+
+ RefPtr<RegisterID> length = generator.emitDirectGetById(generator.newTemporary(), base.get(), generator.propertyNames().length);
+ return generator.move(dst, generator.emitDirectPutByVal(base.get(), length.get(), value.get()));
+}
+
RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect(BytecodeGenerator& generator, RegisterID* dst)
{
ArgumentListNode* node = m_args->m_listNode;
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (268488 => 268489)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2020-10-14 21:48:50 UTC (rev 268489)
@@ -86,7 +86,6 @@
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, arrayProtoFuncJoin, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("pop", arrayProtoFuncPop, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ArrayPopIntrinsic);
JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().pushPublicName(), arrayProtoFuncPush, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, ArrayPushIntrinsic);
- JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().pushPrivateName(), arrayProtoFuncPush, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly, 1, ArrayPushIntrinsic);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("reverse", arrayProtoFuncReverse, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPublicName(), arrayProtoFuncShift, static_cast<unsigned>(PropertyAttribute::DontEnum), 0);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPrivateName(), arrayProtoFuncShift, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly, 0);
Modified: trunk/Source/WebCore/ChangeLog (268488 => 268489)
--- trunk/Source/WebCore/ChangeLog 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/WebCore/ChangeLog 2020-10-14 21:48:50 UTC (rev 268489)
@@ -1,3 +1,26 @@
+2020-10-14 Alexey Shvayka <[email protected]>
+
+ Use @putByValDirect instead of Array.prototype.@push in built-ins
+ https://bugs.webkit.org/show_bug.cgi?id=175432
+
+ Reviewed by Yusuke Suzuki.
+
+ Use @arrayPush() intrinsic instead of Array.prototype.@push.
+
+ No new tests, no behavior change.
+
+ * Modules/streams/ReadableByteStreamInternals.js:
+ (readableByteStreamControllerPull):
+ (readableByteStreamControllerEnqueueChunk):
+ (readableByteStreamControllerPullInto):
+ (readableStreamAddReadIntoRequest):
+ * Modules/streams/ReadableStreamInternals.js:
+ (readableStreamAddReadRequest):
+ * Modules/streams/StreamInternals.js:
+ (enqueueValueWithSize):
+ * Modules/streams/WritableStreamInternals.js:
+ (writableStreamAddWriteRequest):
+
2020-10-14 Don Olmstead <[email protected]>
Non-unified build fixes, mid October 2020
Modified: trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js (268488 => 268489)
--- trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -243,7 +243,7 @@
ctor: @Uint8Array,
readerType: 'default'
};
- @getByIdDirectPrivate(controller, "pendingPullIntos").@push(pullIntoDescriptor);
+ @arrayPush(@getByIdDirectPrivate(controller, "pendingPullIntos"), pullIntoDescriptor);
}
const promise = @readableStreamAddReadRequest(stream);
@@ -347,7 +347,7 @@
{
"use strict";
- @getByIdDirectPrivate(controller, "queue").content.@push({
+ @arrayPush(@getByIdDirectPrivate(controller, "queue").content, {
buffer: buffer,
byteOffset: byteOffset,
byteLength: byteLength
@@ -630,7 +630,7 @@
if (@getByIdDirectPrivate(controller, "pendingPullIntos").length) {
pullIntoDescriptor.buffer = @transferBufferToCurrentRealm(pullIntoDescriptor.buffer);
- @getByIdDirectPrivate(controller, "pendingPullIntos").@push(pullIntoDescriptor);
+ @arrayPush(@getByIdDirectPrivate(controller, "pendingPullIntos"), pullIntoDescriptor);
return @readableStreamAddReadIntoRequest(stream);
}
@@ -653,7 +653,7 @@
}
pullIntoDescriptor.buffer = @transferBufferToCurrentRealm(pullIntoDescriptor.buffer);
- @getByIdDirectPrivate(controller, "pendingPullIntos").@push(pullIntoDescriptor);
+ @arrayPush(@getByIdDirectPrivate(controller, "pendingPullIntos"), pullIntoDescriptor);
const promise = @readableStreamAddReadIntoRequest(stream);
@readableByteStreamControllerCallPullIfNeeded(controller);
return promise;
@@ -667,7 +667,7 @@
@assert(@getByIdDirectPrivate(stream, "state") === @streamReadable || @getByIdDirectPrivate(stream, "state") === @streamClosed);
const readRequest = @newPromise();
- @getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readIntoRequests").@push(readRequest);
+ @arrayPush(@getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readIntoRequests"), readRequest);
return readRequest;
}
Modified: trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js (268488 => 268489)
--- trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -783,7 +783,7 @@
@assert(@getByIdDirectPrivate(stream, "state") == @streamReadable);
const readRequest = @newPromise();
- @getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests").@push(readRequest);
+ @arrayPush(@getByIdDirectPrivate(@getByIdDirectPrivate(stream, "reader"), "readRequests"), readRequest);
return readRequest;
}
Modified: trunk/Source/WebCore/Modules/streams/StreamInternals.js (268488 => 268489)
--- trunk/Source/WebCore/Modules/streams/StreamInternals.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/WebCore/Modules/streams/StreamInternals.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -143,7 +143,7 @@
size = @toNumber(size);
if (!@isFinite(size) || size < 0)
@throwRangeError("size has an incorrect value");
- queue.content.@push({ value: value, size: size });
+ @arrayPush(queue.content, { value, size });
queue.size += size;
}
Modified: trunk/Source/WebCore/Modules/streams/WritableStreamInternals.js (268488 => 268489)
--- trunk/Source/WebCore/Modules/streams/WritableStreamInternals.js 2020-10-14 21:19:02 UTC (rev 268488)
+++ trunk/Source/WebCore/Modules/streams/WritableStreamInternals.js 2020-10-14 21:48:50 UTC (rev 268489)
@@ -163,7 +163,7 @@
const writePromiseCapability = @newPromiseCapability(@Promise);
const writeRequests = @getByIdDirectPrivate(stream, "writeRequests");
- writeRequests.@push(writePromiseCapability);
+ @arrayPush(writeRequests, writePromiseCapability);
return writePromiseCapability.@promise;
}