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( ...@@ -57,7 +57,6 @@ void Builtins::Generate_CopyFastSmiOrObjectElements(
CodeStubAssembler* assembler) { CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
typedef CopyFastSmiOrObjectElementsDescriptor Descriptor; typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler->Parameter(Descriptor::kObject);
...@@ -65,127 +64,39 @@ void Builtins::Generate_CopyFastSmiOrObjectElements( ...@@ -65,127 +64,39 @@ void Builtins::Generate_CopyFastSmiOrObjectElements(
// Load the {object}s elements. // Load the {object}s elements.
Node* source = assembler->LoadObjectField(object, JSObject::kElementsOffset); Node* source = assembler->LoadObjectField(object, JSObject::kElementsOffset);
// Load the {source} length. CodeStubAssembler::ParameterMode mode =
Node* source_length_tagged = assembler->Is64() ? CodeStubAssembler::INTEGER_PARAMETERS
assembler->LoadObjectField(source, FixedArray::kLengthOffset); : CodeStubAssembler::SMI_PARAMETERS;
Node* source_length = assembler->SmiToWord(source_length_tagged); Node* length = (mode == CodeStubAssembler::INTEGER_PARAMETERS)
? assembler->LoadAndUntagFixedArrayBaseLength(source)
// Compute the size of {source} in bytes. : assembler->LoadFixedArrayBaseLength(source);
Node* source_size = assembler->IntPtrAdd(
assembler->WordShl(source_length,
assembler->IntPtrConstant(kPointerSizeLog2)),
assembler->IntPtrConstant(FixedArray::kHeaderSize));
// Check if we can allocate in new space. // 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); Label if_newspace(assembler), if_oldspace(assembler);
assembler->Branch(assembler->UintPtrLessThan( assembler->Branch(
source_size, assembler->IntPtrConstant( assembler->UintPtrLessThan(
Page::kMaxRegularHeapObjectSize)), length, assembler->IntPtrOrSmiConstant(max_elements, mode)),
&if_newspace, &if_oldspace); &if_newspace, &if_oldspace);
assembler->Bind(&if_newspace); assembler->Bind(&if_newspace);
{ {
// Allocate the targeting FixedArray in new space. Node* target = assembler->AllocateFixedArray(kind, length, mode);
Node* target = assembler->Allocate(source_size); assembler->CopyFixedArrayElements(kind, source, target, length,
assembler->StoreMapNoWriteBarrier( SKIP_WRITE_BARRIER, mode);
target, assembler->LoadRoot(Heap::kFixedArrayMapRootIndex)); assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->StoreObjectFieldNoWriteBarrier(target, FixedArray::kLengthOffset, assembler->Return(target);
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);
}
} }
assembler->Bind(&if_oldspace); assembler->Bind(&if_oldspace);
{ {
// Allocate the targeting FixedArray in old space Node* target = assembler->AllocateFixedArray(
// (maybe even in large object space). kind, length, mode, compiler::CodeAssembler::kPretenured);
Node* flags = assembler->SmiConstant( assembler->CopyFixedArrayElements(kind, source, target, length,
Smi::FromInt(AllocateDoubleAlignFlag::encode(false) | UPDATE_WRITE_BARRIER, mode);
AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE))); assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
Node* source_size_tagged = assembler->SmiFromWord(source_size); assembler->Return(target);
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);
}
} }
} }
......
...@@ -1391,17 +1391,21 @@ Node* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map, ...@@ -1391,17 +1391,21 @@ Node* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map,
Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind, Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind,
Node* capacity_node, Node* capacity_node,
ParameterMode mode) { ParameterMode mode,
Node* total_size = ElementOffsetFromIndex(capacity_node, kind, mode, AllocationFlags flags) {
FixedArray::kHeaderSize); Node* total_size = GetFixedAarrayAllocationSize(capacity_node, kind, mode);
// Allocate both array and elements object, and initialize the JSArray. // 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(); Heap* heap = isolate()->heap();
Handle<Map> map(IsFastDoubleElementsKind(kind) Handle<Map> map(IsFastDoubleElementsKind(kind)
? heap->fixed_double_array_map() ? heap->fixed_double_array_map()
: heap->fixed_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( StoreObjectFieldNoWriteBarrier(
array, FixedArray::kLengthOffset, array, FixedArray::kLengthOffset,
mode == INTEGER_PARAMETERS ? SmiTag(capacity_node) : capacity_node); mode == INTEGER_PARAMETERS ? SmiTag(capacity_node) : capacity_node);
...@@ -1592,8 +1596,7 @@ Node* CodeStubAssembler::CheckAndGrowElementsCapacity(Node* context, ...@@ -1592,8 +1596,7 @@ Node* CodeStubAssembler::CheckAndGrowElementsCapacity(Node* context,
// If size of the allocation for the new capacity doesn't fit in a page // 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, // that we can bump-pointer allocate from, fall back to the runtime,
int max_size = ((Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >> int max_size = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
ElementsKindToShiftSize(kind));
GotoIf(UintPtrGreaterThanOrEqual(new_capacity, GotoIf(UintPtrGreaterThanOrEqual(new_capacity,
IntPtrOrSmiConstant(max_size, mode)), IntPtrOrSmiConstant(max_size, mode)),
fail); fail);
......
...@@ -287,7 +287,8 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -287,7 +287,8 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* AllocateFixedArray(ElementsKind kind, compiler::Node* AllocateFixedArray(ElementsKind kind,
compiler::Node* capacity, compiler::Node* capacity,
ParameterMode mode = INTEGER_PARAMETERS); ParameterMode mode = INTEGER_PARAMETERS,
AllocationFlags flags = kNone);
void FillFixedArrayWithHole(ElementsKind kind, compiler::Node* array, void FillFixedArrayWithHole(ElementsKind kind, compiler::Node* array,
compiler::Node* from_index, compiler::Node* from_index,
...@@ -551,6 +552,13 @@ class CodeStubAssembler : public compiler::CodeAssembler { ...@@ -551,6 +552,13 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* feedback_vector, compiler::Node* slot, compiler::Node* feedback_vector, compiler::Node* slot,
compiler::Node* value); compiler::Node* value);
compiler::Node* GetFixedAarrayAllocationSize(compiler::Node* element_count,
ElementsKind kind,
ParameterMode mode) {
return ElementOffsetFromIndex(element_count, kind, mode,
FixedArray::kHeaderSize);
}
private: private:
compiler::Node* ElementOffsetFromIndex(compiler::Node* index, compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
ElementsKind kind, ParameterMode mode, ElementsKind kind, ParameterMode mode,
......
...@@ -15693,6 +15693,10 @@ Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, ...@@ -15693,6 +15693,10 @@ Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
: Nothing<bool>(); : Nothing<bool>();
} }
int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
return ((Page::kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
ElementsKindToShiftSize(kind));
}
void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
Object* temp = get(i); Object* temp = get(i);
......
...@@ -2664,6 +2664,8 @@ class FixedArrayBase: public HeapObject { ...@@ -2664,6 +2664,8 @@ class FixedArrayBase: public HeapObject {
DECLARE_CAST(FixedArrayBase) DECLARE_CAST(FixedArrayBase)
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
// Layout description. // Layout description.
// Length is smi tagged when it is stored. // Length is smi tagged when it is stored.
static const int kLengthOffset = HeapObject::kHeaderSize; 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