[Builtins] Provide a code-stub impl. of Array.prototype.map

BUG=

Review-Url: https://codereview.chromium.org/2765293002
Cr-Commit-Position: refs/heads/master@{#44093}
This commit is contained in:
mvstanton 2017-03-24 04:01:53 -07:00 committed by Commit bot
parent f764a5c8c0
commit 69e02958d3
5 changed files with 79 additions and 12 deletions

View File

@ -3714,6 +3714,7 @@ void Genesis::InitializeGlobal_experimental_fast_array_builtins() {
// Insert experimental fast array builtins here.
InstallOneBuiltinFunction("Array", "filter", Builtins::kArrayFilter);
InstallOneBuiltinFunction("Array", "map", Builtins::kArrayMap);
}
void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {

View File

@ -129,24 +129,42 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
}
Node* FilterProcessor(Node* k_value, Node* k) {
Node* callback_result = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
// ii. Let selected be ToBoolean(? Call(callbackfn, T, kValue, k, O)).
Node* selected = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
Label true_continue(this, &to_), false_continue(this);
BranchIfToBooleanIsTrue(callback_result, &true_continue, &false_continue);
BranchIfToBooleanIsTrue(selected, &true_continue, &false_continue);
Bind(&true_continue);
// iii. If selected is true, then...
{
// 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(),
k_value);
// 1. let status be CreateDataPropertyOrThrow(A, ToString(to), kValue).
// 2. ReturnIfAbrupt(status)
Node* const p_to = ToString(context(), to_.value());
CallRuntime(Runtime::kCreateDataProperty, context(), a(), p_to, k_value);
// 3. Increase to by 1.
to_.Bind(NumberInc(to_.value()));
Goto(&false_continue);
// 2. Increase to by 1.
to_.Bind(NumberInc(to_.value()));
Goto(&false_continue);
}
Bind(&false_continue);
return a();
}
Node* MapResultGenerator() {
// 5. Let A be ? ArraySpeciesCreate(O, len).
return ArraySpeciesCreate(context(), o(), len_);
}
Node* MapProcessor(Node* k_value, Node* k) {
// i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor.
// ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue);
return a();
}
void NullPostLoopAction() {}
protected:
@ -770,13 +788,50 @@ TF_BUILTIN(ArrayFilter, ArrayBuiltinCodeStubAssembler) {
new_target);
GenerateIteratingArrayBuiltinBody(
"Array.prototype.reduce",
"Array.prototype.filter",
&ArrayBuiltinCodeStubAssembler::FilterResultGenerator,
&ArrayBuiltinCodeStubAssembler::FilterProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
CodeFactory::ArrayFilterLoopContinuation(isolate()));
}
TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* array = Parameter(Descriptor::kArray);
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::MapProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* this_arg = Parameter(Descriptor::kThisArg);
Node* new_target = Parameter(Descriptor::kNewTarget);
InitIteratingArrayBuiltinBody(context, receiver, callbackfn, this_arg,
new_target);
GenerateIteratingArrayBuiltinBody(
"Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
&ArrayBuiltinCodeStubAssembler::MapProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
CodeFactory::ArrayMapLoopContinuation(isolate()));
}
TF_BUILTIN(ArrayIsArray, CodeStubAssembler) {
Node* object = Parameter(Descriptor::kArg);
Node* context = Parameter(Descriptor::kContext);

View File

@ -300,6 +300,10 @@ class Isolate;
TFJ(ArrayFilterLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayFilter, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.foreach */ \
TFJ(ArrayMapLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayMap, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.reduce */ \
TFJ(ArrayReduceLoopContinuation, 7, kCallbackFn, kThisArg, kAccumulator, \
kObject, kInitialK, kLength, kTo) \

View File

@ -513,6 +513,12 @@ Callable CodeFactory::ArrayFilterLoopContinuation(Isolate* isolate) {
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayMapLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayMapLoopContinuation(),
IteratingArrayBuiltinLoopContinuationDescriptor(isolate));
}
// static
Callable CodeFactory::ArrayForEachLoopContinuation(Isolate* isolate) {
return Callable(isolate->builtins()->ArrayForEachLoopContinuation(),

View File

@ -185,6 +185,7 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable ArrayConstructor(Isolate* isolate);
static Callable ArrayPush(Isolate* isolate);
static Callable ArrayFilterLoopContinuation(Isolate* isolate);
static Callable ArrayMapLoopContinuation(Isolate* isolate);
static Callable ArrayForEachLoopContinuation(Isolate* isolate);
static Callable ArraySomeLoopContinuation(Isolate* isolate);
static Callable ArrayEveryLoopContinuation(Isolate* isolate);