ARM64: Optimize AllocateHeapNumber to use STP.

R=jochen@chromium.org

Review URL: https://codereview.chromium.org/216933003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20356 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d486f52c
......@@ -285,9 +285,9 @@ struct FPRegister : public CPURegister {
static const unsigned kAllocatableLowRangeBegin = 0;
static const unsigned kAllocatableLowRangeEnd = 14;
static const unsigned kAllocatableHighRangeBegin = 16;
static const unsigned kAllocatableHighRangeEnd = 29;
static const unsigned kAllocatableHighRangeEnd = 28;
static const RegList kAllocatableFPRegisters = 0x3fff7fff;
static const RegList kAllocatableFPRegisters = 0x1fff7fff;
// Gap between low and high ranges.
static const int kAllocatableRangeGapSize =
......@@ -316,12 +316,12 @@ struct FPRegister : public CPURegister {
ASSERT((kAllocatableLowRangeBegin == 0) &&
(kAllocatableLowRangeEnd == 14) &&
(kAllocatableHighRangeBegin == 16) &&
(kAllocatableHighRangeEnd == 29));
(kAllocatableHighRangeEnd == 28));
const char* const names[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
"d8", "d9", "d10", "d11", "d12", "d13", "d14",
"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
"d24", "d25", "d26", "d27", "d28", "d29"
"d24", "d25", "d26", "d27", "d28"
};
return names[index];
}
......@@ -420,9 +420,11 @@ ALIAS_REGISTER(Register, wzr, w31);
// Keeps the 0 double value.
ALIAS_REGISTER(FPRegister, fp_zero, d15);
// Crankshaft double scratch register.
ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d30);
// MacroAssembler double scratch register.
ALIAS_REGISTER(FPRegister, fp_scratch, d31);
ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29);
// MacroAssembler double scratch registers.
ALIAS_REGISTER(FPRegister, fp_scratch, d30);
ALIAS_REGISTER(FPRegister, fp_scratch1, d30);
ALIAS_REGISTER(FPRegister, fp_scratch2, d31);
#undef ALIAS_REGISTER
......
......@@ -1393,9 +1393,8 @@ void MathPowStub::Generate(MacroAssembler* masm) {
// Return.
__ Bind(&done);
__ AllocateHeapNumber(result_tagged, &call_runtime, scratch0, scratch1);
__ Str(result_double,
FieldMemOperand(result_tagged, HeapNumber::kValueOffset));
__ AllocateHeapNumber(result_tagged, &call_runtime, scratch0, scratch1,
result_double);
ASSERT(result_tagged.is(x0));
__ IncrementCounter(
masm->isolate()->counters()->math_pow(), 1, scratch0, scratch1);
......
......@@ -339,8 +339,8 @@ void ElementsTransitionGenerator::GenerateDoubleToObject(
// Non-hole double, copy value into a heap number.
Register heap_num = x5;
__ AllocateHeapNumber(heap_num, &gc_required, x6, x4, heap_num_map);
__ Str(x13, FieldMemOperand(heap_num, HeapNumber::kValueOffset));
__ AllocateHeapNumber(heap_num, &gc_required, x6, x4,
x13, heap_num_map);
__ Mov(x13, dst_elements);
__ Str(heap_num, MemOperand(dst_elements, kPointerSize, PostIndex));
__ RecordWrite(array, x13, heap_num, kLRHasBeenSaved, kDontSaveFPRegs,
......
......@@ -4720,22 +4720,23 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
Register result_value = x2;
Register boolean_done = x3;
Register empty_fixed_array = x4;
Register untagged_result = x5;
__ Mov(map_reg, Operand(map));
__ Pop(result_value);
__ Mov(boolean_done, Operand(isolate()->factory()->ToBoolean(done)));
__ Mov(empty_fixed_array, Operand(isolate()->factory()->empty_fixed_array()));
ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
// TODO(jbramley): Use Stp if possible.
__ Str(map_reg, FieldMemOperand(result, HeapObject::kMapOffset));
__ Str(empty_fixed_array,
FieldMemOperand(result, JSObject::kPropertiesOffset));
__ Str(empty_fixed_array, FieldMemOperand(result, JSObject::kElementsOffset));
__ Str(result_value,
FieldMemOperand(result,
JSGeneratorObject::kResultValuePropertyOffset));
__ Str(boolean_done,
FieldMemOperand(result,
JSGeneratorObject::kResultDonePropertyOffset));
STATIC_ASSERT(JSObject::kPropertiesOffset + kPointerSize ==
JSObject::kElementsOffset);
STATIC_ASSERT(JSGeneratorObject::kResultValuePropertyOffset + kPointerSize ==
JSGeneratorObject::kResultDonePropertyOffset);
__ ObjectUntag(untagged_result, result);
__ Str(map_reg, MemOperand(untagged_result, HeapObject::kMapOffset));
__ Stp(empty_fixed_array, empty_fixed_array,
MemOperand(untagged_result, JSObject::kPropertiesOffset));
__ Stp(result_value, boolean_done,
MemOperand(untagged_result,
JSGeneratorObject::kResultValuePropertyOffset));
// Only the value field needs a write barrier, as the other values are in the
// root set.
......
......@@ -1409,6 +1409,30 @@ void MacroAssembler::JumpIfBothNotSmi(Register value1,
}
void MacroAssembler::ObjectTag(Register tagged_obj, Register obj) {
STATIC_ASSERT(kHeapObjectTag == 1);
if (emit_debug_code()) {
Label ok;
Tbz(obj, 0, &ok);
Abort(kObjectTagged);
Bind(&ok);
}
Orr(tagged_obj, obj, kHeapObjectTag);
}
void MacroAssembler::ObjectUntag(Register untagged_obj, Register obj) {
STATIC_ASSERT(kHeapObjectTag == 1);
if (emit_debug_code()) {
Label ok;
Tbnz(obj, 0, &ok);
Abort(kObjectNotTagged);
Bind(&ok);
}
Bic(untagged_obj, obj, kHeapObjectTag);
}
void MacroAssembler::IsObjectNameType(Register object,
Register type,
Label* fail) {
......
......@@ -53,7 +53,7 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate,
#endif
has_frame_(false),
use_real_aborts_(true),
sp_(jssp), tmp_list_(ip0, ip1), fptmp_list_(fp_scratch) {
sp_(jssp), tmp_list_(ip0, ip1), fptmp_list_(fp_scratch1, fp_scratch2) {
if (isolate() != NULL) {
code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
isolate());
......@@ -1196,7 +1196,7 @@ void MacroAssembler::AssertStackConsistency() {
}
void MacroAssembler::LoadRoot(Register destination,
void MacroAssembler::LoadRoot(CPURegister destination,
Heap::RootListIndex index) {
// TODO(jbramley): Most root values are constants, and can be synthesized
// without a load. Refer to the ARM back end for details.
......@@ -3267,7 +3267,7 @@ void MacroAssembler::Allocate(int object_size,
// Tag the object if requested.
if ((flags & TAG_OBJECT) != 0) {
Orr(result, result, kHeapObjectTag);
ObjectTag(result, result);
}
}
......@@ -3349,7 +3349,7 @@ void MacroAssembler::Allocate(Register object_size,
// Tag the object if requested.
if ((flags & TAG_OBJECT) != 0) {
Orr(result, result, kHeapObjectTag);
ObjectTag(result, result);
}
}
......@@ -3533,32 +3533,50 @@ void MacroAssembler::AllocateHeapNumber(Register result,
Label* gc_required,
Register scratch1,
Register scratch2,
Register heap_number_map) {
CPURegister value,
CPURegister heap_number_map) {
ASSERT(!value.IsValid() || value.Is64Bits());
UseScratchRegisterScope temps(this);
// Allocate an object in the heap for the heap number and tag it as a heap
// object.
Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
TAG_OBJECT);
// Store heap number map in the allocated object.
if (heap_number_map.Is(NoReg)) {
heap_number_map = scratch1;
NO_ALLOCATION_FLAGS);
// Prepare the heap number map.
if (!heap_number_map.IsValid()) {
// If we have a valid value register, use the same type of register to store
// the map so we can use STP to store both in one instruction.
if (value.IsValid() && value.IsFPRegister()) {
heap_number_map = temps.AcquireD();
} else {
heap_number_map = scratch1;
}
LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
}
AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
Str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
}
if (emit_debug_code()) {
Register map;
if (heap_number_map.IsFPRegister()) {
map = scratch1;
Fmov(map, DoubleRegister(heap_number_map));
} else {
map = Register(heap_number_map);
}
AssertRegisterIsRoot(map, Heap::kHeapNumberMapRootIndex);
}
void MacroAssembler::AllocateHeapNumberWithValue(Register result,
DoubleRegister value,
Label* gc_required,
Register scratch1,
Register scratch2,
Register heap_number_map) {
// TODO(all): Check if it would be more efficient to use STP to store both
// the map and the value.
AllocateHeapNumber(result, gc_required, scratch1, scratch2, heap_number_map);
Str(value, FieldMemOperand(result, HeapNumber::kValueOffset));
// Store the heap number map and the value in the allocated object.
if (value.IsSameSizeAndType(heap_number_map)) {
STATIC_ASSERT(HeapObject::kMapOffset + kPointerSize ==
HeapNumber::kValueOffset);
Stp(heap_number_map, value, MemOperand(result, HeapObject::kMapOffset));
} else {
Str(heap_number_map, MemOperand(result, HeapObject::kMapOffset));
if (value.IsValid()) {
Str(value, MemOperand(result, HeapNumber::kValueOffset));
}
}
ObjectTag(result, result);
}
......
......@@ -802,7 +802,7 @@ class MacroAssembler : public Assembler {
inline void InitializeRootRegister();
// Load an object from the root table.
void LoadRoot(Register destination,
void LoadRoot(CPURegister destination,
Heap::RootListIndex index);
// Store an object to the root table.
void StoreRoot(Register source,
......@@ -883,6 +883,9 @@ class MacroAssembler : public Assembler {
void AssertNotSmi(Register object, BailoutReason reason = kOperandIsASmi);
void AssertSmi(Register object, BailoutReason reason = kOperandIsNotASmi);
inline void ObjectTag(Register tagged_obj, Register obj);
inline void ObjectUntag(Register untagged_obj, Register obj);
// Abort execution if argument is not a name, enabled via --debug-code.
void AssertName(Register object);
......@@ -1354,13 +1357,8 @@ class MacroAssembler : public Assembler {
Label* gc_required,
Register scratch1,
Register scratch2,
Register heap_number_map = NoReg);
void AllocateHeapNumberWithValue(Register result,
DoubleRegister value,
Label* gc_required,
Register scratch1,
Register scratch2,
Register heap_number_map = NoReg);
CPURegister value = NoFPReg,
CPURegister heap_number_map = NoReg);
// ---------------------------------------------------------------------------
// Support functions.
......
......@@ -398,9 +398,7 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
DoubleRegister temp_double = temps.AcquireD();
__ SmiUntagToDouble(temp_double, value_reg, kSpeculativeUntag);
Label do_store, heap_number;
__ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2);
Label do_store;
__ JumpIfSmi(value_reg, &do_store);
__ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
......@@ -408,7 +406,7 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
__ Ldr(temp_double, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
__ Bind(&do_store);
__ Str(temp_double, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
__ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2, temp_double);
}
// Stub never generated for non-global objects that require access checks.
......
......@@ -1292,6 +1292,8 @@ class MaybeObject BASE_EMBEDDED {
V(kOperandIsNotAString, "Operand is not a string") \
V(kOperandIsNotSmi, "Operand is not smi") \
V(kOperandNotANumber, "Operand not a number") \
V(kObjectTagged, "The object is tagged") \
V(kObjectNotTagged, "The object is not tagged") \
V(kOptimizationDisabled, "Optimization is disabled") \
V(kOptimizedTooManyTimes, "Optimized too many times") \
V(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister, \
......
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