@@ -4541,6 +4541,179 @@ void CodeStubAssembler::FillFixedDoubleArrayWithZero(
45414541 backing_store, IntPtrConstant (0 ), byte_length);
45424542}
45434543
4544+ void CodeStubAssembler::JumpIfPointersFromHereAreInteresting (
4545+ TNode<Object> object, Label* interesting) {
4546+ Label finished (this );
4547+ TNode<IntPtrT> object_word = BitcastTaggedToWord (object);
4548+ TNode<IntPtrT> object_page = PageFromAddress (object_word);
4549+ TNode<IntPtrT> page_flags = UncheckedCast<IntPtrT>(Load (
4550+ MachineType::IntPtr (), object_page, IntPtrConstant (Page::kFlagsOffset )));
4551+ Branch (
4552+ WordEqual (WordAnd (page_flags,
4553+ IntPtrConstant (
4554+ MemoryChunk::kPointersFromHereAreInterestingMask )),
4555+ IntPtrConstant (0 )),
4556+ &finished, interesting);
4557+ BIND (&finished);
4558+ }
4559+
4560+ void CodeStubAssembler::MoveElements (ElementsKind kind,
4561+ TNode<FixedArrayBase> elements,
4562+ TNode<IntPtrT> dst_index,
4563+ TNode<IntPtrT> src_index,
4564+ TNode<IntPtrT> length) {
4565+ Label finished (this );
4566+ Label needs_barrier (this );
4567+ const bool needs_barrier_check = IsObjectElementsKind (kind);
4568+
4569+ DCHECK (IsFastElementsKind (kind));
4570+ CSA_ASSERT (this , IsFixedArrayWithKind (elements, kind));
4571+ CSA_ASSERT (this ,
4572+ IntPtrLessThanOrEqual (IntPtrAdd (dst_index, length),
4573+ LoadAndUntagFixedArrayBaseLength (elements)));
4574+ CSA_ASSERT (this ,
4575+ IntPtrLessThanOrEqual (IntPtrAdd (src_index, length),
4576+ LoadAndUntagFixedArrayBaseLength (elements)));
4577+
4578+ // The write barrier can be ignored if {elements} is in new space, or if
4579+ // we have a SMI or double ElementsKind.
4580+ if (needs_barrier_check) {
4581+ JumpIfPointersFromHereAreInteresting (elements, &needs_barrier);
4582+ }
4583+
4584+ const TNode<IntPtrT> source_byte_length =
4585+ IntPtrMul (length, IntPtrConstant (ElementsKindToByteSize (kind)));
4586+ static const int32_t fa_base_data_offset =
4587+ FixedArrayBase::kHeaderSize - kHeapObjectTag ;
4588+ TNode<IntPtrT> elements_intptr = BitcastTaggedToWord (elements);
4589+ TNode<IntPtrT> target_data_ptr =
4590+ IntPtrAdd (elements_intptr,
4591+ ElementOffsetFromIndex (dst_index, kind, INTPTR_PARAMETERS,
4592+ fa_base_data_offset));
4593+ TNode<IntPtrT> source_data_ptr =
4594+ IntPtrAdd (elements_intptr,
4595+ ElementOffsetFromIndex (src_index, kind, INTPTR_PARAMETERS,
4596+ fa_base_data_offset));
4597+ TNode<ExternalReference> memmove =
4598+ ExternalConstant (ExternalReference::libc_memmove_function ());
4599+ CallCFunction3 (MachineType::Pointer (), MachineType::Pointer (),
4600+ MachineType::Pointer (), MachineType::UintPtr (), memmove,
4601+ target_data_ptr, source_data_ptr, source_byte_length);
4602+
4603+ if (needs_barrier_check) {
4604+ Goto (&finished);
4605+
4606+ BIND (&needs_barrier);
4607+ {
4608+ const TNode<IntPtrT> begin = src_index;
4609+ const TNode<IntPtrT> end = IntPtrAdd (begin, length);
4610+
4611+ // If dst_index is less than src_index, then walk forward.
4612+ const TNode<IntPtrT> delta =
4613+ IntPtrMul (IntPtrSub (dst_index, begin),
4614+ IntPtrConstant (ElementsKindToByteSize (kind)));
4615+ auto loop_body = [&](Node* array, Node* offset) {
4616+ Node* const element = Load (MachineType::AnyTagged (), array, offset);
4617+ Node* const delta_offset = IntPtrAdd (offset, delta);
4618+ Store (array, delta_offset, element);
4619+ };
4620+
4621+ Label iterate_forward (this );
4622+ Label iterate_backward (this );
4623+ Branch (IntPtrLessThan (delta, IntPtrConstant (0 )), &iterate_forward,
4624+ &iterate_backward);
4625+ BIND (&iterate_forward);
4626+ {
4627+ // Make a loop for the stores.
4628+ BuildFastFixedArrayForEach (elements, kind, begin, end, loop_body,
4629+ INTPTR_PARAMETERS,
4630+ ForEachDirection::kForward );
4631+ Goto (&finished);
4632+ }
4633+
4634+ BIND (&iterate_backward);
4635+ {
4636+ BuildFastFixedArrayForEach (elements, kind, begin, end, loop_body,
4637+ INTPTR_PARAMETERS,
4638+ ForEachDirection::kReverse );
4639+ Goto (&finished);
4640+ }
4641+ }
4642+ BIND (&finished);
4643+ }
4644+ }
4645+
4646+ void CodeStubAssembler::CopyElements (ElementsKind kind,
4647+ TNode<FixedArrayBase> dst_elements,
4648+ TNode<IntPtrT> dst_index,
4649+ TNode<FixedArrayBase> src_elements,
4650+ TNode<IntPtrT> src_index,
4651+ TNode<IntPtrT> length) {
4652+ Label finished (this );
4653+ Label needs_barrier (this );
4654+ const bool needs_barrier_check = IsObjectElementsKind (kind);
4655+
4656+ DCHECK (IsFastElementsKind (kind));
4657+ CSA_ASSERT (this , IsFixedArrayWithKind (dst_elements, kind));
4658+ CSA_ASSERT (this , IsFixedArrayWithKind (src_elements, kind));
4659+ CSA_ASSERT (this , IntPtrLessThanOrEqual (
4660+ IntPtrAdd (dst_index, length),
4661+ LoadAndUntagFixedArrayBaseLength (dst_elements)));
4662+ CSA_ASSERT (this , IntPtrLessThanOrEqual (
4663+ IntPtrAdd (src_index, length),
4664+ LoadAndUntagFixedArrayBaseLength (src_elements)));
4665+ CSA_ASSERT (this , WordNotEqual (dst_elements, src_elements));
4666+
4667+ // The write barrier can be ignored if {dst_elements} is in new space, or if
4668+ // we have a SMI or double ElementsKind.
4669+ if (needs_barrier_check) {
4670+ JumpIfPointersFromHereAreInteresting (dst_elements, &needs_barrier);
4671+ }
4672+
4673+ TNode<IntPtrT> source_byte_length =
4674+ IntPtrMul (length, IntPtrConstant (ElementsKindToByteSize (kind)));
4675+ static const int32_t fa_base_data_offset =
4676+ FixedArrayBase::kHeaderSize - kHeapObjectTag ;
4677+ TNode<IntPtrT> src_offset_start = ElementOffsetFromIndex (
4678+ src_index, kind, INTPTR_PARAMETERS, fa_base_data_offset);
4679+ TNode<IntPtrT> dst_offset_start = ElementOffsetFromIndex (
4680+ dst_index, kind, INTPTR_PARAMETERS, fa_base_data_offset);
4681+ TNode<IntPtrT> src_elements_intptr = BitcastTaggedToWord (src_elements);
4682+ TNode<IntPtrT> source_data_ptr =
4683+ IntPtrAdd (src_elements_intptr, src_offset_start);
4684+ TNode<IntPtrT> dst_elements_intptr = BitcastTaggedToWord (dst_elements);
4685+ TNode<IntPtrT> dst_data_ptr =
4686+ IntPtrAdd (dst_elements_intptr, dst_offset_start);
4687+ TNode<ExternalReference> memcpy =
4688+ ExternalConstant (ExternalReference::libc_memcpy_function ());
4689+ CallCFunction3 (MachineType::Pointer (), MachineType::Pointer (),
4690+ MachineType::Pointer (), MachineType::UintPtr (), memcpy,
4691+ dst_data_ptr, source_data_ptr, source_byte_length);
4692+
4693+ if (needs_barrier_check) {
4694+ Goto (&finished);
4695+
4696+ BIND (&needs_barrier);
4697+ {
4698+ const TNode<IntPtrT> begin = src_index;
4699+ const TNode<IntPtrT> end = IntPtrAdd (begin, length);
4700+ const TNode<IntPtrT> delta =
4701+ IntPtrMul (IntPtrSub (dst_index, src_index),
4702+ IntPtrConstant (ElementsKindToByteSize (kind)));
4703+ BuildFastFixedArrayForEach (
4704+ src_elements, kind, begin, end,
4705+ [&](Node* array, Node* offset) {
4706+ Node* const element = Load (MachineType::AnyTagged (), array, offset);
4707+ Node* const delta_offset = IntPtrAdd (offset, delta);
4708+ Store (dst_elements, delta_offset, element);
4709+ },
4710+ INTPTR_PARAMETERS, ForEachDirection::kForward );
4711+ Goto (&finished);
4712+ }
4713+ BIND (&finished);
4714+ }
4715+ }
4716+
45444717void CodeStubAssembler::CopyFixedArrayElements (
45454718 ElementsKind from_kind, Node* from_array, ElementsKind to_kind,
45464719 Node* to_array, Node* first_element, Node* element_count, Node* capacity,
0 commit comments