-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// r2: initial map
// r7: undefined
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
- // Make sure that the maximum heap object size will never cause us
- // problem here, because it is always greater than the maximum
- // instance size that can be represented in a byte.
- ASSERT(Heap::MaxObjectSizeInPagedSpace() >= JSObject::kMaxInstanceSize);
- __ AllocateObjectInNewSpace(r3, r4, r5, r6, &rt_call, false);
+ __ AllocateObjectInNewSpace(r3, r4, r5, r6, &rt_call, NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields. Map is set to initial
// map and properties and elements are set to empty fixed array.
// r5: First in-object property of JSObject (not tagged)
// r7: undefined
__ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
- ASSERT_EQ(12, JSObject::kHeaderSize);
+ ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
{ Label loop, entry;
__ b(&entry);
__ bind(&loop);
// Check if a non-empty properties array is needed. Continue with allocated
// object if not fall through to runtime call if it is.
// r1: constructor function
- // r2: initial map
// r4: JSObject
// r5: start of next object (not tagged)
// r7: undefined
// Done if no extra properties are to be allocated.
__ b(eq, &allocated);
- __ Assert(al, "Property allocation count failed.");
+ __ Assert(pl, "Property allocation count failed.");
+
+ // Scale the number of elements by pointer size and add the header for
+ // FixedArrays to the start of the next object calculation from above.
+ // r1: constructor
+ // r3: number of elements in properties array
+ // r4: JSObject
+ // r5: start of next object
+ // r7: undefined
+ __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize));
+ __ AllocateObjectInNewSpace(r0,
+ r5,
+ r6,
+ r2,
+ &undo_allocation,
+ RESULT_CONTAINS_TOP);
+
+ // Initialize the FixedArray.
+ // r1: constructor
+ // r3: number of elements in properties array
+ // r4: JSObject
+ // r5: FixedArray (not tagged)
+ // r7: undefined
+ __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex);
+ __ mov(r2, r5);
+ ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
+ __ str(r6, MemOperand(r2, kPointerSize, PostIndex));
+ ASSERT_EQ(1 * kPointerSize, Array::kLengthOffset);
+ __ str(r3, MemOperand(r2, kPointerSize, PostIndex));
+
+ // Initialize the fields to undefined.
+ // r1: constructor function
+ // r2: First element of FixedArray (not tagged)
+ // r3: number of elements in properties array
+ // r4: JSObject
+ // r5: FixedArray (not tagged)
+ // r7: undefined
+ __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
+ ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
+ { Label loop, entry;
+ __ b(&entry);
+ __ bind(&loop);
+ __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
+ __ bind(&entry);
+ __ cmp(r2, Operand(r6));
+ __ b(lt, &loop);
+ }
+
+ // Store the initialized FixedArray into the properties field of
+ // the JSObject
+ // r1: constructor function
+ // r4: JSObject
+ // r5: FixedArray (not tagged)
+ __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag.
+ __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset));
+
+ // Continue with JSObject being successfully allocated
+ // r1: constructor function
+ // r4: JSObject
+ __ jmp(&allocated);
// Undo the setting of the new top so that the heap is verifiable. For
// example, the map's unused properties potentially do not match the
}
// Allocate the new receiver object using the runtime call.
+ // r1: constructor function
__ bind(&rt_call);
__ push(r1); // argument for Runtime_NewObject
__ CallRuntime(Runtime::kNewObject, 1);
scratch1,
scratch2,
need_gc,
- true);
+ TAG_OBJECT);
// Get heap number map and store it in the allocated object.
__ LoadRoot(scratch1, Heap::kHeapNumberMapRootIndex);
Register scratch1,
Register scratch2,
Label* gc_required,
- bool tag_allocated_object) {
+ AllocationFlags flags) {
ASSERT(!result.is(scratch1));
ASSERT(!scratch1.is(scratch2));
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
mov(scratch1, Operand(new_space_allocation_top));
- ldr(result, MemOperand(scratch1));
+ if ((flags & RESULT_CONTAINS_TOP) == 0) {
+ ldr(result, MemOperand(scratch1));
+ } else {
+#ifdef DEBUG
+ // Assert that result actually contains top on entry. scratch2 is used
+ // immediately below so this use of scratch2 does not cause difference with
+ // respect to register content between debug and release mode.
+ ldr(scratch2, MemOperand(scratch1));
+ cmp(result, scratch2);
+ Check(eq, "Unexpected allocation top");
+#endif
+ }
// Calculate new top and bail out if new space is exhausted. Use result
// to calculate the new top.
str(result, MemOperand(scratch1));
// Tag and adjust back to start of new object.
- if (tag_allocated_object) {
+ if ((flags & TAG_OBJECT) != 0) {
sub(result, result, Operand((object_size * kPointerSize) -
kHeapObjectTag));
} else {
Register scratch1,
Register scratch2,
Label* gc_required,
- bool tag_allocated_object) {
+ AllocationFlags flags) {
ASSERT(!result.is(scratch1));
ASSERT(!scratch1.is(scratch2));
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address();
mov(scratch1, Operand(new_space_allocation_top));
- ldr(result, MemOperand(scratch1));
+ if ((flags & RESULT_CONTAINS_TOP) == 0) {
+ ldr(result, MemOperand(scratch1));
+ } else {
+#ifdef DEBUG
+ // Assert that result actually contains top on entry. scratch2 is used
+ // immediately below so this use of scratch2 does not cause difference with
+ // respect to register content between debug and release mode.
+ ldr(scratch2, MemOperand(scratch1));
+ cmp(result, scratch2);
+ Check(eq, "Unexpected allocation top");
+#endif
+ }
// Calculate new top and bail out if new space is exhausted. Use result
// to calculate the new top. Object size is in words so a shift is required to
mov(scratch2, Operand(new_space_allocation_limit));
ldr(scratch2, MemOperand(scratch2));
add(result, result, Operand(object_size, LSL, kPointerSizeLog2));
-
cmp(result, Operand(scratch2));
b(hi, gc_required);
// Update allocation top. result temporarily holds the new top,
str(result, MemOperand(scratch1));
- // Tag and adjust back to start of new object.
- if (tag_allocated_object) {
- sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+ // Adjust back to start of new object.
+ sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
+
+ // Tag object if requested.
+ if ((flags & TAG_OBJECT) != 0) {
add(result, result, Operand(kHeapObjectTag));
- } else {
- sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
}
}
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
};
+// Flags used for the AllocateObjectInNewSpace functions.
+enum AllocationFlags {
+ // No special flags.
+ NO_ALLOCATION_FLAGS = 0,
+ // Return the pointer to the allocated already tagged as a heap object.
+ TAG_OBJECT = 1 << 0,
+ // The content of the result register already contains the allocation top in
+ // new space.
+ RESULT_CONTAINS_TOP = 1 << 1
+};
+
+
// MacroAssembler implements a collection of frequently used macros.
class MacroAssembler: public Assembler {
public:
Register scratch1,
Register scratch2,
Label* gc_required,
- bool tag_allocated_object);
+ AllocationFlags flags);
void AllocateObjectInNewSpace(Register object_size,
Register result,
Register scratch1,
Register scratch2,
Label* gc_required,
- bool tag_allocated_object);
+ AllocationFlags flags);
// Undo allocation in new space. The object passed and objects allocated after
// it will no longer be allocated. The caller must make sure that no pointers
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// problem here, because it is always greater than the maximum
// instance size that can be represented in a byte.
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= JSObject::kMaxInstanceSize);
- __ AllocateObjectInNewSpace(edi, ebx, edi, no_reg, &rt_call, false);
+ __ AllocateObjectInNewSpace(edi,
+ ebx,
+ edi,
+ no_reg,
+ &rt_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields.
// eax: initial map
// ebx: JSObject
ecx,
no_reg,
&undo_allocation,
- true);
+ RESULT_CONTAINS_TOP);
// Initialize the FixedArray.
// ebx: JSObject
}
// Allocate the new receiver object using the runtime call.
- // edi: function (constructor)
__ bind(&rt_call);
// Must restore edi (constructor) before calling runtime.
__ mov(edi, Operand(esp, 0));
+ // edi: function (constructor)
__ push(edi);
__ CallRuntime(Runtime::kNewObject, 1);
__ mov(ebx, Operand(eax)); // store result in ebx
scratch1,
scratch2,
need_gc,
- false);
+ TAG_OBJECT);
- // Set the map and tag the result.
- __ mov(Operand(result, HeapObject::kMapOffset),
+ // Set the map.
+ __ mov(FieldOperand(result, HeapObject::kMapOffset),
Immediate(Factory::heap_number_map()));
- __ or_(Operand(result), Immediate(kHeapObjectTag));
}
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
}
-void MacroAssembler::LoadAllocationTopHelper(
- Register result,
- Register result_end,
- Register scratch,
- bool result_contains_top_on_entry) {
+void MacroAssembler::LoadAllocationTopHelper(Register result,
+ Register result_end,
+ Register scratch,
+ AllocationFlags flags) {
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) {
+ if ((flags & RESULT_CONTAINS_TOP) != 0) {
// No use of scratch if allocation top is provided.
ASSERT(scratch.is(no_reg));
return;
}
}
-void MacroAssembler::AllocateObjectInNewSpace(
- int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- bool result_contains_top_on_entry) {
+
+void MacroAssembler::AllocateObjectInNewSpace(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ or_(Operand(result), Immediate(kHeapObjectTag));
+ }
}
-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) {
+void MacroAssembler::AllocateObjectInNewSpace(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ or_(Operand(result), Immediate(kHeapObjectTag));
+ }
}
-void MacroAssembler::AllocateObjectInNewSpace(
- Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- bool result_contains_top_on_entry) {
+void MacroAssembler::AllocateObjectInNewSpace(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
-
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ or_(Operand(result), Immediate(kHeapObjectTag));
+ }
}
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
};
+// Flags used for the AllocateObjectInNewSpace functions.
+enum AllocationFlags {
+ // No special flags.
+ NO_ALLOCATION_FLAGS = 0,
+ // Return the pointer to the allocated already tagged as a heap object.
+ TAG_OBJECT = 1 << 0,
+ // The content of the result register already contains the allocation top in
+ // new space.
+ RESULT_CONTAINS_TOP = 1 << 1
+};
+
+
// MacroAssembler implements a collection of frequently used macros.
class MacroAssembler: public Assembler {
public:
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void AllocateObjectInNewSpace(int header_size,
ScaleFactor element_size,
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void AllocateObjectInNewSpace(Register object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
// 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
void LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void UpdateAllocationTopHelper(Register result_end, Register scratch);
};
// Make sure that the maximum heap object size will never cause us
// problems here.
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= JSObject::kMaxInstanceSize);
- __ AllocateObjectInNewSpace(ecx, edx, ecx, no_reg, &generic_stub_call, false);
+ __ AllocateObjectInNewSpace(ecx,
+ edx,
+ ecx,
+ no_reg,
+ &generic_stub_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields and add the heap tag.
// ebx: initial map
// problem here, because it is always greater than the maximum
// instance size that can be represented in a byte.
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= (1 << kBitsPerByte));
- __ AllocateObjectInNewSpace(rdi, rbx, rdi, no_reg, &rt_call, false);
+ __ AllocateObjectInNewSpace(rdi,
+ rbx,
+ rdi,
+ no_reg,
+ &rt_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields.
// rax: initial map
// rbx: JSObject (not HeapObject tagged - the actual address).
rax,
no_reg,
&undo_allocation,
- true);
+ RESULT_CONTAINS_TOP);
// Initialize the FixedArray.
// rbx: JSObject
scratch,
no_reg,
need_gc,
- false);
+ TAG_OBJECT);
// Set the map and tag the result.
- __ addq(result, Immediate(kHeapObjectTag));
__ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
__ movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
}
}
-void MacroAssembler::LoadAllocationTopHelper(
- Register result,
- Register result_end,
- Register scratch,
- bool result_contains_top_on_entry) {
+void MacroAssembler::LoadAllocationTopHelper(Register result,
+ Register result_end,
+ Register scratch,
+ AllocationFlags flags) {
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) {
+ if ((flags & RESULT_CONTAINS_TOP) != 0) {
// No use of scratch if allocation top is provided.
ASSERT(scratch.is(no_reg));
return;
}
-void MacroAssembler::AllocateObjectInNewSpace(
- int object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- bool result_contains_top_on_entry) {
+void MacroAssembler::AllocateObjectInNewSpace(int object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag the result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ addq(result, Immediate(kHeapObjectTag));
+ }
}
-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) {
+void MacroAssembler::AllocateObjectInNewSpace(int header_size,
+ ScaleFactor element_size,
+ Register element_count,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
ASSERT(!result.is(result_end));
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag the result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ addq(result, Immediate(kHeapObjectTag));
+ }
}
-void MacroAssembler::AllocateObjectInNewSpace(
- Register object_size,
- Register result,
- Register result_end,
- Register scratch,
- Label* gc_required,
- bool result_contains_top_on_entry) {
+void MacroAssembler::AllocateObjectInNewSpace(Register object_size,
+ Register result,
+ Register result_end,
+ Register scratch,
+ Label* gc_required,
+ AllocationFlags flags) {
// Load address of new object into result.
- LoadAllocationTopHelper(result,
- result_end,
- scratch,
- result_contains_top_on_entry);
-
+ LoadAllocationTopHelper(result, result_end, scratch, flags);
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
// Update allocation top.
UpdateAllocationTopHelper(result_end, scratch);
+
+ // Tag the result if requested.
+ if ((flags & TAG_OBJECT) != 0) {
+ addq(result, Immediate(kHeapObjectTag));
+ }
}
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
};
+// Flags used for the AllocateObjectInNewSpace functions.
+enum AllocationFlags {
+ // No special flags.
+ NO_ALLOCATION_FLAGS = 0,
+ // Return the pointer to the allocated already tagged as a heap object.
+ TAG_OBJECT = 1 << 0,
+ // The content of the result register already contains the allocation top in
+ // new space.
+ RESULT_CONTAINS_TOP = 1 << 1
+};
+
+
// MacroAssembler implements a collection of frequently used macros.
class MacroAssembler: public Assembler {
public:
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void AllocateObjectInNewSpace(int header_size,
ScaleFactor element_size,
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void AllocateObjectInNewSpace(Register object_size,
Register result,
Register result_end,
Register scratch,
Label* gc_required,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
// 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
void LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch,
- bool result_contains_top_on_entry);
+ AllocationFlags flags);
void UpdateAllocationTopHelper(Register result_end, Register scratch);
};
// Make sure that the maximum heap object size will never cause us
// problems here.
ASSERT(Heap::MaxObjectSizeInPagedSpace() >= JSObject::kMaxInstanceSize);
- __ AllocateObjectInNewSpace(rcx, rdx, rcx, no_reg, &generic_stub_call, false);
+ __ AllocateObjectInNewSpace(rcx,
+ rdx,
+ rcx,
+ no_reg,
+ &generic_stub_call,
+ NO_ALLOCATION_FLAGS);
// Allocated the JSObject, now initialize the fields and add the heap tag.
// rbx: initial map