Add allocation support to x64 macro assembler.

Factored out the allocation in new space from assembler code into the macro assembler for x64 as was recently done for ia32.

Added set property svn:eol-style to native for all x64 files.
Review URL: http://codereview.chromium.org/173568

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2778 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2009-08-28 06:18:36 +00:00
parent 231f0b9656
commit 94c0539052
6 changed files with 230 additions and 43 deletions

View File

@ -158,10 +158,10 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ j(less, &loop);
}
// Mostly done with the JSObject. Add the heap tag and store the new top, so
// that we can continue and jump into the continuation code at any time from
// now on. Any failures need to undo the setting of the new top, so that the
// heap is in a consistent state and verifiable.
// Add the object tag to make the JSObject real, so that we can continue and
// jump into the continuation code at any time from now on. Any failures
// need to undo the allocation, so that the heap is in a consistent state
// and verifiable.
// eax: initial map
// ebx: JSObject
// edi: start of next object

View File

@ -669,14 +669,14 @@ void MacroAssembler::AllocateObjectInNewSpace(
ASSERT(!result.is(result_end));
// Load address of new object into result.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
LoadAllocationTopHelper(result,
result_end,
scratch,
result_contains_top_on_entry);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
lea(result_end, Operand(result, object_size));
cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required, not_taken);

View File

@ -542,16 +542,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// problem here, because it is always greater than the maximum
// instance size that can be represented in a byte.
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= (1 << kBitsPerByte));
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
__ movq(kScratchRegister, new_space_allocation_top);
__ movq(rbx, Operand(kScratchRegister, 0));
__ addq(rdi, rbx); // Calculate new top
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
__ movq(kScratchRegister, new_space_allocation_limit);
__ cmpq(rdi, Operand(kScratchRegister, 0));
__ j(above_equal, &rt_call);
__ AllocateObjectInNewSpace(rdi, rbx, rdi, no_reg, &rt_call, false);
// Allocated the JSObject, now initialize the fields.
// rax: initial map
// rbx: JSObject (not HeapObject tagged - the actual address).
@ -576,16 +567,14 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ j(less, &loop);
}
// Mostly done with the JSObject. Add the heap tag and store the new top, so
// that we can continue and jump into the continuation code at any time from
// now on. Any failures need to undo the setting of the new top, so that the
// heap is in a consistent state and verifiable.
// Add the object tag to make the JSObject real, so that we can continue and
// jump into the continuation code at any time from now on. Any failures
// need to undo the allocation, so that the heap is in a consistent state
// and verifiable.
// rax: initial map
// rbx: JSObject
// rdi: start of next object
__ or_(rbx, Immediate(kHeapObjectTag));
__ movq(kScratchRegister, new_space_allocation_top);
__ movq(Operand(kScratchRegister, 0), rdi);
// Check if a non-empty properties array is needed.
// Allocate and initialize a FixedArray if it is.
@ -610,11 +599,14 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// rdx: number of elements in properties array
ASSERT(Heap::MaxObjectSizeInPagedSpace() >
(FixedArray::kHeaderSize + 255*kPointerSize));
__ lea(rax, Operand(rdi, rdx, times_pointer_size, FixedArray::kHeaderSize));
__ movq(kScratchRegister, new_space_allocation_limit);
__ cmpq(rax, Operand(kScratchRegister, 0));
__ j(above_equal, &undo_allocation);
__ store_rax(new_space_allocation_top);
__ AllocateObjectInNewSpace(FixedArray::kHeaderSize,
times_pointer_size,
rdx,
rdi,
rax,
no_reg,
&undo_allocation,
true);
// Initialize the FixedArray.
// rbx: JSObject
@ -659,9 +651,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// allocated objects unused properties.
// rbx: JSObject (previous new top)
__ bind(&undo_allocation);
__ xor_(rbx, Immediate(kHeapObjectTag)); // clear the heap tag
__ movq(kScratchRegister, new_space_allocation_top);
__ movq(Operand(kScratchRegister, 0), rbx);
__ UndoAllocationInNewSpace(rbx);
}
// Allocate the new receiver object using the runtime call.

View File

@ -7324,24 +7324,20 @@ void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm,
Label* need_gc,
Register scratch,
Register result) {
ExternalReference allocation_top =
ExternalReference::new_space_allocation_top_address();
ExternalReference allocation_limit =
ExternalReference::new_space_allocation_limit_address();
__ movq(scratch, allocation_top); // scratch: address of allocation top.
__ movq(result, Operand(scratch, 0));
__ addq(result, Immediate(HeapNumber::kSize)); // New top.
__ movq(kScratchRegister, allocation_limit);
__ cmpq(result, Operand(kScratchRegister, 0));
__ j(above, need_gc);
// Allocate heap number in new space.
__ AllocateObjectInNewSpace(HeapNumber::kSize,
result,
scratch,
no_reg,
need_gc,
false);
__ movq(Operand(scratch, 0), result); // store new top
__ addq(result, Immediate(kHeapObjectTag - HeapNumber::kSize));
// Set the map and tag the result.
__ addq(result, Immediate(kHeapObjectTag));
__ movq(kScratchRegister,
Factory::heap_number_map(),
RelocInfo::EMBEDDED_OBJECT);
__ movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
// Tag old top and use as result.
}

View File

@ -1204,4 +1204,156 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
}
void MacroAssembler::LoadAllocationTopHelper(
Register result,
Register result_end,
Register scratch,
bool result_contains_top_on_entry) {
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
// Just return if allocation top is already known.
if (result_contains_top_on_entry) {
// No use of scratch if allocation top is provided.
ASSERT(scratch.is(no_reg));
return;
}
// Move address of new object to result. Use scratch register if available.
if (scratch.is(no_reg)) {
movq(kScratchRegister, new_space_allocation_top);
movq(result, Operand(kScratchRegister, 0));
} else {
ASSERT(!scratch.is(result_end));
movq(scratch, new_space_allocation_top);
movq(result, Operand(scratch, 0));
}
}
void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
Register scratch) {
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
// Update new top.
if (result_end.is(rax)) {
// rax can be stored directly to a memory location.
store_rax(new_space_allocation_top);
} else {
// Register required - use scratch provided if available.
if (scratch.is(no_reg)) {
movq(kScratchRegister, new_space_allocation_top);
movq(Operand(kScratchRegister, 0), result_end);
} else {
movq(Operand(scratch, 0), result_end);
}
}
}
void MacroAssembler::AllocateObjectInNewSpace(
int object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
LoadAllocationTopHelper(result,
result_end,
scratch,
result_contains_top_on_entry);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
lea(result_end, Operand(result, object_size));
movq(kScratchRegister, new_space_allocation_limit);
cmpq(result_end, Operand(kScratchRegister, 0));
j(above, gc_required);
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
}
void MacroAssembler::AllocateObjectInNewSpace(
int header_size,
ScaleFactor element_size,
Register element_count,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
LoadAllocationTopHelper(result,
result_end,
scratch,
result_contains_top_on_entry);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
lea(result_end, Operand(result, element_count, element_size, header_size));
movq(kScratchRegister, new_space_allocation_limit);
cmpq(result_end, Operand(kScratchRegister, 0));
j(above, gc_required);
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
}
void MacroAssembler::AllocateObjectInNewSpace(
Register object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry) {
// Load address of new object into result.
LoadAllocationTopHelper(result,
result_end,
scratch,
result_contains_top_on_entry);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
if (!object_size.is(result_end)) {
movq(result_end, object_size);
}
addq(result_end, result);
movq(kScratchRegister, new_space_allocation_limit);
cmpq(result_end, Operand(kScratchRegister, 0));
j(above, gc_required);
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
}
void MacroAssembler::UndoAllocationInNewSpace(Register object) {
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
// Make sure the object has no tag before resetting top.
and_(object, Immediate(~kHeapObjectTagMask));
movq(kScratchRegister, new_space_allocation_top);
#ifdef DEBUG
cmpq(object, Operand(kScratchRegister, 0));
Check(below, "Undo allocation of non allocated memory");
#endif
movq(Operand(kScratchRegister, 0), object);
}
} } // namespace v8::internal

View File

@ -222,6 +222,48 @@ class MacroAssembler: public Assembler {
Label* miss);
// ---------------------------------------------------------------------------
// Allocation support
// Allocate an object in new space. If the new space is exhausted control
// continues at the gc_required label. The allocated object is returned in
// result and end of the new object is returned in result_end. The register
// scratch can be passed as no_reg in which case an additional object
// reference will be added to the reloc info. The returned pointers in result
// and result_end have not yet been tagged as heap objects. If
// result_contains_top_on_entry is true the content of result is known to be
// the allocation top on entry (could be result_end from a previous call to
// AllocateObjectInNewSpace). If result_contains_top_on_entry is true scratch
// should be no_reg as it is never used.
void AllocateObjectInNewSpace(int object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry);
void AllocateObjectInNewSpace(int header_size,
ScaleFactor element_size,
Register element_count,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry);
void AllocateObjectInNewSpace(Register object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
bool result_contains_top_on_entry);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. Make sure that no pointers are left to the
// object(s) no longer allocated as they would be invalid when allocation is
// un-done.
void UndoAllocationInNewSpace(Register object);
// ---------------------------------------------------------------------------
// Support functions.
@ -341,6 +383,13 @@ class MacroAssembler: public Assembler {
// Activation support.
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
// Allocation support helpers.
void LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch,
bool result_contains_top_on_entry);
void UpdateAllocationTopHelper(Register result_end, Register scratch);
};