Index: src/ia32/stub-cache-ia32.cc |
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
index 2cda5201c5079aa121138bca3551b1d9786acecd..3c50f0d60449e6431363a4cee7c2ebf10459747e 100644 |
--- a/src/ia32/stub-cache-ia32.cc |
+++ b/src/ia32/stub-cache-ia32.cc |
@@ -1221,6 +1221,8 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
// -- ... |
// -- esp[(argc + 1) * 4] : receiver |
// ----------------------------------- |
+ ASSERT(check == RECEIVER_MAP_CHECK); |
+ |
Label miss; |
// Get the receiver from the stack. |
@@ -1229,7 +1231,7 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
// Check that the receiver isn't a smi. |
__ test(edx, Immediate(kSmiTagMask)); |
- __ j(zero, &miss, not_taken); |
+ __ j(zero, &miss); |
CheckPrototypes(JSObject::cast(object), edx, |
holder, ebx, |
@@ -1246,13 +1248,15 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
// Check that the elements are in fast mode (not dictionary). |
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
Immediate(Factory::fixed_array_map())); |
- __ j(not_equal, &miss, not_taken); |
+ __ j(not_equal, &miss); |
if (argc == 1) { // Otherwise fall through to call builtin. |
Label call_builtin, exit, with_rset_update; |
// Get the array's length into eax and calculate new length. |
__ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
+ STATIC_ASSERT(kSmiTagSize == 1); |
+ STATIC_ASSERT(kSmiTag == 0); |
__ add(Operand(eax), Immediate(argc << 1)); |
// Get the element's length into ecx. |
@@ -1310,6 +1314,90 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
} |
+Object* CallStubCompiler::CompileArrayPopCall(Object* object, |
+ JSObject* holder, |
+ JSFunction* function, |
+ String* name, |
+ CheckType check) { |
+ // ----------- S t a t e ------------- |
+ // -- ecx : name |
+ // -- esp[0] : return address |
+ // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
+ // -- ... |
+ // -- esp[(argc + 1) * 4] : receiver |
+ // ----------------------------------- |
+ ASSERT(check == RECEIVER_MAP_CHECK); |
+ |
+ Label miss, empty_array, call_builtin; |
+ |
+ // Get the receiver from the stack. |
+ const int argc = arguments().immediate(); |
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
+ |
+ // Check that the receiver isn't a smi. |
+ __ test(edx, Immediate(kSmiTagMask)); |
+ __ j(zero, &miss); |
+ |
+ CheckPrototypes(JSObject::cast(object), edx, |
+ holder, ebx, |
+ eax, name, &miss); |
+ |
+ // Get the elements array of the object. |
+ __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
+ |
+ // Check that the elements are in fast mode (not dictionary). |
+ __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
+ Immediate(Factory::fixed_array_map())); |
+ __ j(not_equal, &miss); |
+ |
+ // Get the array's length into ecx and calculate new length. |
+ __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); |
+ __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); |
+ __ j(negative, &empty_array); |
+ |
+ // Get the last element. |
+ STATIC_ASSERT(kSmiTagSize == 1); |
+ STATIC_ASSERT(kSmiTag == 0); |
+ __ mov(eax, FieldOperand(ebx, |
+ ecx, times_half_pointer_size, |
+ FixedArray::kHeaderSize)); |
+ __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); |
+ __ j(equal, &call_builtin); |
+ |
+ // Set the array's length. |
+ __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); |
+ |
+ // Fill with the hole. |
+ __ mov(FieldOperand(ebx, |
+ ecx, times_half_pointer_size, |
+ FixedArray::kHeaderSize), |
+ Immediate(Factory::the_hole_value())); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
+ __ bind(&empty_array); |
+ __ mov(eax, Immediate(Factory::undefined_value())); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
+ __ bind(&call_builtin); |
+ |
+ __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), |
+ argc + 1, |
+ 1); |
+ |
+ __ bind(&miss); |
+ |
+ Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
+ __ jmp(ic, RelocInfo::CODE_TARGET); |
+ |
+ // Return the generated code. |
+ String* function_name = NULL; |
+ if (function->shared()->name()->IsString()) { |
+ function_name = String::cast(function->shared()->name()); |
+ } |
+ return GetCode(CONSTANT_FUNCTION, function_name); |
+} |
+ |
+ |
Object* CallStubCompiler::CompileCallConstant(Object* object, |
JSObject* holder, |
JSFunction* function, |