| 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(),
|
|
|