| Index: src/builtins/builtins-array-gen.cc
|
| diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc
|
| index 32dd9b5b85cf7bbecea29d88e4c388f97fdedae4..316c0b7e9f230b5be2ed91d321150e745308b6b8 100644
|
| --- a/src/builtins/builtins-array-gen.cc
|
| +++ b/src/builtins/builtins-array-gen.cc
|
| @@ -15,13 +15,11 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| : CodeStubAssembler(state),
|
| k_(this, MachineRepresentation::kTagged),
|
| a_(this, MachineRepresentation::kTagged),
|
| - to_(this, MachineRepresentation::kTagged, SmiConstant(0)) {}
|
| -
|
| - typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm)>
|
| - BuiltinResultGenerator;
|
| + to_(this, MachineRepresentation::kTagged, SmiConstant(0)),
|
| + fully_spec_compliant_(this, {&k_, &a_, &to_}) {}
|
|
|
| typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
|
| - BuiltinResultIndexInitializer;
|
| + BuiltinResultGenerator;
|
|
|
| typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm,
|
| Node* k_value, Node* k)>
|
| @@ -30,7 +28,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)>
|
| PostLoopAction;
|
|
|
| - Node* ForEachResultGenerator() { return UndefinedConstant(); }
|
| + void ForEachResultGenerator() { a_.Bind(UndefinedConstant()); }
|
|
|
| Node* ForEachProcessor(Node* k_value, Node* k) {
|
| CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(),
|
| @@ -38,7 +36,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| return a();
|
| }
|
|
|
| - Node* SomeResultGenerator() { return FalseConstant(); }
|
| + void SomeResultGenerator() { a_.Bind(FalseConstant()); }
|
|
|
| Node* SomeProcessor(Node* k_value, Node* k) {
|
| Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
|
| @@ -51,7 +49,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| return a();
|
| }
|
|
|
| - Node* EveryResultGenerator() { return TrueConstant(); }
|
| + void EveryResultGenerator() { a_.Bind(TrueConstant()); }
|
|
|
| Node* EveryProcessor(Node* k_value, Node* k) {
|
| Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(),
|
| @@ -64,7 +62,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| return a();
|
| }
|
|
|
| - Node* ReduceResultGenerator() { return this_arg(); }
|
| + void ReduceResultGenerator() { return a_.Bind(this_arg()); }
|
|
|
| Node* ReduceProcessor(Node* k_value, Node* k) {
|
| VARIABLE(result, MachineRepresentation::kTagged);
|
| @@ -91,9 +89,9 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| BIND(&ok);
|
| }
|
|
|
| - Node* FilterResultGenerator() {
|
| + void FilterResultGenerator() {
|
| // 7. Let A be ArraySpeciesCreate(O, 0).
|
| - return ArraySpeciesCreate(context(), o(), SmiConstant(0));
|
| + a_.Bind(ArraySpeciesCreate(context(), o(), SmiConstant(0)));
|
| }
|
|
|
| Node* FilterProcessor(Node* k_value, Node* k) {
|
| @@ -162,13 +160,53 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| return a();
|
| }
|
|
|
| - Node* MapResultGenerator() {
|
| - // 5. Let A be ? ArraySpeciesCreate(O, len).
|
| - return ArraySpeciesCreate(context(), o(), len_);
|
| + void MapResultGenerator() {
|
| + Label runtime(this), done(this, {&a_});
|
| + GotoIf(DoesntHaveInstanceType(o(), JS_ARRAY_TYPE), &runtime);
|
| + Node* o_map = LoadMap(o());
|
| + Node* const initial_array_prototype = LoadContextElement(
|
| + LoadNativeContext(context()), Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
|
| + Node* proto = LoadMapPrototype(o_map);
|
| + GotoIf(WordNotEqual(proto, initial_array_prototype), &runtime);
|
| +
|
| + Node* species_protector = SpeciesProtectorConstant();
|
| + Node* value = LoadObjectField(species_protector, Cell::kValueOffset);
|
| + Node* const protector_invalid = SmiConstant(Isolate::kProtectorInvalid);
|
| + GotoIf(WordEqual(value, protector_invalid), &runtime);
|
| +
|
| + Node* const initial_array_constructor = LoadContextElement(
|
| + LoadNativeContext(context()), Context::ARRAY_FUNCTION_INDEX);
|
| + a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
|
| + initial_array_constructor, len_));
|
| + Goto(&done);
|
| +
|
| + BIND(&runtime);
|
| + {
|
| + // 5. Let A be ? ArraySpeciesCreate(O, len).
|
| + Node* constructor =
|
| + CallRuntime(Runtime::kArraySpeciesConstructor, context(), o());
|
| + a_.Bind(ConstructJS(CodeFactory::Construct(isolate()), context(),
|
| + constructor, len_));
|
| + Goto(&fully_spec_compliant_);
|
| + }
|
| + BIND(&done);
|
| + }
|
| +
|
| + Node* SpecCompliantMapProcessor(Node* k_value, Node* k) {
|
| + // i. Let kValue be ? Get(O, Pk). Performed by the caller of
|
| + // SpecCompliantMapProcessor.
|
| + // 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();
|
| }
|
|
|
| - Node* MapProcessor(Node* k_value, Node* k) {
|
| - // i. Let kValue be ? Get(O, Pk). Performed by the caller of MapProcessor.
|
| + Node* FastMapProcessor(Node* k_value, Node* k) {
|
| + // i. Let kValue be ? Get(O, Pk). Performed by the caller of
|
| + // FastMapProcessor.
|
| // ii. Let mappedValue be ? Call(callbackfn, T, kValue, k, O).
|
| Node* mappedValue = CallJS(CodeFactory::Call(isolate()), context(),
|
| callbackfn(), this_arg(), k_value, k, o());
|
| @@ -268,8 +306,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| const CallResultProcessor& processor, const PostLoopAction& action,
|
| const Callable& slow_case_continuation,
|
| ForEachDirection direction = ForEachDirection::kForward) {
|
| - Label non_array(this), slow(this, {&k_, &a_, &to_}),
|
| - array_changes(this, {&k_, &a_, &to_});
|
| + Label non_array(this), array_changes(this, {&k_, &a_, &to_});
|
|
|
| // TODO(danno): Seriously? Do we really need to throw the exact error
|
| // message on null and undefined so that the webkit tests pass?
|
| @@ -336,11 +373,11 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| k_.Bind(NumberDec(len()));
|
| }
|
|
|
| - a_.Bind(generator(this));
|
| + generator(this);
|
|
|
| - HandleFastElements(processor, action, &slow, direction);
|
| + HandleFastElements(processor, action, &fully_spec_compliant_, direction);
|
|
|
| - BIND(&slow);
|
| + BIND(&fully_spec_compliant_);
|
|
|
| Node* result =
|
| CallStub(slow_case_continuation, context(), receiver(), callbackfn(),
|
| @@ -440,7 +477,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| } else {
|
| k_.Bind(NumberDec(len()));
|
| }
|
| - a_.Bind(generator(this));
|
| + generator(this);
|
| Node* elements_type = LoadInstanceType(LoadElements(o_));
|
| Switch(elements_type, &unexpected_instance_type, instance_types.data(),
|
| label_ptrs.data(), labels.size());
|
| @@ -690,6 +727,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
|
| Variable k_;
|
| Variable a_;
|
| Variable to_;
|
| + Label fully_spec_compliant_;
|
| };
|
|
|
| TF_BUILTIN(FastArrayPush, CodeStubAssembler) {
|
| @@ -1168,7 +1206,7 @@ TF_BUILTIN(ArrayMapLoopContinuation, ArrayBuiltinCodeStubAssembler) {
|
| len, to);
|
|
|
| GenerateIteratingArrayBuiltinLoopContinuation(
|
| - &ArrayBuiltinCodeStubAssembler::MapProcessor,
|
| + &ArrayBuiltinCodeStubAssembler::SpecCompliantMapProcessor,
|
| &ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
|
| }
|
|
|
| @@ -1187,7 +1225,7 @@ TF_BUILTIN(ArrayMap, ArrayBuiltinCodeStubAssembler) {
|
|
|
| GenerateIteratingArrayBuiltinBody(
|
| "Array.prototype.map", &ArrayBuiltinCodeStubAssembler::MapResultGenerator,
|
| - &ArrayBuiltinCodeStubAssembler::MapProcessor,
|
| + &ArrayBuiltinCodeStubAssembler::FastMapProcessor,
|
| &ArrayBuiltinCodeStubAssembler::NullPostLoopAction,
|
| Builtins::CallableFor(isolate(), Builtins::kArrayMapLoopContinuation));
|
| }
|
|
|