Index: src/builtins/builtins-array-gen.cc |
diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc |
index aad31db8a17d8bbb65347533377e61299e455279..21269fdc65bae7854fa2604358c63ee423207902 100644 |
--- a/src/builtins/builtins-array-gen.cc |
+++ b/src/builtins/builtins-array-gen.cc |
@@ -137,13 +137,58 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
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); |
+ Label after_work(this, &to_); |
+ Node* kind = nullptr; |
- // 2. Increase to by 1. |
- to_.Bind(NumberInc(to_.value())); |
- Goto(&false_continue); |
+ // 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); |
+ BranchIfFastJSArray(a(), context(), FastJSArrayAccessMode::ANY_ACCESS, |
+ &fast, &runtime); |
+ |
+ BIND(&fast); |
+ { |
+ kind = EnsureArrayPushable(a(), &runtime); |
+ GotoIf(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS), |
+ &object_push_pre); |
+ |
+ BuildAppendJSArray(FAST_SMI_ELEMENTS, a(), k_value, &runtime); |
+ Goto(&after_work); |
+ } |
+ |
+ BIND(&object_push_pre); |
+ { |
+ Branch(IsElementsKindGreaterThan(kind, 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); |
+ } |
+ |
+ BIND(&after_work); |
+ { |
+ // 2. Increase to by 1. |
+ to_.Bind(NumberInc(to_.value())); |
+ Goto(&false_continue); |
+ } |
} |
BIND(&false_continue); |
return a(); |
@@ -160,8 +205,58 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
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); |
+ Label finished(this); |
+ 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(IsElementsKindGreaterThan(kind, FAST_HOLEY_SMI_ELEMENTS), |
+ &object_push_pre); |
+ TryStoreArrayElement(FAST_SMI_ELEMENTS, mode, &runtime, elements, k, |
+ mappedValue); |
+ Goto(&finished); |
+ } |
+ |
+ BIND(&object_push_pre); |
+ { |
+ Branch(IsElementsKindGreaterThan(kind, 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(); |
} |
@@ -575,7 +670,7 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
Node* o_map = LoadMap(o()); |
Node* bit_field2 = LoadMapBitField2(o_map); |
Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
- Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
+ Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), |
&maybe_double_elements, &fast_elements); |
ParameterMode mode = OptimalParameterMode(); |
@@ -591,8 +686,8 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler { |
} |
BIND(&maybe_double_elements); |
- Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_DOUBLE_ELEMENTS)), |
- slow, &fast_double_elements); |
+ Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_DOUBLE_ELEMENTS), slow, |
+ &fast_double_elements); |
BIND(&fast_double_elements); |
{ |
@@ -644,39 +739,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); |
- |
- GotoIf(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_SMI_ELEMENTS)), |
+ kind = EnsureArrayPushable(receiver, &runtime); |
+ GotoIf(IsElementsKindGreaterThan(kind, 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); |
} |
@@ -708,22 +777,21 @@ TF_BUILTIN(FastArrayPush, CodeStubAssembler) { |
BIND(&object_push_pre); |
{ |
- Branch(Int32GreaterThan(kind, Int32Constant(FAST_HOLEY_ELEMENTS)), |
- &double_push, &object_push); |
+ Branch(IsElementsKindGreaterThan(kind, FAST_HOLEY_ELEMENTS), &double_push, |
+ &object_push); |
} |
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); |
} |