-void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
- if (object->IsGlobalObject()) {
- const int argc = arguments().immediate();
- const int receiver_offset = argc * kPointerSize;
- __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
- __ sw(a3, MemOperand(sp, receiver_offset));
- }
-}
-
-
-Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Name> name,
- CheckType check,
- Label* miss) {
- // ----------- S t a t e -------------
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
- GenerateNameCheck(name, miss);
-
- Register reg = a0;
-
- // Get the receiver from the stack.
- const int argc = arguments().immediate();
- const int receiver_offset = argc * kPointerSize;
- __ lw(a0, MemOperand(sp, receiver_offset));
-
- // Check that the receiver isn't a smi.
- if (check != NUMBER_CHECK) {
- __ JumpIfSmi(a0, miss);
- }
-
- // Make sure that it's okay not to patch the on stack receiver
- // unless we're doing a receiver map check.
- ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
- switch (check) {
- case RECEIVER_MAP_CHECK:
- __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3);
-
- // Check that the maps haven't changed.
- reg = CheckPrototypes(
- IC::CurrentTypeOf(object, isolate()),
- reg, holder, a1, a3, t0, name, miss);
- break;
-
- case STRING_CHECK: {
- // Check that the object is a string.
- __ GetObjectType(reg, a3, a3);
- __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::STRING_FUNCTION_INDEX, a1, miss);
- break;
- }
- case SYMBOL_CHECK: {
- // Check that the object is a symbol.
- __ GetObjectType(reg, a1, a3);
- __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE));
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss);
- break;
- }
- case NUMBER_CHECK: {
- Label fast;
- // Check that the object is a smi or a heap number.
- __ JumpIfSmi(reg, &fast);
- __ GetObjectType(reg, a3, a3);
- __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE));
- __ bind(&fast);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss);
- break;
- }
- case BOOLEAN_CHECK: {
- GenerateBooleanCheck(reg, miss);
-
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss);
- break;
- }
- }
-
- if (check != RECEIVER_MAP_CHECK) {
- Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
- reg = CheckPrototypes(
- IC::CurrentTypeOf(prototype, isolate()),
- a1, holder, a1, a3, t0, name, miss);
- }
-
- return reg;
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss) {
- ASSERT(function.is(a1));
- // Check that the function really is a function.
- GenerateFunctionCheck(function, a3, miss);
- PatchImplicitReceiver(object);
-
- // Invoke the function.
- __ InvokeFunction(a1, arguments(), JUMP_FUNCTION, NullCallWrapper());
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
- Handle<JSObject> holder,
- Handle<Name> name) {
- Label miss;
-
- GenerateNameCheck(name, &miss);
-
- // Get the number of arguments.
- const int argc = arguments().immediate();
- LookupResult lookup(isolate());
- LookupPostInterceptor(holder, name, &lookup);
-
- // Get the receiver from the stack.
- __ lw(a1, MemOperand(sp, argc * kPointerSize));
-
- CallInterceptorCompiler compiler(this, arguments(), a2);
- compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0,
- &miss);
-
- // Move returned value, the function to call, to a1.
- __ mov(a1, v0);
- // Restore receiver.
- __ lw(a0, MemOperand(sp, argc * kPointerSize));
-
- GenerateJumpFunction(object, a1, &miss);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(Code::FAST, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallGlobal(
- Handle<JSObject> object,
- Handle<GlobalObject> holder,
- Handle<PropertyCell> cell,
- Handle<JSFunction> function,
- Handle<Name> name) {
- if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(
- object, holder, cell, function, Handle<String>::cast(name),
- Code::NORMAL);
- // A null handle means bail out to the regular compiler code below.
- if (!code.is_null()) return code;
- }
-
- Label miss;
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- // Potentially loads a closure that matches the shared function info of the
- // function, rather than function.
- GenerateLoadFunctionFromCell(cell, function, &miss);
- Counters* counters = isolate()->counters();
- __ IncrementCounter(counters->call_global_inline(), 1, a3, t0);
- GenerateJumpFunction(object, a1, function);
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(Code::NORMAL, name);
-}
-
-