Commit 304e74c8 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Torque] Array.prototype.map implemented in Torque

Change-Id: I3a60be25b9c7daadcad6078447348b790b249e1c
Reviewed-on: https://chromium-review.googlesource.com/c/1402774
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59042}
parent 7e616f2b
......@@ -865,6 +865,7 @@ torque_files = [
"src/builtins/array-join.tq",
"src/builtins/array-lastindexof.tq",
"src/builtins/array-of.tq",
"src/builtins/array-map.tq",
"src/builtins/array-reverse.tq",
"src/builtins/array-slice.tq",
"src/builtins/array-splice.tq",
......
This diff is collapsed.
......@@ -93,6 +93,10 @@ class JSArray extends JSObject {
kEmptyFixedArray);
this.length = 0;
}
constructor(implicit context: Context)(map: Map, elements: FixedArrayBase) {
super(map, kEmptyFixedArray, elements);
this.length = elements.length;
}
IsEmpty(): bool {
return this.length == 0;
}
......@@ -232,11 +236,12 @@ const BIGINT64_ELEMENTS:
const kNone:
constexpr AllocationFlags generates 'CodeStubAssembler::kNone';
const kDoubleAlignment:
constexpr AllocationFlags generates 'kDoubleAlignment';
const kPretenured: constexpr AllocationFlags generates 'kPretenured';
const kAllowLargeObjectAllocation:
constexpr AllocationFlags generates 'kAllowLargeObjectAllocation';
const kDoubleAlignment: constexpr AllocationFlags
generates 'CodeStubAssembler::kDoubleAlignment';
const kPretenured:
constexpr AllocationFlags generates 'CodeStubAssembler::kPretenured';
const kAllowLargeObjectAllocation: constexpr AllocationFlags
generates 'CodeStubAssembler::kAllowLargeObjectAllocation';
type FixedUint8Array extends FixedTypedArray;
type FixedInt8Array extends FixedTypedArray;
......@@ -1072,8 +1077,8 @@ UnsafeCast<Object>(o: Object): Object {
}
const kCOWMap: Map = %RawObjectCast<Map>(LoadRoot(kFixedCOWArrayMapRootIndex));
const kEmptyFixedArray: FixedArrayBase =
%RawObjectCast<FixedArrayBase>(LoadRoot(kEmptyFixedArrayRootIndex));
const kEmptyFixedArray: FixedArray =
%RawObjectCast<FixedArray>(LoadRoot(kEmptyFixedArrayRootIndex));
extern macro IsPrototypeInitialArrayPrototype(implicit context: Context)(Map):
bool;
......@@ -1105,6 +1110,7 @@ extern operator '[]' macro LoadFixedArrayElement(
FixedArray, constexpr int31): Object;
extern operator '[]=' macro StoreFixedArrayElement(
FixedArray, intptr, Smi): void;
extern operator '[]=' macro StoreFixedArrayElement(FixedArray, Smi, Smi): void;
extern operator '[]=' macro StoreFixedArrayElement(
FixedArray, intptr, HeapObject): void;
extern operator '[]=' macro StoreFixedArrayElement(
......@@ -1148,6 +1154,16 @@ extern macro IsFastSmiOrTaggedElementsKind(ElementsKind): bool;
extern macro IsFastSmiElementsKind(ElementsKind): bool;
extern macro IsHoleyFastElementsKind(ElementsKind): bool;
macro FastHoleyElementsKind(kind: ElementsKind): ElementsKind {
if (kind == PACKED_SMI_ELEMENTS) {
return HOLEY_SMI_ELEMENTS;
} else if (kind == PACKED_DOUBLE_ELEMENTS) {
return HOLEY_DOUBLE_ELEMENTS;
}
assert(kind == PACKED_ELEMENTS);
return HOLEY_ELEMENTS;
}
macro AllowDoubleElements(kind: ElementsKind): ElementsKind {
if (kind == PACKED_SMI_ELEMENTS) {
return PACKED_DOUBLE_ELEMENTS;
......@@ -1177,6 +1193,8 @@ extern macro CalculateNewElementsCapacity(intptr): intptr;
extern macro AllocateFixedArrayWithHoles(
intptr, constexpr AllocationFlags): FixedArray;
extern macro AllocateFixedDoubleArrayWithHoles(
intptr, constexpr AllocationFlags): FixedDoubleArray;
extern macro CopyFixedArrayElements(
constexpr ElementsKind, FixedArray, constexpr ElementsKind, FixedArray,
intptr, intptr, intptr): void;
......@@ -1186,7 +1204,6 @@ extern macro CopyFixedArrayElements(
extern macro AllocateJSArray(constexpr ElementsKind, Map, intptr, Smi): JSArray;
extern macro AllocateJSArray(constexpr ElementsKind, Map, Smi, Smi): JSArray;
extern macro AllocateJSObjectFromMap(Map): JSObject;
extern operator '[]=' macro StoreFixedDoubleArrayElementSmi(
......@@ -1300,7 +1317,8 @@ LoadElementNoHole<FixedDoubleArray>(implicit context: Context)(
}
extern macro TransitionElementsKind(
JSObject, Map, ElementsKind, ElementsKind): void labels Bailout;
JSObject, Map, constexpr ElementsKind,
constexpr ElementsKind): void labels Bailout;
extern macro IsCallable(HeapObject): bool;
extern macro IsJSArray(HeapObject): bool;
......
......@@ -126,10 +126,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
BIND(&ok);
}
void ArrayBuiltinsAssembler::MapResultGenerator() {
GenerateArraySpeciesCreate(len_);
}
void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() {
// 6. Let A be ? TypedArraySpeciesCreate(O, len).
TNode<JSTypedArray> original_array = CAST(o());
......@@ -148,120 +144,6 @@ Node* ArrayBuiltinsAssembler::FindProcessor(Node* k_value, Node* k) {
a_.Bind(a);
}
Node* ArrayBuiltinsAssembler::SpecCompliantMapProcessor(Node* k_value,
Node* k) {
// i. Let kValue be ? Get(O, Pk). Performed by the caller of
// SpecCompliantMapProcessor.
// ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mapped_value);
return a();
}
Node* ArrayBuiltinsAssembler::FastMapProcessor(Node* k_value, Node* k) {
// i. Let kValue be ? Get(O, Pk). Performed by the caller of
// FastMapProcessor.
// ii. Let mapped_value be ? Call(callbackfn, T, kValue, k, O).
Node* mapped_value = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
// mode is SMI_PARAMETERS because k has tagged representation.
ParameterMode mode = SMI_PARAMETERS;
Label runtime(this), finished(this);
Label transition_pre(this), transition_smi_fast(this),
transition_smi_double(this);
Label array_not_smi(this), array_fast(this), array_double(this);
TNode<Int32T> kind = LoadElementsKind(a());
Node* elements = LoadElements(a());
GotoIf(IsElementsKindGreaterThan(kind, HOLEY_SMI_ELEMENTS), &array_not_smi);
TryStoreArrayElement(HOLEY_SMI_ELEMENTS, mode, &transition_pre, elements, k,
mapped_value);
Goto(&finished);
BIND(&transition_pre);
{
// array is smi. Value is either tagged or a heap number.
CSA_ASSERT(this, TaggedIsNotSmi(mapped_value));
GotoIf(IsHeapNumberMap(LoadMap(mapped_value)), &transition_smi_double);
Goto(&transition_smi_fast);
}
BIND(&array_not_smi);
{
Branch(IsElementsKindGreaterThan(kind, HOLEY_ELEMENTS), &array_double,
&array_fast);
}
BIND(&transition_smi_fast);
{
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
Node* const native_context = LoadNativeContext(context());
Node* const fast_map = LoadContextElement(
native_context, Context::JS_ARRAY_HOLEY_ELEMENTS_MAP_INDEX);
// Since this transition is only a map change, just do it right here.
// Since a() doesn't have an allocation site, it's safe to do the
// map store directly, otherwise I'd call TransitionElementsKind().
StoreMap(a(), fast_map);
Goto(&array_fast);
}
BIND(&array_fast);
{
TryStoreArrayElement(HOLEY_ELEMENTS, mode, &runtime, elements, k,
mapped_value);
Goto(&finished);
}
BIND(&transition_smi_double);
{
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
Node* const native_context = LoadNativeContext(context());
Node* const double_map = LoadContextElement(
native_context, Context::JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX);
const ElementsKind kFromKind = HOLEY_SMI_ELEMENTS;
const ElementsKind kToKind = HOLEY_DOUBLE_ELEMENTS;
Label transition_in_runtime(this, Label::kDeferred);
TransitionElementsKind(a(), double_map, kFromKind, kToKind,
&transition_in_runtime);
Goto(&array_double);
BIND(&transition_in_runtime);
CallRuntime(Runtime::kTransitionElementsKind, context(), a(), double_map);
Goto(&array_double);
}
BIND(&array_double);
{
// TODO(mvstanton): If we use a variable for elements and bind it
// appropriately, we can avoid an extra load of elements by binding the
// value only after a transition from smi to double.
elements = LoadElements(a());
// If the mapped_value isn't a number, this will bail out to the runtime
// to make the transition.
TryStoreArrayElement(HOLEY_DOUBLE_ELEMENTS, mode, &runtime, elements, k,
mapped_value);
Goto(&finished);
}
BIND(&runtime);
{
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mapped_value).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), k,
mapped_value);
Goto(&finished);
}
BIND(&finished);
return a();
}
// See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map.
Node* ArrayBuiltinsAssembler::TypedArrayMapProcessor(Node* k_value, Node* k) {
// 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »).
......@@ -2128,84 +2010,6 @@ TF_BUILTIN(TypedArrayPrototypeReduceRight, ArrayBuiltinsAssembler) {
ForEachDirection::kReverse);
}
TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
TNode<JSReceiver> object = CAST(Parameter(Descriptor::kObject));
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinsAssembler::SpecCompliantMapProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction, MissingPropertyMode::kSkip);
}
TF_BUILTIN(ArrayMapLoopEagerDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
callbackfn, this_arg, array, receiver, initial_k, len,
UndefinedConstant()));
}
TF_BUILTIN(ArrayMapLoopLazyDeoptContinuation, ArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
Node* initial_k = Parameter(Descriptor::kInitialK);
TNode<Number> len = CAST(Parameter(Descriptor::kLength));
Node* result = Parameter(Descriptor::kResult);
// This custom lazy deopt point is right after the callback. map() needs
// to pick up at the next step, which is setting the callback result in
// the output array. After incrementing k, we can glide into the loop
// continuation builtin.
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
CallRuntime(Runtime::kCreateDataProperty, context, array, initial_k, result);
// Then we have to increment k before going on.
initial_k = NumberInc(initial_k);
Return(CallBuiltin(Builtins::kArrayMapLoopContinuation, context, receiver,
callbackfn, this_arg, array, receiver, initial_k, len,
UndefinedConstant()));
}
TF_BUILTIN(ArrayMap, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = args.GetReceiver();
Node* callbackfn = args.GetOptionalArgumentValue(0);
Node* this_arg = args.GetOptionalArgumentValue(1);
InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg, argc);
GenerateIteratingArrayBuiltinBody(
"Array.prototype.map", &ArrayBuiltinsAssembler::MapResultGenerator,
&ArrayBuiltinsAssembler::FastMapProcessor,
&ArrayBuiltinsAssembler::NullPostLoopAction,
Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation),
MissingPropertyMode::kSkip);
}
TF_BUILTIN(TypedArrayPrototypeMap, ArrayBuiltinsAssembler) {
TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
......
......@@ -364,14 +364,6 @@ namespace internal {
TFJ(ArraySomeLoopLazyDeoptContinuation, 5, kReceiver, kCallbackFn, kThisArg, \
kInitialK, kLength, kResult) \
TFJ(ArraySome, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.foreach */ \
TFS(ArrayMapLoopContinuation, kReceiver, kCallbackFn, kThisArg, kArray, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayMapLoopEagerDeoptContinuation, 5, kReceiver, kCallbackFn, kThisArg, \
kArray, kInitialK, kLength) \
TFJ(ArrayMapLoopLazyDeoptContinuation, 6, kReceiver, kCallbackFn, kThisArg, \
kArray, kInitialK, kLength, kResult) \
TFJ(ArrayMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.reduce */ \
TFS(ArrayReduceLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \
......
......@@ -1262,6 +1262,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Smi> value) {
StoreFixedArrayElement(array, index, value, SKIP_WRITE_BARRIER, 0);
}
void StoreFixedArrayElement(TNode<FixedArray> array, TNode<Smi> index,
TNode<Smi> value) {
StoreFixedArrayElement(array, index, value, SKIP_WRITE_BARRIER, 0,
SMI_PARAMETERS);
}
void StoreFixedDoubleArrayElement(
TNode<FixedDoubleArray> object, Node* index, TNode<Float64T> value,
......@@ -1532,6 +1537,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
return result;
}
TNode<FixedDoubleArray> AllocateFixedDoubleArrayWithHoles(
TNode<IntPtrT> capacity, AllocationFlags flags) {
TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity, flags));
FillFixedArrayWithValue(PACKED_DOUBLE_ELEMENTS, result, IntPtrConstant(0),
capacity, RootIndex::kTheHoleValue);
return result;
}
Node* AllocatePropertyArray(Node* capacity,
ParameterMode mode = INTPTR_PARAMETERS,
AllocationFlags flags = kNone);
......
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