Reverting 2797.
Review URL: http://codereview.chromium.org/176060 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2799 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2c0d50dde5
commit
33a8bdad62
@ -88,144 +88,23 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
|||||||
// Enter a construct frame.
|
// Enter a construct frame.
|
||||||
__ EnterConstructFrame();
|
__ EnterConstructFrame();
|
||||||
|
|
||||||
// Preserve the two incoming parameters on the stack.
|
// Preserve the two incoming parameters
|
||||||
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
|
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
|
||||||
__ push(r0); // Smi-tagged arguments count.
|
__ push(r0); // smi-tagged arguments count
|
||||||
__ push(r1); // Constructor function.
|
__ push(r1); // constructor function
|
||||||
|
|
||||||
// Use r7 for holding undefined which is used in several places below.
|
// Allocate the new receiver object.
|
||||||
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
|
|
||||||
|
|
||||||
// Try to allocate the object without transitioning into C code. If any of the
|
|
||||||
// preconditions is not met, the code bails out to the runtime call.
|
|
||||||
Label rt_call, allocated;
|
|
||||||
if (FLAG_inline_new) {
|
|
||||||
Label undo_allocation;
|
|
||||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
|
||||||
ExternalReference debug_step_in_fp =
|
|
||||||
ExternalReference::debug_step_in_fp_address();
|
|
||||||
__ mov(r2, Operand(debug_step_in_fp));
|
|
||||||
__ ldr(r2, MemOperand(r2));
|
|
||||||
__ tst(r2, r2);
|
|
||||||
__ b(nz, &rt_call);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Load the initial map and verify that it is in fact a map.
|
|
||||||
// r1: constructor function
|
|
||||||
// r7: undefined
|
|
||||||
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
__ tst(r2, Operand(kSmiTagMask));
|
|
||||||
__ b(eq, &rt_call);
|
|
||||||
__ CompareObjectType(r2, r3, r4, MAP_TYPE);
|
|
||||||
__ b(ne, &rt_call);
|
|
||||||
|
|
||||||
// Check that the constructor is not constructing a JSFunction (see comments
|
|
||||||
// in Runtime_NewObject in runtime.cc). In which case the initial map's
|
|
||||||
// instance type would be JS_FUNCTION_TYPE.
|
|
||||||
// r1: constructor function
|
|
||||||
// r2: initial map
|
|
||||||
// r7: undefined
|
|
||||||
__ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
|
|
||||||
__ b(eq, &rt_call);
|
|
||||||
|
|
||||||
// Now allocate the JSObject on the heap.
|
|
||||||
// r1: constructor function
|
|
||||||
// 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);
|
|
||||||
// Allocated the JSObject, now initialize the fields. Map is set to initial
|
|
||||||
// map and properties and elements are set to empty fixed array.
|
|
||||||
// r1: constructor function
|
|
||||||
// r2: initial map
|
|
||||||
// r3: object size
|
|
||||||
// r4: JSObject (not tagged)
|
|
||||||
// r7: undefined
|
|
||||||
__ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
|
|
||||||
__ mov(r5, r4);
|
|
||||||
ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset);
|
|
||||||
__ str(r2, MemOperand(r5, kPointerSize, PostIndex));
|
|
||||||
ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
|
|
||||||
__ str(r6, MemOperand(r5, kPointerSize, PostIndex));
|
|
||||||
ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset);
|
|
||||||
__ str(r6, MemOperand(r5, kPointerSize, PostIndex));
|
|
||||||
|
|
||||||
// Fill all the in-object properties with undefined.
|
|
||||||
// r1: constructor function
|
|
||||||
// r2: initial map
|
|
||||||
// r3: object size (in words)
|
|
||||||
// r4: JSObject (not tagged)
|
|
||||||
// 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);
|
|
||||||
{ Label loop, entry;
|
|
||||||
__ b(&entry);
|
|
||||||
__ bind(&loop);
|
|
||||||
__ str(r7, MemOperand(r5, kPointerSize, PostIndex));
|
|
||||||
__ bind(&entry);
|
|
||||||
__ cmp(r5, Operand(r6));
|
|
||||||
__ b(lt, &loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
__ add(r4, r4, Operand(kHeapObjectTag));
|
|
||||||
|
|
||||||
// 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
|
|
||||||
__ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset));
|
|
||||||
// The field instance sizes contains both pre-allocated property fields and
|
|
||||||
// in-object properties.
|
|
||||||
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
|
|
||||||
__ and_(r6,
|
|
||||||
r0,
|
|
||||||
Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8));
|
|
||||||
__ add(r3, r3, Operand(r6, LSR, Map::kPreAllocatedPropertyFieldsByte * 8));
|
|
||||||
__ and_(r6, r0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8));
|
|
||||||
__ sub(r3, r3, Operand(r6, LSR, Map::kInObjectPropertiesByte * 8), SetCC);
|
|
||||||
|
|
||||||
// Done if no extra properties are to be allocated.
|
|
||||||
__ b(eq, &allocated);
|
|
||||||
__ Assert(pl, "Property allocation count failed.");
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// allocated objects unused properties.
|
|
||||||
// r4: JSObject (previous new top)
|
|
||||||
__ bind(&undo_allocation);
|
|
||||||
__ UndoAllocationInNewSpace(r4, r5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate the new receiver object using the runtime call.
|
|
||||||
__ bind(&rt_call);
|
|
||||||
__ push(r1); // argument for Runtime_NewObject
|
__ push(r1); // argument for Runtime_NewObject
|
||||||
__ CallRuntime(Runtime::kNewObject, 1);
|
__ CallRuntime(Runtime::kNewObject, 1);
|
||||||
__ mov(r4, r0);
|
__ push(r0); // save the receiver
|
||||||
|
|
||||||
// Receiver for constructor call allocated.
|
|
||||||
// r4: JSObject
|
|
||||||
__ bind(&allocated);
|
|
||||||
__ push(r4);
|
|
||||||
|
|
||||||
// Push the function and the allocated receiver from the stack.
|
// Push the function and the allocated receiver from the stack.
|
||||||
// sp[0]: receiver (newly allocated object)
|
// sp[0]: receiver (newly allocated object)
|
||||||
// sp[1]: constructor function
|
// sp[1]: constructor function
|
||||||
// sp[2]: number of arguments (smi-tagged)
|
// sp[2]: number of arguments (smi-tagged)
|
||||||
__ ldr(r1, MemOperand(sp, kPointerSize));
|
__ ldr(r1, MemOperand(sp, kPointerSize));
|
||||||
__ push(r1); // Constructor function.
|
__ push(r1); // function
|
||||||
__ push(r4); // Receiver.
|
__ push(r0); // receiver
|
||||||
|
|
||||||
// Reload the number of arguments from the stack.
|
// Reload the number of arguments from the stack.
|
||||||
// r1: constructor function
|
// r1: constructor function
|
||||||
@ -315,7 +194,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
|||||||
__ LeaveConstructFrame();
|
__ LeaveConstructFrame();
|
||||||
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
|
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
|
||||||
__ add(sp, sp, Operand(kPointerSize));
|
__ add(sp, sp, Operand(kPointerSize));
|
||||||
__ IncrementCounter(&Counters::constructed_objects, 1, r1, r2);
|
|
||||||
__ Jump(lr);
|
__ Jump(lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4950,7 +4950,7 @@ static void AllocateHeapNumber(
|
|||||||
Register scratch2) { // Another scratch register.
|
Register scratch2) { // Another scratch register.
|
||||||
// Allocate an object in the heap for the heap number and tag it as a heap
|
// Allocate an object in the heap for the heap number and tag it as a heap
|
||||||
// object.
|
// object.
|
||||||
__ AllocateObjectInNewSpace(HeapNumber::kSize / kPointerSize,
|
__ AllocateObjectInNewSpace(HeapNumber::kSize,
|
||||||
result,
|
result,
|
||||||
scratch1,
|
scratch1,
|
||||||
scratch2,
|
scratch2,
|
||||||
|
@ -790,7 +790,7 @@ void MacroAssembler::AllocateObjectInNewSpace(int object_size,
|
|||||||
ExternalReference::new_space_allocation_limit_address();
|
ExternalReference::new_space_allocation_limit_address();
|
||||||
mov(scratch2, Operand(new_space_allocation_limit));
|
mov(scratch2, Operand(new_space_allocation_limit));
|
||||||
ldr(scratch2, MemOperand(scratch2));
|
ldr(scratch2, MemOperand(scratch2));
|
||||||
add(result, result, Operand(object_size * kPointerSize));
|
add(result, result, Operand(object_size));
|
||||||
cmp(result, Operand(scratch2));
|
cmp(result, Operand(scratch2));
|
||||||
b(hi, gc_required);
|
b(hi, gc_required);
|
||||||
|
|
||||||
@ -799,84 +799,18 @@ void MacroAssembler::AllocateObjectInNewSpace(int object_size,
|
|||||||
|
|
||||||
// Tag and adjust back to start of new object.
|
// Tag and adjust back to start of new object.
|
||||||
if (tag_allocated_object) {
|
if (tag_allocated_object) {
|
||||||
sub(result, result, Operand((object_size * kPointerSize) -
|
sub(result, result, Operand(object_size - kHeapObjectTag));
|
||||||
kHeapObjectTag));
|
|
||||||
} else {
|
} else {
|
||||||
sub(result, result, Operand(object_size * kPointerSize));
|
sub(result, result, Operand(object_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::AllocateObjectInNewSpace(Register object_size,
|
|
||||||
Register result,
|
|
||||||
Register scratch1,
|
|
||||||
Register scratch2,
|
|
||||||
Label* gc_required,
|
|
||||||
bool tag_allocated_object) {
|
|
||||||
ASSERT(!result.is(scratch1));
|
|
||||||
ASSERT(!scratch1.is(scratch2));
|
|
||||||
|
|
||||||
// Load address of new object into result and allocation top address into
|
|
||||||
// scratch1.
|
|
||||||
ExternalReference new_space_allocation_top =
|
|
||||||
ExternalReference::new_space_allocation_top_address();
|
|
||||||
mov(scratch1, Operand(new_space_allocation_top));
|
|
||||||
ldr(result, MemOperand(scratch1));
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// get the number of bytes
|
|
||||||
ExternalReference new_space_allocation_limit =
|
|
||||||
ExternalReference::new_space_allocation_limit_address();
|
|
||||||
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));
|
|
||||||
add(result, result, Operand(kHeapObjectTag));
|
|
||||||
} else {
|
|
||||||
sub(result, result, Operand(object_size, LSL, kPointerSizeLog2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::UndoAllocationInNewSpace(Register object,
|
|
||||||
Register scratch) {
|
|
||||||
ExternalReference new_space_allocation_top =
|
|
||||||
ExternalReference::new_space_allocation_top_address();
|
|
||||||
|
|
||||||
// Make sure the object has no tag before resetting top.
|
|
||||||
and_(object, object, Operand(~kHeapObjectTagMask));
|
|
||||||
#ifdef DEBUG
|
|
||||||
mov(scratch, Operand(new_space_allocation_top));
|
|
||||||
ldr(scratch, MemOperand(scratch));
|
|
||||||
cmp(object, scratch);
|
|
||||||
Check(lt, "Undo allocation of non allocated memory");
|
|
||||||
#endif
|
|
||||||
str(object, MemOperand(scratch));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::CompareObjectType(Register function,
|
void MacroAssembler::CompareObjectType(Register function,
|
||||||
Register map,
|
Register map,
|
||||||
Register type_reg,
|
Register type_reg,
|
||||||
InstanceType type) {
|
InstanceType type) {
|
||||||
ldr(map, FieldMemOperand(function, HeapObject::kMapOffset));
|
ldr(map, FieldMemOperand(function, HeapObject::kMapOffset));
|
||||||
CompareInstanceType(map, type_reg, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::CompareInstanceType(Register map,
|
|
||||||
Register type_reg,
|
|
||||||
InstanceType type) {
|
|
||||||
ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
||||||
cmp(type_reg, Operand(type));
|
cmp(type_reg, Operand(type));
|
||||||
}
|
}
|
||||||
|
@ -190,28 +190,16 @@ class MacroAssembler: public Assembler {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Allocation support
|
// Allocation support
|
||||||
|
|
||||||
// Allocate an object in new space. The object_size is specified in words (not
|
// Allocate an object in new space. If the new space is exhausted control
|
||||||
// bytes). If the new space is exhausted control continues at the gc_required
|
// continues at the gc_required label. The allocated object is returned in
|
||||||
// label. The allocated object is returned in result. If the flag
|
// result. If the flag tag_allocated_object is true the result is tagged as
|
||||||
// tag_allocated_object is true the result is tagged as as a heap object.
|
// as a heap object.
|
||||||
void AllocateObjectInNewSpace(int object_size,
|
void AllocateObjectInNewSpace(int object_size,
|
||||||
Register result,
|
Register result,
|
||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Label* gc_required,
|
Label* gc_required,
|
||||||
bool tag_allocated_object);
|
bool tag_allocated_object);
|
||||||
void AllocateObjectInNewSpace(Register object_size,
|
|
||||||
Register result,
|
|
||||||
Register scratch1,
|
|
||||||
Register scratch2,
|
|
||||||
Label* gc_required,
|
|
||||||
bool tag_allocated_object);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// are left to the object(s) no longer allocated as they would be invalid when
|
|
||||||
// allocation is undone.
|
|
||||||
void UndoAllocationInNewSpace(Register object, Register scratch);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Support functions.
|
// Support functions.
|
||||||
@ -232,21 +220,12 @@ class MacroAssembler: public Assembler {
|
|||||||
// It leaves the map in the map register (unless the type_reg and map register
|
// It leaves the map in the map register (unless the type_reg and map register
|
||||||
// are the same register). It leaves the heap object in the heap_object
|
// are the same register). It leaves the heap object in the heap_object
|
||||||
// register unless the heap_object register is the same register as one of the
|
// register unless the heap_object register is the same register as one of the
|
||||||
// other registers.
|
// other // registers.
|
||||||
void CompareObjectType(Register heap_object,
|
void CompareObjectType(Register heap_object,
|
||||||
Register map,
|
Register map,
|
||||||
Register type_reg,
|
Register type_reg,
|
||||||
InstanceType type);
|
InstanceType type);
|
||||||
|
|
||||||
// Compare instance type in a map. map contains a valid map object whose
|
|
||||||
// object type should be compared with the given type. This both
|
|
||||||
// sets the flags and leaves the object type in the type_reg register. It
|
|
||||||
// leaves the heap object in the heap_object register unless the heap_object
|
|
||||||
// register is the same register as type_reg.
|
|
||||||
void CompareInstanceType(Register map,
|
|
||||||
Register type_reg,
|
|
||||||
InstanceType type);
|
|
||||||
|
|
||||||
inline void BranchOnSmi(Register value, Label* smi_label) {
|
inline void BranchOnSmi(Register value, Label* smi_label) {
|
||||||
tst(value, Operand(kSmiTagMask));
|
tst(value, Operand(kSmiTagMask));
|
||||||
b(eq, smi_label);
|
b(eq, smi_label);
|
||||||
|
@ -2891,12 +2891,8 @@ class Map: public HeapObject {
|
|||||||
|
|
||||||
// Byte offsets within kInstanceSizesOffset.
|
// Byte offsets within kInstanceSizesOffset.
|
||||||
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
|
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
|
||||||
static const int kInObjectPropertiesByte = 1;
|
static const int kInObjectPropertiesOffset = kInstanceSizesOffset + 1;
|
||||||
static const int kInObjectPropertiesOffset =
|
static const int kPreAllocatedPropertyFieldsOffset = kInstanceSizesOffset + 2;
|
||||||
kInstanceSizesOffset + kInObjectPropertiesByte;
|
|
||||||
static const int kPreAllocatedPropertyFieldsByte = 2;
|
|
||||||
static const int kPreAllocatedPropertyFieldsOffset =
|
|
||||||
kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
|
|
||||||
// The byte at position 3 is not in use at the moment.
|
// The byte at position 3 is not in use at the moment.
|
||||||
|
|
||||||
// Byte offsets within kInstanceAttributesOffset attributes.
|
// Byte offsets within kInstanceAttributesOffset attributes.
|
||||||
|
Loading…
Reference in New Issue
Block a user