Commit 0d4ed06c authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

Replace JS version of Array.of with a CSA version

This removes the Javascript version of Array.of in js/array.js and adds
a CodeStubAssembler version in src/builtins/builtins-array-gen.cc.

Mostly this change is for code-health reasons but it also gives
performance improvements for nearly all cases with the exception of
"transplanted" arrays. E.g.
function ArrayLike {}
ArrayLike.of = Array.of
ArrayLike.of(...) is now slower in the perf tests. Most of this change
can be attributed to using CallRuntime(kSetProperty,...) to set the
length. The JS version can do better due to inline caches trained on
the same datatype for 1000s of iterations, but this kind of workload is
unlikely.

Change-Id: I18e5b19b185257e9e0d553e1183b40ba4a5d3289
Reviewed-on: https://chromium-review.googlesource.com/863625
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50680}
parent e4d7995c
......@@ -1705,6 +1705,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
array_function, "isArray", Builtins::kArrayIsArray, 1, true);
native_context()->set_is_arraylike(*is_arraylike);
SimpleInstallFunction(array_function, "of", Builtins::kArrayOf, 0, false);
JSObject::AddProperty(proto, factory->constructor_string(), array_function,
DONT_ENUM);
......
......@@ -1840,6 +1840,83 @@ TF_BUILTIN(ArrayPrototypeFindIndex, ArrayBuiltinCodeStubAssembler) {
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
}
// ES #sec-array.of
TF_BUILTIN(ArrayOf, ArrayBuiltinCodeStubAssembler) {
TNode<Int32T> argc =
UncheckedCast<Int32T>(Parameter(BuiltinDescriptor::kArgumentsCount));
TNode<Smi> length = SmiFromWord32(argc);
TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext));
CodeStubArguments args(this, length, nullptr, ParameterMode::SMI_PARAMETERS,
CodeStubArguments::ReceiverMode::kHasReceiver);
TVARIABLE(Object, array);
TNode<Object> receiver = args.GetReceiver();
{
Label is_constructor(this), is_not_constructor(this), next(this);
GotoIf(TaggedIsSmi(receiver), &is_not_constructor);
Branch(IsConstructor(receiver), &is_constructor, &is_not_constructor);
BIND(&is_constructor);
{
array = CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
receiver, length));
Goto(&next);
}
BIND(&is_not_constructor);
{
TNode<Map> array_map = CAST(LoadContextElement(
context, Context::JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX));
// TODO(delphick): Consider using AllocateUninitializedJSArrayWithElements
// to avoid initializing an array and then writing over it.
array = CAST(AllocateJSArray(PACKED_SMI_ELEMENTS, array_map, length,
SmiConstant(0), nullptr,
ParameterMode::SMI_PARAMETERS));
Goto(&next);
}
BIND(&next);
}
BuildFastLoop(SmiConstant(0), length,
[this, context, &array, args](Node* index) {
CallRuntime(
Runtime::kCreateDataProperty, context,
static_cast<Node*>(array), index,
args.AtIndex(index, ParameterMode::SMI_PARAMETERS));
},
1, ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost);
{
Label is_js_array(this), is_not_js_array(this), next(this);
// TODO(delphick): Consider changing this since it does an an unnecessary
// check for SMIs.
// TODO(delphick): Also we could hoist this to after the array construction
// and copy the args into array in the same way as the Array constructor.
BranchIfFastJSArray(array, context, &is_js_array, &is_not_js_array);
BIND(&is_js_array);
{
StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
Goto(&next);
}
BIND(&is_not_js_array);
{
CallRuntime(Runtime::kSetProperty, context, static_cast<Node*>(array),
CodeStubAssembler::LengthStringConstant(), length,
SmiConstant(LanguageMode::kStrict));
Goto(&next);
}
BIND(&next);
}
args.PopAndReturn(array);
}
// ES #sec-get-%typedarray%.prototype.find
TF_BUILTIN(TypedArrayPrototypeFind, ArrayBuiltinCodeStubAssembler) {
Node* argc =
......
......@@ -247,6 +247,8 @@ namespace internal {
CPP(ArrayConcat) \
/* ES6 #sec-array.isarray */ \
TFJ(ArrayIsArray, 1, kArg) \
/* ES6 #sec-array.of */ \
TFJ(ArrayOf, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES7 #sec-array.prototype.includes */ \
TFJ(ArrayIncludes, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.indexof */ \
......
......@@ -1210,24 +1210,6 @@ DEFINE_METHOD_LEN(
1 /* Set function length. */
);
// ES6, draft 05-22-14, section 22.1.2.3
DEFINE_METHOD(
GlobalArray,
of(...args) {
var length = args.length;
var constructor = this;
// TODO: Implement IsConstructor (ES6 section 7.2.5)
var array = %IsConstructor(constructor) ? new constructor(length) : [];
for (var i = 0; i < length; i++) {
%CreateDataProperty(array, i, args[i]);
}
array.length = length;
return array;
}
);
// -------------------------------------------------------------------
// Set up unscopable properties on the Array.prototype object.
var unscopables = {
__proto__: null,
......
Markdown is supported
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