Index: src/builtins/builtins-internal.cc |
diff --git a/src/builtins/builtins-internal.cc b/src/builtins/builtins-internal.cc |
index 82ff1534ebaec7e22a7a86eb369d9777781d94e2..03728764c6ace49613316280896869472f48fbe1 100644 |
--- a/src/builtins/builtins-internal.cc |
+++ b/src/builtins/builtins-internal.cc |
@@ -4,7 +4,7 @@ |
#include "src/builtins/builtins.h" |
#include "src/builtins/builtins-utils.h" |
- |
+#include "src/interface-descriptors.h" |
#include "src/macro-assembler.h" |
namespace v8 { |
@@ -50,5 +50,132 @@ void Builtins::Generate_StackCheck(MacroAssembler* masm) { |
masm->TailCallRuntime(Runtime::kStackGuard); |
} |
+// ----------------------------------------------------------------------------- |
+// FixedArray helpers. |
+ |
+void Builtins::Generate_CopyFixedArray(CodeStubAssembler* assembler) { |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Variable Variable; |
+ typedef CopyFixedArrayDescriptor Descriptor; |
+ |
+ Node* source = assembler->Parameter(Descriptor::kSource); |
+ |
+ // Load the {source} length. |
+ Node* source_length_tagged = |
+ assembler->LoadObjectField(source, FixedArray::kLengthOffset); |
+ Node* source_length = assembler->SmiToWord(source_length_tagged); |
+ |
+ // Compute the size of {source} in bytes. |
+ Node* source_size = assembler->IntPtrAdd( |
+ assembler->WordShl(source_length, |
+ assembler->IntPtrConstant(kPointerSizeLog2)), |
+ assembler->IntPtrConstant(FixedArray::kHeaderSize)); |
+ |
+ // Check if we can allocate in new space. |
+ Label if_newspace(assembler), if_oldspace(assembler); |
+ assembler->Branch(assembler->UintPtrLessThan( |
+ source_size, assembler->IntPtrConstant( |
+ Page::kMaxRegularHeapObjectSize)), |
+ &if_newspace, &if_oldspace); |
+ |
+ assembler->Bind(&if_newspace); |
+ { |
+ // Allocate the targeting FixedArray in new space. |
+ Node* target = assembler->Allocate(source_size); |
+ assembler->StoreMapNoWriteBarrier( |
+ target, assembler->LoadRoot(Heap::kFixedArrayMapRootIndex)); |
+ assembler->StoreObjectFieldNoWriteBarrier(target, FixedArray::kLengthOffset, |
+ source_length_tagged); |
+ |
+ // Compute the limit. |
+ Node* limit = assembler->IntPtrSub( |
+ source_size, assembler->IntPtrConstant(kHeapObjectTag)); |
+ |
+ // Copy the {source} to the {target}. |
+ Variable var_offset(assembler, MachineType::PointerRepresentation()); |
+ Label loop(assembler, &var_offset), done_loop(assembler); |
+ var_offset.Bind( |
+ assembler->IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ assembler->Goto(&loop); |
+ assembler->Bind(&loop); |
+ { |
+ // Determine the current {offset}. |
+ Node* offset = var_offset.value(); |
+ |
+ // Check if we are done. |
+ assembler->GotoUnless(assembler->UintPtrLessThan(offset, limit), |
+ &done_loop); |
+ |
+ // Load the value from {source}. |
+ Node* value = assembler->Load(MachineType::AnyTagged(), source, offset); |
+ |
+ // Store the {value} to the {target} without a write barrier, since we |
+ // know that the {target} is allocated in new space. |
+ assembler->StoreNoWriteBarrier(MachineRepresentation::kTagged, target, |
+ offset, value); |
+ |
+ // Increment {offset} and continue. |
+ var_offset.Bind(assembler->IntPtrAdd( |
+ offset, assembler->IntPtrConstant(kPointerSize))); |
+ assembler->Goto(&loop); |
+ } |
+ |
+ assembler->Bind(&done_loop); |
+ assembler->Return(target); |
+ } |
+ |
+ assembler->Bind(&if_oldspace); |
+ { |
+ // Allocate the targeting FixedArray in old space |
+ // (maybe even in large object space). |
+ Node* flags = assembler->SmiConstant( |
+ Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | |
+ AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE))); |
+ Node* source_size_tagged = assembler->SmiFromWord(source_size); |
+ Node* target = assembler->CallRuntime(Runtime::kAllocateInTargetSpace, |
+ assembler->NoContextConstant(), |
+ source_size_tagged, flags); |
+ assembler->StoreMapNoWriteBarrier( |
+ target, assembler->LoadRoot(Heap::kFixedArrayMapRootIndex)); |
+ assembler->StoreObjectFieldNoWriteBarrier(target, FixedArray::kLengthOffset, |
+ source_length_tagged); |
+ |
+ // Compute the limit. |
+ Node* limit = assembler->IntPtrSub( |
+ source_size, assembler->IntPtrConstant(kHeapObjectTag)); |
+ |
+ // Copy the {source} to the {target}. |
+ Variable var_offset(assembler, MachineType::PointerRepresentation()); |
+ Label loop(assembler, &var_offset), done_loop(assembler); |
+ var_offset.Bind( |
+ assembler->IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ assembler->Goto(&loop); |
+ assembler->Bind(&loop); |
+ { |
+ // Determine the current {offset}. |
+ Node* offset = var_offset.value(); |
+ |
+ // Check if we are done. |
+ assembler->GotoUnless(assembler->UintPtrLessThan(offset, limit), |
+ &done_loop); |
+ |
+ // Load the value from {source}. |
+ Node* value = assembler->Load(MachineType::AnyTagged(), source, offset); |
+ |
+ // Store the {value} to the {target} with a proper write barrier. |
+ assembler->Store(MachineRepresentation::kTagged, target, offset, value); |
+ |
+ // Increment {offset} and continue. |
+ var_offset.Bind(assembler->IntPtrAdd( |
+ offset, assembler->IntPtrConstant(kPointerSize))); |
+ assembler->Goto(&loop); |
+ } |
+ |
+ assembler->Bind(&done_loop); |
+ assembler->Return(target); |
+ } |
+} |
+ |
} // namespace internal |
} // namespace v8 |