Commit 6545ee7a authored by Iain Ireland's avatar Iain Ireland Committed by Richard Pospesel
Browse files

Bug 1770048: Improve self-hosted new_List (ESR) r=jandem,tcampbell, a=dsmith

Differential Revision: https://phabricator.services.mozilla.com/D146774
parent 0d4fe6c6
......@@ -4243,3 +4243,35 @@ JS_PUBLIC_API bool JS::SetArrayLength(JSContext* cx, Handle<JSObject*> obj,
return SetLengthProperty(cx, obj, length);
}
bool js::intrinsic_newList(JSContext* cx, unsigned argc, js::Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
size_t length = 0;
gc::AllocKind allocKind = GuessArrayGCKind(length);
MOZ_ASSERT(CanChangeToBackgroundAllocKind(allocKind, &ArrayObject::class_));
allocKind = ForegroundToBackgroundAllocKind(allocKind);
/*
* Get a shape with zero fixed slots, regardless of the size class.
* See JSObject::createArray.
*/
RootedShape shape(
cx, SharedShape::getInitialShape(cx, &ArrayObject::class_, cx->realm(),
TaggedProto(), gc::AllocKind::OBJECT0));
if (!shape) {
return false;
}
gc::InitialHeap heap = gc::InitialHeap::DefaultHeap;
AutoSetNewObjectMetadata metadata(cx);
RootedArrayObject list(cx, ArrayObject::createArray(cx, allocKind, heap,
shape, length, metadata));
if (!list || !AddLengthProperty(cx, list)) {
return false;
}
args.rval().setObject(*list);
return true;
}
......@@ -116,6 +116,8 @@ 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);
extern bool intrinsic_newList(JSContext* cx, unsigned argc, js::Value* vp);
/*
* Append the given (non-hole) value to the end of an array. The array must be
* a newborn array -- that is, one which has not been exposed to script for
......
......@@ -14,7 +14,7 @@ function CallModuleResolveHook(module, moduleRequest, expectedMinimumStatus)
// https://tc39.es/ecma262/#sec-getexportednames
// ES2020 15.2.1.17.2 GetExportedNames
function ModuleGetExportedNames(exportStarSet = [])
function ModuleGetExportedNames(exportStarSet = new_List())
{
if (!IsObject(this) || !IsModule(this)) {
return callFunction(CallModuleMethodIfWrapped, this, exportStarSet,
......@@ -26,13 +26,13 @@ function ModuleGetExportedNames(exportStarSet = [])
// Step 4
if (callFunction(ArrayIncludes, exportStarSet, module))
return [];
return new_List();
// Step 5
DefineDataProperty(exportStarSet, exportStarSet.length, module);
// Step 6
let exportedNames = [];
let exportedNames = new_List();
let namesCount = 0;
// Step 7
......@@ -99,7 +99,7 @@ function ModuleSetStatus(module, newStatus)
// - If the request is found to be ambiguous, the string `"ambiguous"` is
// returned.
//
function ModuleResolveExport(exportName, resolveSet = [])
function ModuleResolveExport(exportName, resolveSet = new_List())
{
assert(typeof exportName === "string", "ModuleResolveExport");
......@@ -206,7 +206,7 @@ function GetModuleNamespace(module)
// Step 4
if (typeof namespace === "undefined") {
let exportedNames = callFunction(module.getExportedNames, module);
let unambiguousNames = [];
let unambiguousNames = new_List();
for (let i = 0; i < exportedNames.length; i++) {
let name = exportedNames[i];
let resolution = callFunction(module.resolveExport, module, name);
......@@ -312,7 +312,7 @@ function ModuleInstantiate()
}
// Step 3
let stack = [];
let stack = new_List();
// Steps 4-5
try {
......@@ -606,7 +606,7 @@ function ModuleEvaluate()
}
// Step 4
let stack = [];
let stack = new_List();
// Steps 5-6
try {
......@@ -769,7 +769,7 @@ function InnerModuleEvaluation(module, stack, index)
}
// https://tc39.es/proposal-top-level-await/#sec-gather-async-parent-completions
function GatherAsyncParentCompletions(module, execList = []) {
function GatherAsyncParentCompletions(module, execList = new_List()) {
assert(module.status == MODULE_STATUS_EVALUATED, "bad status for async module");
// Step 5.
......@@ -809,4 +809,3 @@ function ExecuteAsyncModule(module) {
ExecuteModule(module);
}
......@@ -349,7 +349,7 @@ function RegExpReplaceSlowPath(rx, S, lengthS, replaceValue,
}
// Step 9.
var results = [];
var results = new_List();
var nResults = 0;
// Step 11.
......@@ -456,7 +456,7 @@ function RegExpGetComplexReplacement(result, matched, S, position,
functionalReplace, firstDollarIndex)
{
// Step 14.h.
var captures = [];
var captures = new_List();
var capturesLength = 0;
// Step 14.k.i (reordered).
......@@ -546,7 +546,7 @@ function RegExpGetFunctionalReplacement(result, S, position, replaceValue) {
}
// Steps 14.g-i, 14.k.i-ii.
var captures = [];
var captures = new_List();
for (var n = 0; n <= nCaptures; n++) {
assert(typeof result[n] === "string" || result[n] === undefined,
"RegExpMatcher returns only strings and undefined");
......
......@@ -27,16 +27,7 @@
// code are installed via the std_functions JSFunctionSpec[] in
// SelfHosting.cpp.
/********** List / Record specification types **********/
// A "List" is an internal type used in the ECMAScript spec to define a simple
// ordered list of values. It is never exposed to user script, but we use a
// simple Object (with null prototype) as a convenient implementation.
//
// NOTE: This does not track a `length` field.
function new_List() {
return std_Object_create(null);
}
/********** Specification types **********/
// A "Record" is an internal type used in the ECMAScript spec to define a struct
......
......@@ -2386,7 +2386,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("UnsafeSetReservedSlot", intrinsic_UnsafeSetReservedSlot, 3,
0, IntrinsicUnsafeSetReservedSlot),
// Intrinsics and standard functions used by Intl API implementation.
// Intrinsics and standard functions used by Intl API implementation.
#ifdef JS_HAS_INTL_API
JS_FN("intl_BestAvailableLocale", intl_BestAvailableLocale, 3, 0),
JS_FN("intl_CallCollatorMethodIfWrapped",
......@@ -2476,6 +2476,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
#endif // JS_HAS_INTL_API
// Standard builtins used by self-hosting.
JS_FN("new_List", intrinsic_newList, 0, 0),
JS_INLINABLE_FN("std_Array", array_construct, 1, 0, Array),
JS_INLINABLE_FN("std_Array_pop", array_pop, 0, 0, ArrayPop),
JS_INLINABLE_FN("std_Array_push", array_push, 1, 0, ArrayPush),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment