| Index: src/ia32/stub-cache-ia32.cc
|
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
|
| index 697a71fd38f99b04f9d1b2f7605d60280e20ac37..2cda5201c5079aa121138bca3551b1d9786acecd 100644
|
| --- a/src/ia32/stub-cache-ia32.cc
|
| +++ b/src/ia32/stub-cache-ia32.cc
|
| @@ -549,9 +549,8 @@ class CallOptimization BASE_EMBEDDED {
|
| // fast api call builtin.
|
| void AnalyzePossibleApiFunction(JSFunction* function) {
|
| SharedFunctionInfo* sfi = function->shared();
|
| - if (sfi->function_data()->IsUndefined()) return;
|
| - FunctionTemplateInfo* info =
|
| - FunctionTemplateInfo::cast(sfi->function_data());
|
| + if (!sfi->IsApiFunction()) return;
|
| + FunctionTemplateInfo* info = sfi->get_api_func_data();
|
|
|
| // Require a C++ callback.
|
| if (info->call_code()->IsUndefined()) return;
|
| @@ -1210,6 +1209,107 @@ Object* CallStubCompiler::CompileCallField(JSObject* object,
|
| }
|
|
|
|
|
| +Object* CallStubCompiler::CompileArrayPushCall(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
|
| + // -----------------------------------
|
| + Label miss;
|
| +
|
| + // 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, not_taken);
|
| +
|
| + CheckPrototypes(JSObject::cast(object), edx,
|
| + holder, ebx,
|
| + eax, name, &miss);
|
| +
|
| + if (argc == 0) {
|
| + // Noop, return the length.
|
| + __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
|
| + __ ret((argc + 1) * kPointerSize);
|
| + } else {
|
| + // 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, not_taken);
|
| +
|
| + 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));
|
| + __ add(Operand(eax), Immediate(argc << 1));
|
| +
|
| + // Get the element's length into ecx.
|
| + __ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
|
| + __ SmiTag(ecx);
|
| +
|
| + // Check if we could survive without allocation, go to builtin otherwise.
|
| + __ cmp(eax, Operand(ecx));
|
| + __ j(greater, &call_builtin);
|
| +
|
| + // Save new length.
|
| + __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
|
| +
|
| + // Push the element.
|
| + __ lea(edx, FieldOperand(ebx,
|
| + eax, times_half_pointer_size,
|
| + FixedArray::kHeaderSize - argc * kPointerSize));
|
| + __ mov(ecx, Operand(esp, argc * kPointerSize));
|
| + __ mov(Operand(edx, 0), ecx);
|
| +
|
| + // Check if wrote not a smi.
|
| + __ test(ecx, Immediate(kSmiTagMask));
|
| + __ j(not_zero, &with_rset_update);
|
| +
|
| + __ bind(&exit);
|
| + __ ret((argc + 1) * kPointerSize);
|
| +
|
| + __ bind(&with_rset_update);
|
| +
|
| + __ InNewSpace(ebx, ecx, equal, &exit);
|
| +
|
| + RecordWriteStub stub(ebx, edx, ecx);
|
| + __ CallStub(&stub);
|
| + __ ret((argc + 1) * kPointerSize);
|
| +
|
| + __ bind(&call_builtin);
|
| + }
|
| +
|
| + __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
|
| + 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,
|
| @@ -1222,6 +1322,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
|
| // -- ...
|
| // -- esp[(argc + 1) * 4] : receiver
|
| // -----------------------------------
|
| +
|
| + SharedFunctionInfo* function_info = function->shared();
|
| + if (function_info->HasCustomCallGenerator()) {
|
| + CustomCallGenerator generator =
|
| + ToCData<CustomCallGenerator>(function_info->function_data());
|
| + return generator(this, object, holder, function, name, check);
|
| + }
|
| +
|
| Label miss_in_smi_check;
|
|
|
| // Get the receiver from the stack.
|
|
|