Bug 1790275 - Part 5: Change ArrayPushDense to use [[Define]] instead of [[Set]] semantics. r=jandem

This is just nice to have at this point, but might make it a bit more clearer
what should happen when `setOrExtendDenseElements` returns `Incomplete`. For
example we don't want to execute a [[Set]] operation which might trigger
accessors on the prototype chain. (`array_push` uses [[Set]] internally.)

Depends on D157104

Differential Revision: https://phabricator.services.mozilla.com/D157105
This commit is contained in:
André Bargull 2022-09-12 12:44:32 +00:00
Родитель c518b868d3
Коммит 93c6e48cfa
3 изменённых файлов: 27 добавлений и 24 удалений

Просмотреть файл

@ -2266,7 +2266,7 @@ bool js::NewbornArrayPush(JSContext* cx, HandleObject obj, const Value& v) {
// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
// 22.1.3.18 Array.prototype.push ( ...items )
bool js::array_push(JSContext* cx, unsigned argc, Value* vp) {
static bool array_push(JSContext* cx, unsigned argc, Value* vp) {
AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "push");
CallArgs args = CallArgsFromVp(argc, vp);
@ -2431,7 +2431,7 @@ static DenseElementResult ArrayShiftDenseKernel(JSContext* cx, HandleObject obj,
// ES2017 draft rev 1b0184bc17fc09a8ddcf4aeec9b6d9fcac4eafce
// 22.1.3.22 Array.prototype.shift ( )
bool js::array_shift(JSContext* cx, unsigned argc, Value* vp) {
static bool array_shift(JSContext* cx, unsigned argc, Value* vp) {
AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "shift");
CallArgs args = CallArgsFromVp(argc, vp);
@ -3822,7 +3822,7 @@ static bool ArraySliceOrdinary(JSContext* cx, HandleObject obj, uint64_t begin,
}
/* ES 2016 draft Mar 25, 2016 22.1.3.23. */
bool js::array_slice(JSContext* cx, unsigned argc, Value* vp) {
static bool array_slice(JSContext* cx, unsigned argc, Value* vp) {
AutoJSMethodProfilerEntry pseudoFrame(cx, "Array.prototype", "slice");
CallArgs args = CallArgsFromVp(argc, vp);

Просмотреть файл

@ -110,18 +110,12 @@ extern bool array_includes(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_indexOf(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_lastIndexOf(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_push(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_pop(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_join(JSContext* cx, unsigned argc, js::Value* vp);
extern void ArrayShiftMoveElements(ArrayObject* arr);
extern bool array_shift(JSContext* cx, unsigned argc, js::Value* vp);
extern bool array_slice(JSContext* cx, unsigned argc, js::Value* vp);
extern JSObject* ArraySliceDense(JSContext* cx, HandleObject obj, int32_t begin,
int32_t end, HandleObject result);

Просмотреть файл

@ -643,25 +643,34 @@ template bool StringsCompare<ComparisonKind::GreaterThanOrEqual>(
bool ArrayPushDense(JSContext* cx, Handle<ArrayObject*> arr, HandleValue v,
uint32_t* length) {
*length = arr->length();
DenseElementResult result =
arr->setOrExtendDenseElements(cx, *length, v.address(), 1);
if (result != DenseElementResult::Incomplete) {
(*length)++;
return result == DenseElementResult::Success;
}
// Shape guards guarantee that the input is an extensible ArrayObject, which
// has a writable "length" property and has no other indexed properties.
MOZ_ASSERT(arr->isExtensible());
MOZ_ASSERT(arr->lengthIsWritable());
MOZ_ASSERT(!arr->isIndexed());
JS::RootedValueArray<3> argv(cx);
argv[0].setUndefined();
argv[1].setObject(*arr);
argv[2].set(v);
if (!js::array_push(cx, 1, argv.begin())) {
return false;
}
// Shape guards ensure that there aren't any indexed properties along the
// prototype chain.
MOZ_ASSERT(!PrototypeMayHaveIndexedProperties(arr));
// Length must fit in an int32 because we guard against overflow before
// calling this VM function.
*length = argv[0].toInt32();
uint32_t index = arr->length();
MOZ_ASSERT(index < uint32_t(INT32_MAX));
DenseElementResult result =
arr->setOrExtendDenseElements(cx, index, v.address(), 1);
if (result != DenseElementResult::Incomplete) {
*length = index + 1;
return result == DenseElementResult::Success;
}
if (!DefineDataElement(cx, arr, index, v)) {
return false;
}
arr->setLength(index + 1);
*length = index + 1;
return true;
}