Index: src/arm/builtins-arm.cc |
=================================================================== |
--- src/arm/builtins-arm.cc (revision 5500) |
+++ src/arm/builtins-arm.cc (working copy) |
@@ -521,7 +521,11 @@ |
static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
- bool is_api_function) { |
+ bool is_api_function, |
+ bool count_constructions) { |
+ // Should never count constructions for api objects. |
+ ASSERT(!is_api_function || !count_constructions); |
+ |
// Enter a construct frame. |
__ EnterConstructFrame(); |
@@ -530,9 +534,6 @@ |
__ push(r0); // Smi-tagged arguments count. |
__ push(r1); // Constructor function. |
- // Use r7 for holding undefined which is used in several places below. |
- __ 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; |
@@ -549,7 +550,6 @@ |
// Load the initial map and verify that it is in fact a map. |
// r1: constructor function |
- // r7: undefined value |
__ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
__ tst(r2, Operand(kSmiTagMask)); |
__ b(eq, &rt_call); |
@@ -561,14 +561,35 @@ |
// instance type would be JS_FUNCTION_TYPE. |
// r1: constructor function |
// r2: initial map |
- // r7: undefined value |
__ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); |
__ b(eq, &rt_call); |
+ if (count_constructions) { |
+ Label allocate; |
+ // Decrease generous allocation count. |
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
+ MemOperand constructor_count = |
+ FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); |
+ __ ldrb(r4, constructor_count); |
+ __ sub(r4, r4, Operand(1), SetCC); |
+ __ strb(r4, constructor_count); |
+ __ b(ne, &allocate); |
+ |
+ __ Push(r1, r2); |
+ |
+ __ push(r1); // constructor |
+ // The call will replace the stub, so the countdown is only done once. |
+ __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
+ |
+ __ pop(r2); |
+ __ pop(r1); |
+ |
+ __ bind(&allocate); |
+ } |
+ |
// Now allocate the JSObject on the heap. |
// r1: constructor function |
// r2: initial map |
- // r7: undefined value |
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); |
__ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); |
@@ -578,7 +599,6 @@ |
// r2: initial map |
// r3: object size |
// r4: JSObject (not tagged) |
- // r7: undefined value |
__ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
__ mov(r5, r4); |
ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
@@ -588,16 +608,21 @@ |
ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); |
__ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
- // Fill all the in-object properties with undefined. |
+ // Fill all the in-object properties with the appropriate filler. |
// 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 value |
__ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
{ Label loop, entry; |
+ if (count_constructions) { |
+ // To allow for truncation. |
+ __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); |
+ } else { |
+ __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
+ } |
__ b(&entry); |
__ bind(&loop); |
__ str(r7, MemOperand(r5, kPointerSize, PostIndex)); |
@@ -617,7 +642,6 @@ |
// r1: constructor function |
// r4: JSObject |
// r5: start of next object (not tagged) |
- // r7: undefined value |
__ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); |
// The field instance sizes contains both pre-allocated property fields and |
// in-object properties. |
@@ -637,7 +661,6 @@ |
// r3: number of elements in properties array |
// r4: JSObject |
// r5: start of next object |
- // r7: undefined value |
__ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); |
__ AllocateInNewSpace( |
r0, |
@@ -652,7 +675,6 @@ |
// r3: number of elements in properties array |
// r4: JSObject |
// r5: FixedArray (not tagged) |
- // r7: undefined value |
__ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); |
__ mov(r2, r5); |
ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
@@ -667,10 +689,16 @@ |
// 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; |
+ if (count_constructions) { |
+ __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
+ } else if (FLAG_debug_code) { |
+ __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
+ __ cmp(r7, r8); |
+ __ Assert(eq, "Undefined value not loaded."); |
+ } |
__ b(&entry); |
__ bind(&loop); |
__ str(r7, MemOperand(r2, kPointerSize, PostIndex)); |
@@ -822,13 +850,18 @@ |
} |
+void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
+ Generate_JSConstructStubHelper(masm, false, true); |
+} |
+ |
+ |
void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
- Generate_JSConstructStubHelper(masm, false); |
+ Generate_JSConstructStubHelper(masm, false, false); |
} |
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
- Generate_JSConstructStubHelper(masm, true); |
+ Generate_JSConstructStubHelper(masm, true, false); |
} |