[vm/compiler] Various cleanups involving CreateArrayInstr.

* Rename values and methods like kElementTypePos or element_type() to
  corresponding names like kTypeArgumentsPos or type_arguments() (since
  the input to CreateArrayInstr is the type arguments vector for the
  array, not just the type of the element.)

* Create a AllocateArrayABI struct for the input and output registers of
  the AllocateArray stub and use those where applicable.

* Explicitly list what registers are clobbered in the AllocateArray
  stubs in their documentation comment.

* Avoid clobbering the type arguments input register in the arm64
  version of AllocateArrayInstr, so all input registers are preserved
  across all architectures.

TEST=Refactoring, so existing tests.

Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-debug-x64c-try,vm-kernel-linux-debug-simarm64c-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-nnbd-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try
Change-Id: I3a7c2b6afdd307c26f8d4f97a4c8bd7684e7b242
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/201183
Reviewed-by: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Clement Skau <cskau@google.com>
This commit is contained in:
Tess Strickland 2021-05-26 09:39:22 +00:00 committed by commit-bot@chromium.org
parent 10cabb4d08
commit 619f46cd19
15 changed files with 313 additions and 243 deletions

View file

@ -2961,7 +2961,7 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
break;
}
} else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
return create_array->element_type()->definition();
return create_array->type_arguments()->definition();
} else if (LoadFieldInstr* load_array = array->AsLoadField()) {
const Slot& slot = load_array->slot();
switch (slot.kind()) {

View file

@ -6405,20 +6405,20 @@ class TemplateArrayAllocation : public ArrayAllocationInstr {
class CreateArrayInstr : public TemplateArrayAllocation<2> {
public:
CreateArrayInstr(const InstructionSource& source,
Value* element_type,
Value* type_arguments,
Value* num_elements,
intptr_t deopt_id)
: TemplateArrayAllocation(source, deopt_id) {
SetInputAt(kElementTypePos, element_type);
SetInputAt(kTypeArgumentsPos, type_arguments);
SetInputAt(kLengthPos, num_elements);
}
enum { kElementTypePos = 0, kLengthPos = 1 };
enum { kTypeArgumentsPos = 0, kLengthPos = 1 };
DECLARE_INSTRUCTION(CreateArray)
virtual CompileType ComputeType() const;
Value* element_type() const { return inputs_[kElementTypePos]; }
Value* type_arguments() const { return inputs_[kTypeArgumentsPos]; }
virtual Value* num_elements() const { return inputs_[kLengthPos]; }
virtual bool HasUnknownSideEffects() const { return false; }

View file

@ -3114,9 +3114,11 @@ LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(kElementTypePos, Location::RegisterLocation(R1));
locs->set_in(kLengthPos, Location::RegisterLocation(R2));
locs->set_out(0, Location::RegisterLocation(R0));
locs->set_in(kTypeArgumentsPos,
Location::RegisterLocation(AllocateArrayABI::kTypeArgumentsReg));
locs->set_in(kLengthPos,
Location::RegisterLocation(AllocateArrayABI::kLengthReg));
locs->set_out(0, Location::RegisterLocation(AllocateArrayABI::kResultReg));
return locs;
}
@ -3126,31 +3128,31 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
compiler::Label* slow_path,
compiler::Label* done) {
const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
const Register kLengthReg = R2;
const Register kElemTypeReg = R1;
const intptr_t instance_size = Array::InstanceSize(num_elements);
__ TryAllocateArray(kArrayCid, instance_size, slow_path,
R0, // instance
R3, // end address
AllocateArrayABI::kResultReg, // instance
R3, // end address
R8, R6);
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// Store the type argument field.
__ StoreIntoObjectNoBarrier(
R0,
compiler::FieldAddress(R0,
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
compiler::target::Array::type_arguments_offset()),
kElemTypeReg);
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
R0, compiler::FieldAddress(R0, compiler::target::Array::length_offset()),
kLengthReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
compiler::target::Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// R6: iterator which initially points to the start of the variable
// data area to be initialized.
@ -3166,12 +3168,15 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
__ LoadImmediate(R9, 0x1);
#endif // DEBUG
}
__ AddImmediate(R6, R0, sizeof(UntaggedArray) - kHeapObjectTag);
__ AddImmediate(R6, AllocateArrayABI::kResultReg,
sizeof(UntaggedArray) - kHeapObjectTag);
if (array_size < (kInlineArraySize * compiler::target::kWordSize)) {
__ InitializeFieldsNoBarrierUnrolled(
R0, R6, 0, num_elements * compiler::target::kWordSize, R8, R9);
AllocateArrayABI::kResultReg, R6, 0,
num_elements * compiler::target::kWordSize, R8, R9);
} else {
__ InitializeFieldsNoBarrier(R0, R6, R3, R8, R9);
__ InitializeFieldsNoBarrier(AllocateArrayABI::kResultReg, R6, R3, R8,
R9);
}
}
__ b(done);
@ -3183,16 +3188,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Class& list_class =
Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
element_type()->definition());
type_arguments()->definition());
}
const Register kLengthReg = R2;
const Register kElemTypeReg = R1;
const Register kResultReg = R0;
ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg);
ASSERT(locs()->in(kLengthPos).reg() == kLengthReg);
compiler::Label slow_path, done;
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
@ -3214,7 +3212,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
env());
__ Bind(&done);
ASSERT(locs()->out(0).reg() == kResultReg);
}
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,

View file

@ -2674,9 +2674,11 @@ LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(kElementTypePos, Location::RegisterLocation(R1));
locs->set_in(kLengthPos, Location::RegisterLocation(R2));
locs->set_out(0, Location::RegisterLocation(R0));
locs->set_in(kTypeArgumentsPos,
Location::RegisterLocation(AllocateArrayABI::kTypeArgumentsReg));
locs->set_in(kLengthPos,
Location::RegisterLocation(AllocateArrayABI::kLengthReg));
locs->set_out(0, Location::RegisterLocation(AllocateArrayABI::kResultReg));
return locs;
}
@ -2686,29 +2688,32 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
compiler::Label* slow_path,
compiler::Label* done) {
const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
const Register kLengthReg = R2;
const Register kElemTypeReg = R1;
const intptr_t instance_size = Array::InstanceSize(num_elements);
__ TryAllocateArray(kArrayCid, instance_size, slow_path,
R0, // instance
R3, // end address
AllocateArrayABI::kResultReg, // instance
R3, // end address
R6, R8);
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// Store the type argument field.
__ StoreIntoObjectNoBarrier(
R0, compiler::FieldAddress(R0, Array::type_arguments_offset()),
kElemTypeReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
R0, compiler::FieldAddress(R0, Array::length_offset()), kLengthReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::length_offset()),
AllocateArrayABI::kLengthReg);
// TODO(zra): Use stp once added.
// Initialize all array elements to raw_null.
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// R8: iterator which initially points to the start of the variable
// data area to be initialized.
@ -2716,7 +2721,8 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
if (num_elements > 0) {
const intptr_t array_size = instance_size - sizeof(UntaggedArray);
__ LoadObject(R6, Object::null_object());
__ AddImmediate(R8, R0, sizeof(UntaggedArray) - kHeapObjectTag);
__ AddImmediate(R8, AllocateArrayABI::kResultReg,
sizeof(UntaggedArray) - kHeapObjectTag);
if (array_size < (kInlineArraySize * kWordSize)) {
intptr_t current_offset = 0;
while (current_offset < array_size) {
@ -2743,16 +2749,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Class& list_class =
Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
element_type()->definition());
type_arguments()->definition());
}
const Register kLengthReg = R2;
const Register kElemTypeReg = R1;
const Register kResultReg = R0;
ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg);
ASSERT(locs()->in(kLengthPos).reg() == kLengthReg);
compiler::Label slow_path, done;
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
@ -2773,7 +2772,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->GenerateStubCall(source(), allocate_array_stub,
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
env());
ASSERT(locs()->out(0).reg() == kResultReg);
__ Bind(&done);
}

View file

@ -2393,9 +2393,11 @@ LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(ECX));
locs->set_in(1, Location::RegisterLocation(EDX));
locs->set_out(0, Location::RegisterLocation(EAX));
locs->set_in(kTypeArgumentsPos,
Location::RegisterLocation(AllocateArrayABI::kTypeArgumentsReg));
locs->set_in(kLengthPos,
Location::RegisterLocation(AllocateArrayABI::kLengthReg));
locs->set_out(0, Location::RegisterLocation(AllocateArrayABI::kResultReg));
return locs;
}
@ -2405,29 +2407,32 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
compiler::Label* slow_path,
compiler::Label* done) {
const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
const Register kLengthReg = EDX;
const Register kElemTypeReg = ECX;
const intptr_t instance_size = Array::InstanceSize(num_elements);
// Instance in EAX.
// Instance in AllocateArrayABI::kResultReg.
// Object end address in EBX.
__ TryAllocateArray(kArrayCid, instance_size, slow_path,
compiler::Assembler::kFarJump,
EAX, // instance
EBX, // end address
EDI); // temp
AllocateArrayABI::kResultReg, // instance
EBX, // end address
EDI); // temp
// Store the type argument field.
__ StoreIntoObjectNoBarrier(
EAX, compiler::FieldAddress(EAX, Array::type_arguments_offset()),
kElemTypeReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
EAX, compiler::FieldAddress(EAX, Array::length_offset()), kLengthReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// EAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// EBX: new object end address.
// EDI: iterator which initially points to the start of the variable
// data area to be initialized.
@ -2435,19 +2440,22 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
const intptr_t array_size = instance_size - sizeof(UntaggedArray);
const compiler::Immediate& raw_null =
compiler::Immediate(static_cast<intptr_t>(Object::null()));
__ leal(EDI, compiler::FieldAddress(EAX, sizeof(UntaggedArray)));
__ leal(EDI, compiler::FieldAddress(AllocateArrayABI::kResultReg,
sizeof(UntaggedArray)));
if (array_size < (kInlineArraySize * kWordSize)) {
intptr_t current_offset = 0;
__ movl(EBX, raw_null);
while (current_offset < array_size) {
__ StoreIntoObjectNoBarrier(EAX, compiler::Address(EDI, current_offset),
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
compiler::Address(EDI, current_offset),
EBX);
current_offset += kWordSize;
}
} else {
compiler::Label init_loop;
__ Bind(&init_loop);
__ StoreIntoObjectNoBarrier(EAX, compiler::Address(EDI, 0),
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
compiler::Address(EDI, 0),
Object::null_object());
__ addl(EDI, compiler::Immediate(kWordSize));
__ cmpl(EDI, EBX);
@ -2458,13 +2466,6 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
}
void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// Allocate the array. EDX = length, ECX = element type.
const Register kLengthReg = EDX;
const Register kElemTypeReg = ECX;
const Register kResultReg = EAX;
ASSERT(locs()->in(0).reg() == kElemTypeReg);
ASSERT(locs()->in(1).reg() == kLengthReg);
compiler::Label slow_path, done;
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
if (compiler->is_optimizing() && num_elements()->BindsToConstant() &&
@ -2485,7 +2486,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
env());
__ Bind(&done);
ASSERT(locs()->out(0).reg() == kResultReg);
}
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,

View file

@ -2769,9 +2769,11 @@ LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone,
const intptr_t kNumTemps = 0;
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
locs->set_in(0, Location::RegisterLocation(RBX));
locs->set_in(1, Location::RegisterLocation(R10));
locs->set_out(0, Location::RegisterLocation(RAX));
locs->set_in(kTypeArgumentsPos,
Location::RegisterLocation(AllocateArrayABI::kTypeArgumentsReg));
locs->set_in(kLengthPos,
Location::RegisterLocation(AllocateArrayABI::kLengthReg));
locs->set_out(0, Location::RegisterLocation(AllocateArrayABI::kResultReg));
return locs;
}
@ -2781,46 +2783,52 @@ static void InlineArrayAllocation(FlowGraphCompiler* compiler,
compiler::Label* slow_path,
compiler::Label* done) {
const int kInlineArraySize = 12; // Same as kInlineInstanceSize.
const Register kLengthReg = R10;
const Register kElemTypeReg = RBX;
const intptr_t instance_size = Array::InstanceSize(num_elements);
__ TryAllocateArray(kArrayCid, instance_size, slow_path,
compiler::Assembler::kFarJump,
RAX, // instance
RCX, // end address
R13); // temp
AllocateArrayABI::kResultReg, // instance
RCX, // end address
R13); // temp
// RAX: new object start as a tagged pointer.
// Store the type argument field.
__ StoreIntoObjectNoBarrier(
RAX, compiler::FieldAddress(RAX, Array::type_arguments_offset()),
kElemTypeReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
RAX, compiler::FieldAddress(RAX, Array::length_offset()), kLengthReg);
AllocateArrayABI::kResultReg,
compiler::FieldAddress(AllocateArrayABI::kResultReg,
Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// RAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// RCX: new object end address.
// RDI: iterator which initially points to the start of the variable
// data area to be initialized.
if (num_elements > 0) {
const intptr_t array_size = instance_size - sizeof(UntaggedArray);
__ LoadObject(R12, Object::null_object());
__ leaq(RDI, compiler::FieldAddress(RAX, sizeof(UntaggedArray)));
__ leaq(RDI, compiler::FieldAddress(AllocateArrayABI::kResultReg,
sizeof(UntaggedArray)));
if (array_size < (kInlineArraySize * kWordSize)) {
intptr_t current_offset = 0;
while (current_offset < array_size) {
__ StoreIntoObjectNoBarrier(RAX, compiler::Address(RDI, current_offset),
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
compiler::Address(RDI, current_offset),
R12);
current_offset += kWordSize;
}
} else {
compiler::Label init_loop;
__ Bind(&init_loop);
__ StoreIntoObjectNoBarrier(RAX, compiler::Address(RDI, 0), R12);
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
compiler::Address(RDI, 0), R12);
__ addq(RDI, compiler::Immediate(kWordSize));
__ cmpq(RDI, RCX);
__ j(BELOW, &init_loop, compiler::Assembler::kNearJump);
@ -2835,16 +2843,9 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Class& list_class =
Class::Handle(compiler->isolate_group()->class_table()->At(kArrayCid));
RegisterTypeArgumentsUse(compiler->function(), type_usage_info, list_class,
element_type()->definition());
type_arguments()->definition());
}
// Allocate the array. R10 = length, RBX = element type.
const Register kLengthReg = R10;
const Register kElemTypeReg = RBX;
const Register kResultReg = RAX;
ASSERT(locs()->in(0).reg() == kElemTypeReg);
ASSERT(locs()->in(1).reg() == kLengthReg);
compiler::Label slow_path, done;
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
if (compiler->is_optimizing() && !FLAG_precompiled_mode &&
@ -2866,7 +2867,6 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
UntaggedPcDescriptors::kOther, locs(), deopt_id(),
env());
__ Bind(&done);
ASSERT(locs()->out(0).reg() == kResultReg);
}
LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone,

View file

@ -2111,7 +2111,7 @@ class LoadOptimizer : public ValueObject {
if (auto load = use->instruction()->AsLoadField()) {
if (load->slot().IsTypeArguments()) {
place_id = GetPlaceId(load);
forward_def = alloc->element_type()->definition();
forward_def = alloc->type_arguments()->definition();
}
} else if (use->instruction()->IsLoadIndexed() ||
use->instruction()->IsStoreIndexed()) {

View file

@ -1000,11 +1000,14 @@ void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
}
// Called for inline allocation of arrays.
// Input parameters:
// Input registers (preserved):
// LR: return address.
// R1: array element type (either NULL or an instantiated type).
// R2: array length as Smi (must be preserved).
// The newly allocated object is returned in R0.
// AllocateArrayABI::kLengthReg: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// Output registers:
// AllocateArrayABI::kResultReg: newly allocated array.
// Clobbered:
// R3, R4, R8, R9
void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
Label slow_case;
@ -1012,7 +1015,7 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// and is computed as:
// RoundedAllocationSize(
// (array_length * kwordSize) + target::Array::header_size()).
__ mov(R3, Operand(R2)); // Array length.
__ mov(R3, Operand(AllocateArrayABI::kLengthReg)); // Array length.
// Check that length is a Smi.
__ tst(R3, Operand(kSmiTagMask));
__ b(&slow_case, NE);
@ -1037,12 +1040,14 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// R9: Allocation size.
// Potential new object start.
__ ldr(R0, Address(THR, target::Thread::top_offset()));
__ adds(R3, R0, Operand(R9)); // Potential next object start.
__ ldr(AllocateArrayABI::kResultReg,
Address(THR, target::Thread::top_offset()));
__ adds(R3, AllocateArrayABI::kResultReg,
Operand(R9)); // Potential next object start.
__ b(&slow_case, CS); // Branch if unsigned overflow.
// Check if the allocation fits into the remaining space.
// R0: potential new object start.
// AllocateArrayABI::kResultReg: potential new object start.
// R3: potential next object start.
// R9: allocation size.
__ ldr(TMP, Address(THR, target::Thread::end_offset()));
@ -1052,10 +1057,11 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
__ str(R3, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
__ add(AllocateArrayABI::kResultReg, AllocateArrayABI::kResultReg,
Operand(kHeapObjectTag));
// Initialize the tags.
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// R9: allocation size.
{
@ -1072,22 +1078,27 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
__ LoadImmediate(TMP, tags);
__ orr(R8, R8, Operand(TMP));
__ str(R8,
FieldAddress(R0, target::Array::tags_offset())); // Store tags.
__ str(R8, FieldAddress(AllocateArrayABI::kResultReg,
target::Array::tags_offset())); // Store tags.
}
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R3: new object end address.
// Store the type argument field.
__ StoreIntoObjectNoBarrier(
R0, FieldAddress(R0, target::Array::type_arguments_offset()), R1);
AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
R0, FieldAddress(R0, target::Array::length_offset()), R2);
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R8, R9: null
// R4: iterator which initially points to the start of the variable
// data area to be initialized.
@ -1096,9 +1107,10 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
__ LoadObject(R8, NullObject());
__ mov(R9, Operand(R8));
__ AddImmediate(R4, R0, target::Array::header_size() - kHeapObjectTag);
__ InitializeFieldsNoBarrier(R0, R4, R3, R8, R9);
__ Ret(); // Returns the newly allocated object in R0.
__ AddImmediate(R4, AllocateArrayABI::kResultReg,
target::Array::header_size() - kHeapObjectTag);
__ InitializeFieldsNoBarrier(AllocateArrayABI::kResultReg, R4, R3, R8, R9);
__ Ret();
// Unable to allocate the array using the fast inline code, just call
// into the runtime.
__ Bind(&slow_case);
@ -1110,11 +1122,13 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
__ LoadImmediate(TMP, 0);
// Setup space on stack for return value.
// Push array length as Smi and element type.
__ PushList((1 << R1) | (1 << R2) | (1 << IP));
__ PushList((1 << AllocateArrayABI::kTypeArgumentsReg) |
(1 << AllocateArrayABI::kLengthReg) | (1 << IP));
__ CallRuntime(kAllocateArrayRuntimeEntry, 2);
// Pop arguments; result is popped in IP.
__ PopList((1 << R1) | (1 << R2) | (1 << IP)); // R2 is restored.
__ mov(R0, Operand(IP));
__ PopList((1 << AllocateArrayABI::kTypeArgumentsReg) |
(1 << AllocateArrayABI::kLengthReg) | (1 << IP));
__ mov(AllocateArrayABI::kResultReg, Operand(IP));
__ LeaveStubFrame();
// Write-barrier elimination might be enabled for this array (depending on the

View file

@ -1118,12 +1118,14 @@ void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
}
// Called for inline allocation of arrays.
// Input parameters:
// Input registers (preserved):
// LR: return address.
// R2: array length as Smi.
// R1: array element type (either NULL or an instantiated type).
// NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
// The newly allocated object is returned in R0.
// AllocateArrayABI::kLengthReg: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// Output registers:
// AllocateArrayABI::kResultReg: newly allocated array.
// Clobbered:
// R3, R7
void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
Label slow_case;
@ -1132,12 +1134,12 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// RoundedAllocationSize(
// (array_length * kwordSize) + target::Array::header_size()).
// Check that length is a Smi.
__ BranchIfNotSmi(R2, &slow_case);
__ BranchIfNotSmi(AllocateArrayABI::kLengthReg, &slow_case);
// Check length >= 0 && length <= kMaxNewSpaceElements
const intptr_t max_len =
target::ToRawSmi(target::Array::kMaxNewSpaceElements);
__ CompareImmediate(R2, max_len, kObjectBytes);
__ CompareImmediate(AllocateArrayABI::kLengthReg, max_len, kObjectBytes);
__ b(&slow_case, HI);
const intptr_t cid = kArrayCid;
@ -1145,26 +1147,28 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Calculate and align allocation size.
// Load new object start and calculate next object start.
// R1: array element type.
// R2: array length as Smi.
__ ldr(R0, Address(THR, target::Thread::top_offset()));
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// AllocateArrayABI::kLengthReg: array length as Smi.
__ ldr(AllocateArrayABI::kResultReg,
Address(THR, target::Thread::top_offset()));
intptr_t fixed_size_plus_alignment_padding =
target::Array::header_size() +
target::ObjectAlignment::kObjectAlignment - 1;
__ LoadImmediate(R3, fixed_size_plus_alignment_padding);
__ add(R3, R3, Operand(R2, LSL, 2), kObjectBytes); // R2 is Smi.
__ add(R3, R3, Operand(AllocateArrayABI::kLengthReg, LSL, 2),
kObjectBytes); // R2 is Smi.
ASSERT(kSmiTagShift == 1);
__ andi(R3, R3,
Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));
// R0: potential new object start.
// AllocateArrayABI::kResultReg: potential new object start.
// R3: object size in bytes.
__ adds(R7, R3, Operand(R0));
__ adds(R7, R3, Operand(AllocateArrayABI::kResultReg));
__ b(&slow_case, CS); // Branch if unsigned overflow.
// Check if the allocation fits into the remaining space.
// R0: potential new object start.
// R1: array element type.
// R2: array length as Smi.
// AllocateArrayABI::kResultReg: potential new object start.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// AllocateArrayABI::kLengthReg: array length as Smi.
// R3: array size.
// R7: potential next object start.
__ LoadFromOffset(TMP, THR, target::Thread::end_offset());
@ -1173,66 +1177,72 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
// R0: potential new object start.
// AllocateArrayABI::kResultReg: potential new object start.
// R3: array size.
// R7: potential next object start.
__ str(R7, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
__ add(AllocateArrayABI::kResultReg, AllocateArrayABI::kResultReg,
Operand(kHeapObjectTag));
// R0: new object start as a tagged pointer.
// R1: array element type.
// R2: array length as Smi.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// AllocateArrayABI::kLengthReg: array length as Smi.
// R3: array size.
// R7: new object end address.
// Store the type argument field.
__ StoreIntoObjectOffsetNoBarrier(
R0, target::Array::type_arguments_offset(), R1);
__ StoreIntoObjectOffsetNoBarrier(AllocateArrayABI::kResultReg,
target::Array::type_arguments_offset(),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectOffsetNoBarrier(R0, target::Array::length_offset(), R2);
__ StoreIntoObjectOffsetNoBarrier(AllocateArrayABI::kResultReg,
target::Array::length_offset(),
AllocateArrayABI::kLengthReg);
// Calculate the size tag.
// R0: new object start as a tagged pointer.
// R2: array length as Smi.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// AllocateArrayABI::kLengthReg: array length as Smi.
// R3: array size.
// R7: new object end address.
const intptr_t shift = target::UntaggedObject::kTagBitsSizeTagPos -
target::ObjectAlignment::kObjectAlignmentLog2;
__ CompareImmediate(R3, target::UntaggedObject::kSizeTagMaxSizeTag);
// If no size tag overflow, shift R1 left, else set R1 to zero.
// If no size tag overflow, shift R3 left, else set R3 to zero.
__ LslImmediate(TMP, R3, shift);
__ csel(R1, TMP, R1, LS);
__ csel(R1, ZR, R1, HI);
__ csel(R3, TMP, R3, LS);
__ csel(R3, ZR, R3, HI);
// Get the class index and insert it into the tags.
const uword tags =
target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
__ LoadImmediate(TMP, tags);
__ orr(R1, R1, Operand(TMP));
__ StoreFieldToOffset(R1, R0, target::Array::tags_offset());
__ orr(R3, R3, Operand(TMP));
__ StoreFieldToOffset(R3, AllocateArrayABI::kResultReg,
target::Array::tags_offset());
// Initialize all array elements to raw_null.
// R0: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// R7: new object end address.
// R2: array length as Smi.
__ AddImmediate(R1, R0, target::Array::data_offset() - kHeapObjectTag);
// R1: iterator which initially points to the start of the variable
// AllocateArrayABI::kLengthReg: array length as Smi.
__ AddImmediate(R3, AllocateArrayABI::kResultReg,
target::Array::data_offset() - kHeapObjectTag);
// R3: iterator which initially points to the start of the variable
// data area to be initialized.
Label loop, done;
__ Bind(&loop);
// TODO(cshapiro): StoreIntoObjectNoBarrier
__ CompareRegisters(R1, R7);
__ CompareRegisters(R3, R7);
__ b(&done, CS);
__ str(NULL_REG, Address(R1)); // Store if unsigned lower.
__ AddImmediate(R1, target::kWordSize);
__ b(&loop); // Loop until R1 == R7.
__ str(NULL_REG, Address(R3)); // Store if unsigned lower.
__ AddImmediate(R3, target::kWordSize);
__ b(&loop); // Loop until R3 == R7.
__ Bind(&done);
// Done allocating and initializing the array.
// R0: new object.
// R2: array length as Smi (preserved for the caller.)
// AllocateArrayABI::kResultReg: new object.
// AllocateArrayABI::kLengthReg: array length as Smi (preserved).
__ ret();
// Unable to allocate the array using the fast inline code, just call
@ -1245,13 +1255,13 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Setup space on stack for return value.
// Push array length as Smi and element type.
__ Push(ZR);
__ Push(R2);
__ Push(R1);
__ Push(AllocateArrayABI::kLengthReg);
__ Push(AllocateArrayABI::kTypeArgumentsReg);
__ CallRuntime(kAllocateArrayRuntimeEntry, 2);
// Pop arguments; result is popped in IP.
__ Pop(R1);
__ Pop(R2);
__ Pop(R0);
__ Pop(AllocateArrayABI::kTypeArgumentsReg);
__ Pop(AllocateArrayABI::kLengthReg);
__ Pop(AllocateArrayABI::kResultReg);
__ LeaveStubFrame();
// Write-barrier elimination might be enabled for this array (depending on the

View file

@ -791,11 +791,13 @@ void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
}
// Called for inline allocation of arrays.
// Input parameters:
// EDX : Array length as Smi (must be preserved).
// ECX : array element type (either NULL or an instantiated type).
// Uses EAX, EBX, ECX, EDI as temporary registers.
// The newly allocated object is returned in EAX.
// Input registers (preserved):
// AllocateArrayABI::kLengthReg: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// Output registers:
// AllocateArrayABI::kResultReg: newly allocated array.
// Clobbered:
// EBX, EDI
void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
Label slow_case;
@ -804,54 +806,57 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// RoundedAllocationSize(
// (array_length * kwordSize) + target::Array::header_size()).
// Assert that length is a Smi.
__ testl(EDX, Immediate(kSmiTagMask));
__ testl(AllocateArrayABI::kLengthReg, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &slow_case);
// Check for maximum allowed length.
const Immediate& max_len =
Immediate(target::ToRawSmi(target::Array::kMaxNewSpaceElements));
__ cmpl(EDX, max_len);
__ cmpl(AllocateArrayABI::kLengthReg, max_len);
__ j(ABOVE, &slow_case);
NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid, EAX, &slow_case,
Assembler::kFarJump));
NOT_IN_PRODUCT(__ MaybeTraceAllocation(kArrayCid,
AllocateArrayABI::kResultReg,
&slow_case, Assembler::kFarJump));
const intptr_t fixed_size_plus_alignment_padding =
target::Array::header_size() +
target::ObjectAlignment::kObjectAlignment - 1;
// EDX is Smi.
__ leal(EBX, Address(EDX, TIMES_2, fixed_size_plus_alignment_padding));
// AllocateArrayABI::kLengthReg is Smi.
__ leal(EBX, Address(AllocateArrayABI::kLengthReg, TIMES_2,
fixed_size_plus_alignment_padding));
ASSERT(kSmiTagShift == 1);
__ andl(EBX, Immediate(-target::ObjectAlignment::kObjectAlignment));
// ECX: array element type.
// EDX: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: array type arguments.
// AllocateArrayABI::kLengthReg: array length as Smi.
// EBX: allocation size.
const intptr_t cid = kArrayCid;
__ movl(EAX, Address(THR, target::Thread::top_offset()));
__ addl(EBX, EAX);
__ movl(AllocateArrayABI::kResultReg,
Address(THR, target::Thread::top_offset()));
__ addl(EBX, AllocateArrayABI::kResultReg);
__ j(CARRY, &slow_case);
// Check if the allocation fits into the remaining space.
// EAX: potential new object start.
// AllocateArrayABI::kResultReg: potential new object start.
// EBX: potential next object start.
// ECX: array element type.
// EDX: array length as Smi).
// AllocateArrayABI::kTypeArgumentsReg: array type arguments.
// AllocateArrayABI::kLengthReg: array length as Smi).
__ cmpl(EBX, Address(THR, target::Thread::end_offset()));
__ j(ABOVE_EQUAL, &slow_case);
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
__ movl(Address(THR, target::Thread::top_offset()), EBX);
__ subl(EBX, EAX);
__ addl(EAX, Immediate(kHeapObjectTag));
__ subl(EBX, AllocateArrayABI::kResultReg);
__ addl(AllocateArrayABI::kResultReg, Immediate(kHeapObjectTag));
// Initialize the tags.
// EAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// EBX: allocation size.
// ECX: array element type.
// EDX: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: array type arguments.
// AllocateArrayABI::kLengthReg: array length as Smi.
{
Label size_tag_overflow, done;
__ movl(EDI, EBX);
@ -868,41 +873,50 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Get the class index and insert it into the tags.
uword tags = target::MakeTagWordForNewSpaceObject(cid, 0);
__ orl(EDI, Immediate(tags));
__ movl(FieldAddress(EAX, target::Object::tags_offset()), EDI); // Tags.
__ movl(FieldAddress(AllocateArrayABI::kResultReg,
target::Object::tags_offset()),
EDI); // Tags.
}
// EAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// EBX: allocation size.
// ECX: array element type.
// EDX: Array length as Smi (preserved).
// AllocateArrayABI::kTypeArgumentsReg: array type arguments.
// AllocateArrayABI::kLengthReg: Array length as Smi (preserved).
// Store the type argument field.
// No generational barrier needed, since we store into a new object.
__ StoreIntoObjectNoBarrier(
EAX, FieldAddress(EAX, target::Array::type_arguments_offset()), ECX);
AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
EAX, FieldAddress(EAX, target::Array::length_offset()), EDX);
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// EAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// EBX: allocation size.
// EDI: iterator which initially points to the start of the variable
// data area to be initialized.
// ECX: array element type.
// EDX: array length as Smi.
__ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0));
__ leal(EDI, FieldAddress(EAX, target::Array::header_size()));
// AllocateArrayABI::kTypeArgumentsReg: array type arguments.
// AllocateArrayABI::kLengthReg: array length as Smi.
__ leal(EBX, FieldAddress(AllocateArrayABI::kResultReg, EBX, TIMES_1, 0));
__ leal(EDI, FieldAddress(AllocateArrayABI::kResultReg,
target::Array::header_size()));
Label done;
Label init_loop;
__ Bind(&init_loop);
__ cmpl(EDI, EBX);
__ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
// No generational barrier needed, since we are storing null.
__ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), NullObject());
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg, Address(EDI, 0),
NullObject());
__ addl(EDI, Immediate(target::kWordSize));
__ jmp(&init_loop, Assembler::kNearJump);
__ Bind(&done);
__ ret(); // returns the newly allocated object in EAX.
__ ret();
// Unable to allocate the array using the fast inline code, just call
// into the runtime.
@ -912,12 +926,12 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// calling into the runtime.
__ EnterStubFrame();
__ pushl(Immediate(0)); // Setup space on stack for return value.
__ pushl(EDX); // Array length as Smi.
__ pushl(ECX); // Element type.
__ pushl(AllocateArrayABI::kLengthReg); // Array length as Smi.
__ pushl(AllocateArrayABI::kTypeArgumentsReg); // Type arguments.
__ CallRuntime(kAllocateArrayRuntimeEntry, 2);
__ popl(EAX); // Pop element type argument.
__ popl(EDX); // Pop array length argument (preserved).
__ popl(EAX); // Pop return value from return slot.
__ popl(AllocateArrayABI::kTypeArgumentsReg); // Pop type arguments.
__ popl(AllocateArrayABI::kLengthReg); // Pop array length argument.
__ popl(AllocateArrayABI::kResultReg); // Pop return value from return slot.
// Write-barrier elimination might be enabled for this array (depending on the
// array length). To be sure we will check if the allocated object is in old

View file

@ -1048,11 +1048,13 @@ void StubCodeCompiler::GenerateNoSuchMethodDispatcherStub(
}
// Called for inline allocation of arrays.
// Input parameters:
// R10 : Array length as Smi.
// RBX : array element type (either NULL or an instantiated type).
// NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
// The newly allocated object is returned in RAX.
// Input registers (preserved):
// AllocateArrayABI::kLengthReg: array length as Smi.
// AllocateArrayABI::kTypeArgumentsReg: type arguments of array.
// Output registers:
// AllocateArrayABI::kResultReg: newly allocated array.
// Clobbered:
// RCX, RDI, R12
void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
if (!FLAG_use_slow_path && FLAG_inline_alloc) {
Label slow_case;
@ -1060,7 +1062,7 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// and is computed as:
// RoundedAllocationSize(
// (array_length * target::kwordSize) + target::Array::header_size()).
__ movq(RDI, R10); // Array Length.
__ movq(RDI, AllocateArrayABI::kLengthReg); // Array Length.
// Check that length is Smi.
__ testq(RDI, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &slow_case);
@ -1084,15 +1086,16 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
__ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
const intptr_t cid = kArrayCid;
__ movq(RAX, Address(THR, target::Thread::top_offset()));
__ movq(AllocateArrayABI::kResultReg,
Address(THR, target::Thread::top_offset()));
// RDI: allocation size.
__ movq(RCX, RAX);
__ movq(RCX, AllocateArrayABI::kResultReg);
__ addq(RCX, RDI);
__ j(CARRY, &slow_case);
// Check if the allocation fits into the remaining space.
// RAX: potential new object start.
// AllocateArrayABI::kResultReg: potential new object start.
// RCX: potential next object start.
// RDI: allocation size.
__ cmpq(RCX, Address(THR, target::Thread::end_offset()));
@ -1101,10 +1104,10 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
__ movq(Address(THR, target::Thread::top_offset()), RCX);
__ addq(RAX, Immediate(kHeapObjectTag));
__ addq(AllocateArrayABI::kResultReg, Immediate(kHeapObjectTag));
// Initialize the tags.
// RAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// RDI: allocation size.
{
Label size_tag_overflow, done;
@ -1124,23 +1127,29 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
__ movq(FieldAddress(RAX, target::Array::tags_offset()), RDI); // Tags.
}
// RAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// Store the type argument field.
// No generational barrier needed, since we store into a new object.
__ StoreIntoObjectNoBarrier(
RAX, FieldAddress(RAX, target::Array::type_arguments_offset()), RBX);
AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::type_arguments_offset()),
AllocateArrayABI::kTypeArgumentsReg);
// Set the length field.
__ StoreIntoObjectNoBarrier(
RAX, FieldAddress(RAX, target::Array::length_offset()), R10);
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg,
FieldAddress(AllocateArrayABI::kResultReg,
target::Array::length_offset()),
AllocateArrayABI::kLengthReg);
// Initialize all array elements to raw_null.
// RAX: new object start as a tagged pointer.
// AllocateArrayABI::kResultReg: new object start as a tagged pointer.
// RCX: new object end address.
// RDI: iterator which initially points to the start of the variable
// data area to be initialized.
__ LoadObject(R12, NullObject());
__ leaq(RDI, FieldAddress(RAX, target::Array::header_size()));
__ leaq(RDI, FieldAddress(AllocateArrayABI::kResultReg,
target::Array::header_size()));
Label done;
Label init_loop;
__ Bind(&init_loop);
@ -1152,11 +1161,12 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
#endif // DEBUG
__ j(ABOVE_EQUAL, &done, kJumpLength);
// No generational barrier needed, since we are storing null.
__ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12);
__ StoreIntoObjectNoBarrier(AllocateArrayABI::kResultReg, Address(RDI, 0),
R12);
__ addq(RDI, Immediate(target::kWordSize));
__ jmp(&init_loop, kJumpLength);
__ Bind(&done);
__ ret(); // returns the newly allocated object in RAX.
__ ret();
// Unable to allocate the array using the fast inline code, just call
// into the runtime.
@ -1165,14 +1175,13 @@ void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
// Setup space on stack for return value.
__ pushq(Immediate(0));
__ pushq(R10); // Array length as Smi.
__ pushq(RBX); // Element type.
__ pushq(Immediate(0)); // Space for return value.
__ pushq(AllocateArrayABI::kLengthReg); // Array length as Smi.
__ pushq(AllocateArrayABI::kTypeArgumentsReg); // Element type.
__ CallRuntime(kAllocateArrayRuntimeEntry, 2);
__ popq(RAX); // Pop element type argument.
__ popq(R10); // Pop array length argument.
__ popq(RAX); // Pop return value from return slot.
__ popq(AllocateArrayABI::kTypeArgumentsReg); // Pop element type argument.
__ popq(AllocateArrayABI::kLengthReg); // Pop array length argument.
__ popq(AllocateArrayABI::kResultReg); // Pop allocated object.
// Write-barrier elimination might be enabled for this array (depending on the
// array length). To be sure we will check if the allocated object is in old

View file

@ -470,7 +470,14 @@ struct AllocateBoxABI {
static const Register kTempReg = R1;
};
// ABI for Allocate<TypedData>ArrayStub.
// ABI for AllocateArrayStub.
struct AllocateArrayABI {
static const Register kResultReg = R0;
static const Register kLengthReg = R2;
static const Register kTypeArgumentsReg = R1;
};
// ABI for AllocateTypedDataArrayStub.
struct AllocateTypedDataArrayABI {
static const Register kLengthReg = R4;
static const Register kResultReg = R0;

View file

@ -310,7 +310,14 @@ struct AllocateBoxABI {
static const Register kTempReg = R1;
};
// ABI for Allocate<TypedData>ArrayStub.
// ABI for AllocateArrayStub.
struct AllocateArrayABI {
static const Register kResultReg = R0;
static const Register kLengthReg = R2;
static const Register kTypeArgumentsReg = R1;
};
// ABI for AllocateTypedDataArrayStub.
struct AllocateTypedDataArrayABI {
static const Register kLengthReg = R4;
static const Register kResultReg = R0;

View file

@ -209,7 +209,14 @@ struct AllocateClosureABI {
static const Register kScratchReg = EDX;
};
// ABI for Allocate<TypedData>ArrayStub.
// ABI for AllocateArrayStub.
struct AllocateArrayABI {
static const Register kResultReg = EAX;
static const Register kLengthReg = EDX;
static const Register kTypeArgumentsReg = ECX;
};
// ABI for AllocateTypedDataArrayStub.
struct AllocateTypedDataArrayABI {
static const Register kLengthReg = EAX;
static const Register kResultReg = EAX;

View file

@ -282,7 +282,14 @@ struct AllocateBoxABI {
static const Register kTempReg = RBX;
};
// ABI for Allocate<TypedData>ArrayStub.
// ABI for AllocateArrayStub.
struct AllocateArrayABI {
static const Register kResultReg = RAX;
static const Register kLengthReg = R10;
static const Register kTypeArgumentsReg = RBX;
};
// ABI for AllocateTypedDataArrayStub.
struct AllocateTypedDataArrayABI {
static const Register kLengthReg = RAX;
static const Register kResultReg = RAX;