| Index: src/code-stub-assembler.cc | 
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc | 
| index 2a01133efebfa3a32c666a872b0b90a25db3470a..5d4531f6937674a04926f75000ba95da6ce8385c 100644 | 
| --- a/src/code-stub-assembler.cc | 
| +++ b/src/code-stub-assembler.cc | 
| @@ -1523,8 +1523,53 @@ Node* CodeStubAssembler::StoreFixedDoubleArrayElement( | 
| return StoreNoWriteBarrier(rep, object, offset, value); | 
| } | 
|  | 
| -Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 
| -                                            Node* array, | 
| +Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) { | 
| +  // 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)), bailout); | 
| + | 
| +  // 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), bailout); | 
| + | 
| +  // 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), bailout); | 
| + | 
| +  Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | 
| +  return kind; | 
| +} | 
| + | 
| +void CodeStubAssembler::PossiblyGrowElementsCapacity( | 
| +    ParameterMode mode, ElementsKind kind, Node* array, Node* length, | 
| +    Variable* var_elements, Node* growth, Label* bailout) { | 
| +  Label fits(this, var_elements); | 
| +  Node* capacity = | 
| +      TaggedToParameter(LoadFixedArrayBaseLength(var_elements->value()), mode); | 
| +  // length and growth nodes are already in a ParameterMode appropriate | 
| +  // representation. | 
| +  Node* new_length = IntPtrOrSmiAdd(growth, length, mode); | 
| +  GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | 
| +  Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | 
| +  var_elements->Bind(GrowElementsCapacity(array, var_elements->value(), kind, | 
| +                                          kind, capacity, new_capacity, mode, | 
| +                                          bailout)); | 
| +  Goto(&fits); | 
| +  BIND(&fits); | 
| +} | 
| + | 
| +Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | 
| CodeStubArguments& args, | 
| Variable& arg_index, | 
| Label* bailout) { | 
| @@ -1536,46 +1581,22 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 
| VARIABLE(var_length, OptimalParameterRepresentation(), | 
| TaggedToParameter(LoadJSArrayLength(array), mode)); | 
| VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); | 
| -  Node* capacity = | 
| -      TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); | 
|  | 
| // Resize the capacity of the fixed array if it doesn't fit. | 
| -  Label fits(this, &var_elements); | 
| Node* first = arg_index.value(); | 
| -  Node* growth = IntPtrSub(args.GetLength(), first); | 
| -  Node* new_length = | 
| -      IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode); | 
| -  GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | 
| -  Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | 
| -  var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, | 
| -                                         kind, capacity, new_capacity, mode, | 
| -                                         &pre_bailout)); | 
| -  Goto(&fits); | 
| -  BIND(&fits); | 
| -  Node* elements = var_elements.value(); | 
| +  Node* growth = WordToParameter(IntPtrSub(args.GetLength(), first), mode); | 
| +  PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(), | 
| +                               &var_elements, growth, &pre_bailout); | 
|  | 
| // Push each argument onto the end of the array now that there is enough | 
| // capacity. | 
| CodeStubAssembler::VariableList push_vars({&var_length}, zone()); | 
| +  Node* elements = var_elements.value(); | 
| args.ForEach( | 
| push_vars, | 
| [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { | 
| -        if (IsFastSmiElementsKind(kind)) { | 
| -          GotoIf(TaggedIsNotSmi(arg), &pre_bailout); | 
| -        } else if (IsFastDoubleElementsKind(kind)) { | 
| -          GotoIfNotNumber(arg, &pre_bailout); | 
| -        } | 
| -        if (IsFastDoubleElementsKind(kind)) { | 
| -          Node* double_value = ChangeNumberToFloat64(arg); | 
| -          StoreFixedDoubleArrayElement(elements, var_length.value(), | 
| -                                       Float64SilenceNaN(double_value), mode); | 
| -        } else { | 
| -          WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) | 
| -                                              ? SKIP_WRITE_BARRIER | 
| -                                              : UPDATE_WRITE_BARRIER; | 
| -          StoreFixedArrayElement(elements, var_length.value(), arg, | 
| -                                 barrier_mode, 0, mode); | 
| -        } | 
| +        TryStoreArrayElement(kind, mode, &pre_bailout, elements, | 
| +                             var_length.value(), arg); | 
| Increment(var_length, 1, mode); | 
| }, | 
| first, nullptr); | 
| @@ -1600,6 +1621,49 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 
| return var_tagged_length.value(); | 
| } | 
|  | 
| +void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind, | 
| +                                             ParameterMode mode, Label* bailout, | 
| +                                             Node* elements, Node* index, | 
| +                                             Node* value) { | 
| +  if (IsFastSmiElementsKind(kind)) { | 
| +    GotoIf(TaggedIsNotSmi(value), bailout); | 
| +  } else if (IsFastDoubleElementsKind(kind)) { | 
| +    GotoIfNotNumber(value, bailout); | 
| +  } | 
| +  if (IsFastDoubleElementsKind(kind)) { | 
| +    Node* double_value = ChangeNumberToFloat64(value); | 
| +    StoreFixedDoubleArrayElement(elements, index, | 
| +                                 Float64SilenceNaN(double_value), mode); | 
| +  } else { | 
| +    WriteBarrierMode barrier_mode = | 
| +        IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 
| +    StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); | 
| +  } | 
| +} | 
| + | 
| +void CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | 
| +                                           Node* value, Label* bailout) { | 
| +  Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | 
| +  ParameterMode mode = OptimalParameterMode(); | 
| +  VARIABLE(var_length, OptimalParameterRepresentation(), | 
| +           TaggedToParameter(LoadJSArrayLength(array), mode)); | 
| +  VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); | 
| + | 
| +  // Resize the capacity of the fixed array if it doesn't fit. | 
| +  Node* growth = IntPtrOrSmiConstant(1, mode); | 
| +  PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(), | 
| +                               &var_elements, growth, bailout); | 
| + | 
| +  // Push each argument onto the end of the array now that there is enough | 
| +  // capacity. | 
| +  TryStoreArrayElement(kind, mode, bailout, var_elements.value(), | 
| +                       var_length.value(), value); | 
| +  Increment(var_length, 1, mode); | 
| + | 
| +  Node* length = ParameterToTagged(var_length.value(), mode); | 
| +  StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 
| +} | 
| + | 
| Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { | 
| Node* result = Allocate(HeapNumber::kSize, kNone); | 
| Heap::RootListIndex heap_map_index = | 
| @@ -8485,6 +8549,11 @@ Node* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) { | 
| return Word32Equal(holey_elements, Int32Constant(1)); | 
| } | 
|  | 
| +Node* CodeStubAssembler::IsElementsKindGreaterThan( | 
| +    Node* target_kind, ElementsKind reference_kind) { | 
| +  return Int32GreaterThan(target_kind, Int32Constant(reference_kind)); | 
| +} | 
| + | 
| Node* CodeStubAssembler::IsDebugActive() { | 
| Node* is_debug_active = Load( | 
| MachineType::Uint8(), | 
|  |