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 =
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];
}
// 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
// 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);
// 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,
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.
}
+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) {
#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());
}
-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.
// Tag the object if requested.
if ((flags & TAG_OBJECT) != 0) {
- Orr(result, result, kHeapObjectTag);
+ ObjectTag(result, result);
}
}
// Tag the object if requested.
if ((flags & TAG_OBJECT) != 0) {
- Orr(result, result, kHeapObjectTag);
+ ObjectTag(result, 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);
}
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,
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);
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.
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,
__ 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.
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, \