From 14547ef434656085671b604d2185e33c9da05666 Mon Sep 17 00:00:00 2001 From: "antonm@chromium.org" Date: Mon, 15 Mar 2010 15:16:04 +0000 Subject: [PATCH] Just grow elements if they happen to be at the edge of new space. Review URL: http://codereview.chromium.org/945002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4133 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/stub-cache-ia32.cc | 48 ++++++++++++++++++++++++++++++++++++++++++--- test/mjsunit/array-push.js | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 902a5b8..e554a31 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -1251,7 +1251,8 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ j(not_equal, &miss); if (argc == 1) { // Otherwise fall through to call builtin. - Label call_builtin, exit, with_rset_update; + Label call_builtin, exit, with_rset_update, + attempt_to_grow_elements, finish_push; // Get the array's length into eax and calculate new length. __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); @@ -1263,9 +1264,9 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); __ SmiTag(ecx); - // Check if we could survive without allocation, go to builtin otherwise. + // Check if we could survive without allocation. __ cmp(eax, Operand(ecx)); - __ j(greater, &call_builtin); + __ j(greater, &attempt_to_grow_elements); // Save new length. __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); @@ -1277,6 +1278,8 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ mov(ecx, Operand(esp, argc * kPointerSize)); __ mov(Operand(edx, 0), ecx); + __ bind(&finish_push); + // Check if value is a smi. __ test(ecx, Immediate(kSmiTagMask)); __ j(not_zero, &with_rset_update); @@ -1292,6 +1295,45 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ CallStub(&stub); __ ret((argc + 1) * kPointerSize); + __ bind(&attempt_to_grow_elements); + ExternalReference new_space_allocation_top = + ExternalReference::new_space_allocation_top_address(); + ExternalReference new_space_allocation_limit = + ExternalReference::new_space_allocation_limit_address(); + + const int kAllocationDelta = 4; + // Load top. + __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); + + // Check if it's the end of elements. + __ lea(edx, FieldOperand(ebx, + eax, times_half_pointer_size, + FixedArray::kHeaderSize - argc * kPointerSize)); + __ cmp(edx, Operand(ecx)); + __ j(not_equal, &call_builtin); + __ add(Operand(ecx), Immediate(kAllocationDelta * kPointerSize)); + __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); + __ j(greater, &call_builtin); + + // We fit and could grow elements. + __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); + __ mov(ecx, Operand(esp, argc * kPointerSize)); + __ mov(Operand(edx, 0), ecx); + for (int i = 1; i < kAllocationDelta; i++) { + __ mov(Operand(edx, i * kPointerSize), + Immediate(Factory::undefined_value())); + } + + // Restore receiver to edx as finish sequence assumes it's here. + __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); + + // Increment element's and array's sizes. + __ add(FieldOperand(ebx, FixedArray::kLengthOffset), + Immediate(kAllocationDelta)); + __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); + + __ jmp(&finish_push); + __ bind(&call_builtin); } diff --git a/test/mjsunit/array-push.js b/test/mjsunit/array-push.js index a316833..baccf00 100644 --- a/test/mjsunit/array-push.js +++ b/test/mjsunit/array-push.js @@ -66,3 +66,40 @@ "after .push(22, 23, 24, 25, 26, 27, 28)"); } })(); + +// Excerises various pushes to the array at the end of new space. +(function() { + var a = undefined; + for (var i = 0; i < 7; i++) { + a = []; + assertEquals(1, a.push(1)); + assertEquals(2, a.push(2)); + assertEquals(3, a.push(3)); + assertEquals(4, a.push(4)); + assertEquals(5, a.push(5)); + assertEquals(6, a.push(6)); + assertEquals(7, a.push(7)); + assertEquals(8, a.push(8)); + assertEquals(9, a.push(9)); + assertEquals(10, a.push(10)); + assertEquals(11, a.push(11)); + assertEquals(12, a.push(12)); + assertEquals(13, a.push(13)); + assertEquals(14, a.push(14)); + assertEquals(15, a.push(15)); + assertEquals(16, a.push(16)); + assertEquals(17, a.push(17)); + assertEquals(18, a.push(18)); + assertEquals(19, a.push(19)); + assertEquals(20, a.push(20)); + assertEquals(21, a.push(21)); + assertEquals(22, a.push(22)); + assertEquals(23, a.push(23)); + assertEquals(24, a.push(24)); + assertEquals(25, a.push(25)); + assertEquals(26, a.push(26)); + assertEquals(27, a.push(27)); + assertEquals(28, a.push(28)); + assertEquals(29, a.push(29)); + } +})(); -- 2.7.4