Chromium Code Reviews| Index: src/builtins/builtins-array-gen.cc |
| diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
| index 6a51a4ac36e02255bec75da15be8c6baa9b1a747..9b78a4602b8672216c0eb35afca4477b6532d7a7 100644 |
| --- a/src/builtins/builtins-array-gen.cc |
| +++ b/src/builtins/builtins-array-gen.cc |
| @@ -24,7 +24,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| BuiltinResultIndexInitializer; |
| typedef std::function<Node*(ArrayBuiltinCodeStubAssembler* masm, |
| - Node* k_value, Node* k)> |
| + ElementsKind o_kind, Node* k_value, Node* k)> |
| CallResultProcessor; |
| typedef std::function<void(ArrayBuiltinCodeStubAssembler* masm)> |
| @@ -32,7 +32,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| Node* ForEachResultGenerator() { return UndefinedConstant(); } |
| - Node* ForEachProcessor(Node* k_value, Node* k) { |
| + Node* ForEachProcessor(ElementsKind o_kind, Node* k_value, Node* k) { |
| CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), this_arg(), |
| k_value, k, o()); |
| return a(); |
| @@ -40,7 +40,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| Node* SomeResultGenerator() { return FalseConstant(); } |
| - Node* SomeProcessor(Node* k_value, Node* k) { |
| + Node* SomeProcessor(ElementsKind o_kind, Node* k_value, Node* k) { |
| Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), |
| this_arg(), k_value, k, o()); |
| Label false_continue(this), return_true(this); |
| @@ -53,7 +53,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| Node* EveryResultGenerator() { return TrueConstant(); } |
| - Node* EveryProcessor(Node* k_value, Node* k) { |
| + Node* EveryProcessor(ElementsKind o_kind, Node* k_value, Node* k) { |
| Node* value = CallJS(CodeFactory::Call(isolate()), context(), callbackfn(), |
| this_arg(), k_value, k, o()); |
| Label true_continue(this), return_false(this); |
| @@ -98,7 +98,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| return a.value(); |
| } |
| - Node* ReduceProcessor(Node* k_value, Node* k) { |
| + Node* ReduceProcessor(ElementsKind o_kind, Node* k_value, Node* k) { |
| Variable result(this, MachineRepresentation::kTagged); |
| Label done(this, {&result}), initial(this); |
| GotoIf(WordEqual(a(), TheHoleConstant()), &initial); |
| @@ -128,22 +128,68 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| return ArraySpeciesCreate(context(), o(), SmiConstant(0)); |
| } |
| - Node* FilterProcessor(Node* k_value, Node* k) { |
| + Node* FilterProcessor(ElementsKind o_kind, Node* k_value, Node* k) { |
| // 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(selected, &true_continue, &false_continue); |
| Bind(&true_continue); |
| - // iii. If selected is true, then... |
| { |
| + // iii. If selected is true, then... |
| + Label after_work(this, &to_); |
| + if (o_kind < DICTIONARY_ELEMENTS) { |
|
danno
2017/04/03 15:35:27
Please use the predicates in elements-kind.h, e.g.
mvstanton
2017/04/06 08:57:36
Per our discussion, I'll just remove the o_kind pa
|
| + Node* kind = nullptr; |
| + |
| + // If a() is a JSArray, we can have a fast path. |
| + Label fast(this); |
| + Label runtime(this); |
| + Label object_push_pre(this), object_push(this), double_push(this); |
|
danno
2017/04/03 15:35:27
I think you can make this slightly better. Since y
mvstanton
2017/04/06 08:57:36
Right, because of the vagaries of what can happen
|
| + BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
| + &fast, &runtime); |
| + |
| + Bind(&fast); |
| + { |
| + kind = EnsureArrayPushable(a(), &runtime); |
| + GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), |
| + &object_push_pre); |
| + |
| + BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime); |
| + Goto(&after_work); |
| + } |
| + |
| + Bind(&object_push_pre); |
| + { |
| + Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
| + &double_push, &object_push); |
| + } |
| + |
| + Bind(&object_push); |
| + { |
| + BuildAppendJSArray(FAST_ELEMENTS, a(), k_value, &runtime); |
| + Goto(&after_work); |
| + } |
| + |
| + Bind(&double_push); |
| + { |
| + BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, a(), k_value, &runtime); |
| + Goto(&after_work); |
| + } |
| + |
| + Bind(&runtime); |
| + } |
| + |
| // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue). |
| CallRuntime(Runtime::kCreateDataProperty, context(), a(), to_.value(), |
| k_value); |
| + Goto(&after_work); |
| - // 2. Increase to by 1. |
| - to_.Bind(NumberInc(to_.value())); |
| - Goto(&false_continue); |
| + Bind(&after_work); |
| + { |
| + // 2. Increase to by 1. |
| + to_.Bind(NumberInc(to_.value())); |
| + Goto(&false_continue); |
| + } |
| } |
| Bind(&false_continue); |
| return a(); |
| @@ -154,14 +200,66 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| return ArraySpeciesCreate(context(), o(), len_); |
| } |
| - Node* MapProcessor(Node* k_value, Node* k) { |
| + Node* MapProcessor(ElementsKind o_kind, 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()); |
| + Label finished(this); |
| + if (o_kind < DICTIONARY_ELEMENTS) { |
| + Node* kind = nullptr; |
| + Node* elements = nullptr; |
| + |
| + // If a() is a JSArray, we can have a fast path. |
| + // mode is SMI_PARAMETERS because k has tagged representation. |
| + ParameterMode mode = SMI_PARAMETERS; |
| + Label fast(this); |
| + Label runtime(this); |
| + Label object_push_pre(this), object_push(this), double_push(this); |
| + BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
| + &fast, &runtime); |
| + |
| + Bind(&fast); |
| + { |
| + kind = EnsureArrayPushable(a(), &runtime); |
| + elements = LoadElements(a()); |
| + GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), |
|
danno
2017/04/03 15:35:27
Consider adding/using existing predicates in code-
mvstanton
2017/04/06 08:57:36
I use a "greater than" metaphor to avoid multiple
|
| + &object_push_pre); |
| + |
| + TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k, |
| + mappedValue); |
| + Goto(&finished); |
| + } |
| + |
| + Bind(&object_push_pre); |
| + { |
| + Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
| + &double_push, &object_push); |
| + } |
| + |
| + Bind(&object_push); |
| + { |
| + TryStoreArrayElement(FAST_ELEMENTS, mode, &runtime, elements, k, |
| + mappedValue); |
| + Goto(&finished); |
| + } |
| + |
| + Bind(&double_push); |
| + { |
| + TryStoreArrayElement(FAST_DOUBLE_ELEMENTS, mode, &runtime, elements, k, |
| + mappedValue); |
| + Goto(&finished); |
| + } |
| + |
| + Bind(&runtime); |
| + } |
| + |
| // iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). |
| CallRuntime(Runtime::kCreateDataProperty, context(), a(), k, mappedValue); |
| + Goto(&finished); |
| + |
| + Bind(&finished); |
| return a(); |
| } |
| @@ -420,7 +518,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| // iii. Let funcResult be Call(callbackfn, T, «kValue, k, O»). |
| // iv. ReturnIfAbrupt(funcResult). |
| - a_.Bind(processor(this, k_value, k())); |
| + a_.Bind(processor(this, DICTIONARY_ELEMENTS, k_value, k())); |
|
danno
2017/04/03 15:35:27
Although I know what you mean here, the elements m
|
| Goto(&done_element); |
| Bind(&done_element); |
| @@ -473,7 +571,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| Node* value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, kind, |
| SMI_PARAMETERS); |
| k_.Bind(index); |
| - a_.Bind(processor(this, value, index)); |
| + a_.Bind(processor(this, kind, value, index)); |
| }; |
| BuildFastLoop(list, SmiConstant(0), len_, body, 1, |
| ParameterMode::SMI_PARAMETERS, IndexAdvanceMode::kPost); |
| @@ -529,7 +627,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
| LoadDoubleWithHoleCheck(elements, offset, &hole_element); |
| value = AllocateHeapNumberWithValue(double_value); |
| } |
| - a_.Bind(processor(this, value, k())); |
| + a_.Bind(processor(this, kind, value, k())); |
| Goto(&one_element_done); |
| Bind(&hole_element); |
| @@ -632,39 +730,13 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
| Bind(&fast); |
| { |
| - // Disallow pushing onto prototypes. It might be the JSArray prototype. |
| - // Disallow pushing onto non-extensible objects. |
| - Comment("Disallow pushing onto prototypes"); |
| - Node* map = LoadMap(receiver); |
| - Node* bit_field2 = LoadMapBitField2(map); |
| - int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | |
| - (1 << Map::kIsExtensible); |
| - Node* test = Word32And(bit_field2, Int32Constant(mask)); |
| - GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), |
| - &runtime); |
| - |
| - // Disallow pushing onto arrays in dictionary named property mode. We need |
| - // to figure out whether the length property is still writable. |
| - Comment("Disallow pushing onto arrays in dictionary named property mode"); |
| - GotoIf(IsDictionaryMap(map), &runtime); |
| - |
| - // Check whether the length property is writable. The length property is the |
| - // only default named property on arrays. It's nonconfigurable, hence is |
| - // guaranteed to stay the first property. |
| - Node* descriptors = LoadMapDescriptors(map); |
| - Node* details = |
| - LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); |
| - GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), |
| - &runtime); |
| - |
| arg_index.Bind(IntPtrConstant(0)); |
| - kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| - |
| + kind = EnsureArrayPushable(receiver, &runtime); |
| GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), |
| &object_push_pre); |
| - Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, context, receiver, |
| - args, arg_index, &smi_transition); |
| + Node* new_length = BuildAppendJSArray(FAST_SMI_ELEMENTS, receiver, args, |
| + arg_index, &smi_transition); |
| args.PopAndReturn(new_length); |
| } |
| @@ -702,16 +774,15 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
| Bind(&object_push); |
| { |
| - Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, context, receiver, |
| - args, arg_index, &default_label); |
| + Node* new_length = BuildAppendJSArray(FAST_ELEMENTS, receiver, args, |
| + arg_index, &default_label); |
| args.PopAndReturn(new_length); |
| } |
| Bind(&double_push); |
| { |
| - Node* new_length = |
| - BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, context, receiver, args, |
| - arg_index, &double_transition); |
| + Node* new_length = BuildAppendJSArray(FAST_DOUBLE_ELEMENTS, receiver, args, |
| + arg_index, &double_transition); |
| args.PopAndReturn(new_length); |
| } |