| Index: src/x64/stub-cache-x64.cc
|
| ===================================================================
|
| --- src/x64/stub-cache-x64.cc (revision 2502)
|
| +++ src/x64/stub-cache-x64.cc (working copy)
|
| @@ -241,8 +241,69 @@
|
| JSGlobalPropertyCell* cell,
|
| JSFunction* function,
|
| String* name) {
|
| - // TODO(X64): Implement a real stub.
|
| - return Failure::InternalError();
|
| + // ----------- S t a t e -------------
|
| + // -----------------------------------
|
| + // rsp[0] return address
|
| + // rsp[8] argument argc
|
| + // rsp[16] argument argc - 1
|
| + // ...
|
| + // rsp[argc * 8] argument 1
|
| + // rsp[(argc + 1) * 8] argument 0 = receiver
|
| + // rsp[(argc + 2) * 8] function name
|
| + Label miss;
|
| +
|
| + __ IncrementCounter(&Counters::call_global_inline, 1);
|
| +
|
| + // Get the number of arguments.
|
| + const int argc = arguments().immediate();
|
| +
|
| + // Get the receiver from the stack.
|
| + __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
|
| +
|
| + // If the object is the holder then we know that it's a global
|
| + // object which can only happen for contextual calls. In this case,
|
| + // the receiver cannot be a smi.
|
| + if (object != holder) {
|
| + __ testl(rdx, Immediate(kSmiTagMask));
|
| + __ j(zero, &miss);
|
| + }
|
| +
|
| + // Check that the maps haven't changed.
|
| + CheckPrototypes(object, rdx, holder, rbx, rcx, name, &miss);
|
| +
|
| + // Get the value from the cell.
|
| + __ Move(rdi, Handle<JSGlobalPropertyCell>(cell));
|
| + __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset));
|
| +
|
| + // Check that the cell contains the same function.
|
| + __ Cmp(rdi, Handle<JSFunction>(function));
|
| + __ j(not_equal, &miss);
|
| +
|
| + // Patch the receiver on the stack with the global proxy.
|
| + if (object->IsGlobalObject()) {
|
| + __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
|
| + __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
|
| + }
|
| +
|
| + // Setup the context (function already in edi).
|
| + __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
| +
|
| + // Jump to the cached code (tail call).
|
| + ASSERT(function->is_compiled());
|
| + Handle<Code> code(function->code());
|
| + ParameterCount expected(function->shared()->formal_parameter_count());
|
| + __ InvokeCode(code, expected, arguments(),
|
| + RelocInfo::CODE_TARGET, JUMP_FUNCTION);
|
| +
|
| + // Handle call cache miss.
|
| + __ bind(&miss);
|
| + __ DecrementCounter(&Counters::call_global_inline, 1);
|
| + __ IncrementCounter(&Counters::call_global_inline_miss, 1);
|
| + Handle<Code> ic = ComputeCallMiss(arguments().immediate());
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(NORMAL, name);
|
| }
|
|
|
|
|
|
|