Commit 87448cdd authored by danno's avatar danno Committed by Commit bot

[stubs] Cleanup FixedArray copying

Use common CodeStubAssembler routines for FixedArray-copying builtin.
Also cleanup a few shared pieces of code along the way.

BUG=chromium:608675

Review-Url: https://codereview.chromium.org/2220673002
Cr-Commit-Position: refs/heads/master@{#38478}
parent 54ff89b2
......@@ -57,7 +57,6 @@ void Builtins::Generate_CopyFastSmiOrObjectElements(
CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
Node* object = assembler->Parameter(Descriptor::kObject);
......@@ -65,127 +64,39 @@ void Builtins::Generate_CopyFastSmiOrObjectElements(
// Load the {object}s elements.
Node* source = assembler->LoadObjectField(object, JSObject::kElementsOffset);
// 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));
CodeStubAssembler::ParameterMode mode =
assembler->Is64() ? CodeStubAssembler::INTEGER_PARAMETERS
: CodeStubAssembler::SMI_PARAMETERS;
Node* length = (mode == CodeStubAssembler::INTEGER_PARAMETERS)
? assembler->LoadAndUntagFixedArrayBaseLength(source)
: assembler->LoadFixedArrayBaseLength(source);
// Check if we can allocate in new space.
ElementsKind kind = FAST_ELEMENTS;
int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
Label if_newspace(assembler), if_oldspace(assembler);
assembler->Branch(assembler->UintPtrLessThan(
source_size, assembler->IntPtrConstant(
Page::kMaxRegularHeapObjectSize)),
&if_newspace, &if_oldspace);
assembler->Branch(
assembler->UintPtrLessThan(
length, assembler->IntPtrOrSmiConstant(max_elements, mode)),
&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);
{
// Update the {object}s element to {target}.
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->Return(target);
}
Node* target = assembler->AllocateFixedArray(kind, length, mode);
assembler->CopyFixedArrayElements(kind, source, target, length,
SKIP_WRITE_BARRIER, mode);
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
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);
{
// Update the {object}s element to {target}.
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->Return(target);
}
Node* target = assembler->AllocateFixedArray(
kind, length, mode, compiler::CodeAssembler::kPretenured);
assembler->CopyFixedArrayElements(kind, source, target, length,
UPDATE_WRITE_BARRIER, mode);
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->Return(target);
}
}
......
......@@ -1391,17 +1391,21 @@ Node* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map,
Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind,
Node* capacity_node,
ParameterMode mode) {
Node* total_size = ElementOffsetFromIndex(capacity_node, kind, mode,
FixedArray::kHeaderSize);
ParameterMode mode,
AllocationFlags flags) {
Node* total_size = GetFixedAarrayAllocationSize(capacity_node, kind, mode);
// Allocate both array and elements object, and initialize the JSArray.
Node* array = Allocate(total_size);
Node* array = Allocate(total_size, flags);
Heap* heap = isolate()->heap();
Handle<Map> map(IsFastDoubleElementsKind(kind)
? heap->fixed_double_array_map()
: heap->fixed_array_map());
StoreMapNoWriteBarrier(array, HeapConstant(map));
if (flags & kPretenured) {
StoreObjectField(array, JSObject::kMapOffset, HeapConstant(map));
} else {
StoreMapNoWriteBarrier(array, HeapConstant(map));
}
StoreObjectFieldNoWriteBarrier(
array, FixedArray::kLengthOffset,
mode == INTEGER_PARAMETERS ? SmiTag(capacity_node) : capacity_node);
......@@ -1592,8 +1596,7 @@ Node* CodeStubAssembler::CheckAndGrowElementsCapacity(Node* context,
// If size of the allocation for the new capacity doesn't fit in a page
// that we can bump-pointer allocate from, fall back to the runtime,
int max_size = ((Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
ElementsKindToShiftSize(kind));
int max_size = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
GotoIf(UintPtrGreaterThanOrEqual(new_capacity,
IntPtrOrSmiConstant(max_size, mode)),
fail);
......
......@@ -287,7 +287,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* AllocateFixedArray(ElementsKind kind,
compiler::Node* capacity,
ParameterMode mode = INTEGER_PARAMETERS);
ParameterMode mode = INTEGER_PARAMETERS,
AllocationFlags flags = kNone);
void FillFixedArrayWithHole(ElementsKind kind, compiler::Node* array,
compiler::Node* from_index,
......@@ -551,6 +552,13 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* feedback_vector, compiler::Node* slot,
compiler::Node* value);
compiler::Node* GetFixedAarrayAllocationSize(compiler::Node* element_count,
ElementsKind kind,
ParameterMode mode) {
return ElementOffsetFromIndex(element_count, kind, mode,
FixedArray::kHeaderSize);
}
private:
compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
ElementsKind kind, ParameterMode mode,
......
......@@ -15693,6 +15693,10 @@ Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
: Nothing<bool>();
}
int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
return ((Page::kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
ElementsKindToShiftSize(kind));
}
void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
Object* temp = get(i);
......
......@@ -2664,6 +2664,8 @@ class FixedArrayBase: public HeapObject {
DECLARE_CAST(FixedArrayBase)
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
// Layout description.
// Length is smi tagged when it is stored.
static const int kLengthOffset = HeapObject::kHeaderSize;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment