X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fv8%2Fsrc%2Fmips%2Fstub-cache-mips.cc;h=d1b428a34560d41a0d7c55f96e383423c26b4fdf;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=ef98db59bb8288a52e746dbb9d0a79c9456a5acf;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/v8/src/mips/stub-cache-mips.cc b/src/v8/src/mips/stub-cache-mips.cc index ef98db5..d1b428a 100644 --- a/src/v8/src/mips/stub-cache-mips.cc +++ b/src/v8/src/mips/stub-cache-mips.cc @@ -287,15 +287,19 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( Register prototype, Label* miss) { Isolate* isolate = masm->isolate(); - // Check we're still in the same context. - __ lw(prototype, - MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); - ASSERT(!prototype.is(at)); - __ li(at, isolate->global_object()); - __ Branch(miss, ne, prototype, Operand(at)); // Get the global function with the given index. Handle function( JSFunction::cast(isolate->native_context()->get(index))); + + // Check we're still in the same context. + Register scratch = prototype; + const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); + __ lw(scratch, MemOperand(cp, offset)); + __ lw(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); + __ lw(scratch, MemOperand(scratch, Context::SlotOffset(index))); + __ li(at, function); + __ Branch(miss, ne, at, Operand(scratch)); + // Load its initial map. The global functions all have initial maps. __ li(prototype, Handle(function->initial_map())); // Load the prototype from the initial map. @@ -765,376 +769,83 @@ static void CompileCallLoadPropertyWithInterceptor( } -static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; - - -static void GenerateFastApiCallBody(MacroAssembler* masm, - const CallOptimization& optimization, - int argc, - Register holder, - Register scratch1, - Register scratch2, - Register scratch3, - bool restore_context) { - // ----------- S t a t e ------------- - // -- sp[0] : last JS argument - // -- ... - // -- sp[(argc - 1) * 4] : first JS argument - // -- sp[argc * 4] : receiver - // ----------------------------------- - ASSERT(optimization.is_simple_api_call()); - - typedef FunctionCallbackArguments FCA; - - STATIC_ASSERT(FCA::kHolderIndex == 0); - STATIC_ASSERT(FCA::kIsolateIndex == 1); - STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); - STATIC_ASSERT(FCA::kReturnValueOffset == 3); - STATIC_ASSERT(FCA::kDataIndex == 4); - STATIC_ASSERT(FCA::kCalleeIndex == 5); - STATIC_ASSERT(FCA::kContextSaveIndex == 6); - STATIC_ASSERT(FCA::kArgsLength == 7); - - ASSERT(!holder.is(cp)); - - // Save calling context. - __ push(cp); - // Get the function and setup the context. - Handle function = optimization.constant_function(); - __ li(scratch1, function); - __ lw(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset)); - __ push(scratch1); - - // Construct the FunctionCallbackInfo. - Handle api_call_info = optimization.api_call_info(); - Handle call_data(api_call_info->data(), masm->isolate()); - bool call_data_undefined = false; - if (masm->isolate()->heap()->InNewSpace(*call_data)) { - __ li(scratch1, api_call_info); - __ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); - } else if (call_data->IsUndefined()) { - call_data_undefined = true; - __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); - } else { - __ li(scratch1, call_data); - } - // Store call data. - __ push(scratch1); - if (!call_data_undefined) { - __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); - } - // Store ReturnValue default and ReturnValue. - __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); - __ Push(scratch1, scratch1); - // Store isolate. - __ li(scratch1, Operand(ExternalReference::isolate_address(masm->isolate()))); - __ push(scratch1); - // Store holder. - __ push(holder); - - // Prepare arguments. - __ Move(a2, sp); - - // Allocate the v8::Arguments structure in the arguments' space since - // it's not controlled by GC. - const int kApiStackSpace = 4; - - FrameScope frame_scope(masm, StackFrame::MANUAL); - __ EnterExitFrame(false, kApiStackSpace); - - // a0 = FunctionCallbackInfo& - // Arguments is built at sp + 1 (sp is a reserved spot for ra). - __ Addu(a0, sp, kPointerSize); - // FunctionCallbackInfo::implicit_args_ - __ sw(a2, MemOperand(a0, 0 * kPointerSize)); - // FunctionCallbackInfo::values_ - __ Addu(t0, a2, Operand((kFastApiCallArguments - 1 + argc) * kPointerSize)); - __ sw(t0, MemOperand(a0, 1 * kPointerSize)); - // FunctionCallbackInfo::length_ = argc - __ li(t0, Operand(argc)); - __ sw(t0, MemOperand(a0, 2 * kPointerSize)); - // FunctionCallbackInfo::is_construct_call = 0 - __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize)); - - const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; - Address function_address = v8::ToCData
(api_call_info->callback()); - ApiFunction fun(function_address); - ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; - ExternalReference ref = - ExternalReference(&fun, - type, - masm->isolate()); - Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); - ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; - ApiFunction thunk_fun(thunk_address); - ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, - masm->isolate()); - - AllowExternalCallThatCantCauseGC scope(masm); - MemOperand context_restore_operand( - fp, (2 + FCA::kContextSaveIndex) * kPointerSize); - MemOperand return_value_operand( - fp, (2 + FCA::kReturnValueOffset) * kPointerSize); - - __ CallApiFunctionAndReturn(ref, - function_address, - thunk_ref, - a1, - kStackUnwindSpace, - return_value_operand, - restore_context ? - &context_restore_operand : NULL); -} - - -// Generates call to API function. -static void GenerateFastApiCall(MacroAssembler* masm, - const CallOptimization& optimization, - int argc, - Handle map_to_holder, - CallOptimization::HolderLookup holder_lookup) { - Counters* counters = masm->isolate()->counters(); - __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1); - - // Move holder to a register. - Register holder_reg = a0; - switch (holder_lookup) { - case CallOptimization::kHolderIsReceiver: - { - ASSERT(map_to_holder.is_null()); - __ lw(holder_reg, MemOperand(sp, argc * kPointerSize)); - } - break; - case CallOptimization::kHolderIsPrototypeOfMap: - { - Handle holder(JSObject::cast(map_to_holder->prototype())); - if (!masm->isolate()->heap()->InNewSpace(*holder)) { - __ li(holder_reg, holder); - } else { - __ li(holder_reg, map_to_holder); - __ lw(holder_reg, - FieldMemOperand(holder_reg, Map::kPrototypeOffset)); - } - } - break; - case CallOptimization::kHolderNotFound: - UNREACHABLE(); - } - GenerateFastApiCallBody(masm, - optimization, - argc, - holder_reg, - a1, - a2, - a3, - false); -} - - // Generate call to api function. static void GenerateFastApiCall(MacroAssembler* masm, const CallOptimization& optimization, + Handle receiver_map, Register receiver, - Register scratch, + Register scratch_in, int argc, Register* values) { - ASSERT(!receiver.is(scratch)); - __ push(receiver); + ASSERT(!receiver.is(scratch_in)); + // Preparing to push, adjust sp. + __ Subu(sp, sp, Operand((argc + 1) * kPointerSize)); + __ sw(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. // Write the arguments to stack frame. for (int i = 0; i < argc; i++) { Register arg = values[argc-1-i]; ASSERT(!receiver.is(arg)); - ASSERT(!scratch.is(arg)); - __ push(arg); - } - - Register scratch1 = a0; - Register scratch2 = a1; - Register scratch3 = a2; - if (!a3.is(receiver)) { - __ mov(a3, receiver); - receiver = a3; + ASSERT(!scratch_in.is(arg)); + __ sw(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. } - // Stack now matches JSFunction abi. - GenerateFastApiCallBody(masm, - optimization, - argc, - receiver, - scratch1, - scratch2, - scratch3, - true); -} - - -class CallInterceptorCompiler BASE_EMBEDDED { - public: - CallInterceptorCompiler(CallStubCompiler* stub_compiler, - const ParameterCount& arguments, - Register name) - : stub_compiler_(stub_compiler), - arguments_(arguments), - name_(name) {} - - void Compile(MacroAssembler* masm, - Handle object, - Handle holder, - Handle name, - LookupResult* lookup, - Register receiver, - Register scratch1, - Register scratch2, - Register scratch3, - Label* miss) { - ASSERT(holder->HasNamedInterceptor()); - ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); - - // Check that the receiver isn't a smi. - __ JumpIfSmi(receiver, miss); - CallOptimization optimization(lookup); - if (optimization.is_constant_call()) { - CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, - holder, lookup, name, optimization, miss); - } else { - CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, - name, holder, miss); - } - } - - private: - void CompileCacheable(MacroAssembler* masm, - Handle object, - Register receiver, - Register scratch1, - Register scratch2, - Register scratch3, - Handle interceptor_holder, - LookupResult* lookup, - Handle name, - const CallOptimization& optimization, - Label* miss_label) { - ASSERT(optimization.is_constant_call()); - ASSERT(!lookup->holder()->IsGlobalObject()); - Counters* counters = masm->isolate()->counters(); - __ IncrementCounter(counters->call_const_interceptor(), 1, - scratch1, scratch2); - - // Check that the maps from receiver to interceptor's holder - // haven't changed and thus we can invoke interceptor. - Label miss_cleanup; - Register holder = - stub_compiler_->CheckPrototypes( - IC::CurrentTypeOf(object, masm->isolate()), receiver, - interceptor_holder, scratch1, scratch2, scratch3, - name, miss_label); - - // Invoke an interceptor and if it provides a value, - // branch to |regular_invoke|. - Label regular_invoke; - LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, - ®ular_invoke); - - // Interceptor returned nothing for this property. Try to use cached - // constant function. - - // Check that the maps from interceptor's holder to constant function's - // holder haven't changed and thus we can use cached constant function. - if (*interceptor_holder != lookup->holder()) { - stub_compiler_->CheckPrototypes( - IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, - handle(lookup->holder()), scratch1, scratch2, scratch3, - name, miss_label); - } - - Handle lookup_map; - CallOptimization::HolderLookup holder_lookup = - CallOptimization::kHolderNotFound; - if (optimization.is_simple_api_call() && - !lookup->holder()->IsGlobalObject()) { - lookup_map = optimization.LookupHolderOfExpectedType( - object, object, interceptor_holder, &holder_lookup); - if (holder_lookup == CallOptimization::kHolderNotFound) { - lookup_map = - optimization.LookupHolderOfExpectedType( - object, - interceptor_holder, - Handle(lookup->holder()), - &holder_lookup); - } - } - - // Invoke function. - if (holder_lookup != CallOptimization::kHolderNotFound) { - int argc = arguments_.immediate(); - GenerateFastApiCall(masm, - optimization, - argc, - lookup_map, - holder_lookup); - } else { - Handle function = optimization.constant_function(); - __ Move(a0, receiver); - stub_compiler_->GenerateJumpFunction(object, function); - } + ASSERT(optimization.is_simple_api_call()); - // Invoke a regular function. - __ bind(®ular_invoke); + // Abi for CallApiFunctionStub. + Register callee = a0; + Register call_data = t0; + Register holder = a2; + Register api_function_address = a1; + + // Put holder in place. + CallOptimization::HolderLookup holder_lookup; + Handle api_holder = optimization.LookupHolderOfExpectedType( + receiver_map, + &holder_lookup); + switch (holder_lookup) { + case CallOptimization::kHolderIsReceiver: + __ Move(holder, receiver); + break; + case CallOptimization::kHolderFound: + __ li(holder, api_holder); + break; + case CallOptimization::kHolderNotFound: + UNREACHABLE(); + break; } - void CompileRegular(MacroAssembler* masm, - Handle object, - Register receiver, - Register scratch1, - Register scratch2, - Register scratch3, - Handle name, - Handle interceptor_holder, - Label* miss_label) { - Register holder = - stub_compiler_->CheckPrototypes( - IC::CurrentTypeOf(object, masm->isolate()), receiver, - interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); - - // Call a runtime function to load the interceptor property. - FrameScope scope(masm, StackFrame::INTERNAL); - // Save the name_ register across the call. - __ push(name_); - - CompileCallLoadPropertyWithInterceptor( - masm, receiver, holder, name_, interceptor_holder, - IC::kLoadPropertyWithInterceptorForCall); - - // Restore the name_ register. - __ pop(name_); - // Leave the internal frame. - } + Isolate* isolate = masm->isolate(); + Handle function = optimization.constant_function(); + Handle api_call_info = optimization.api_call_info(); + Handle call_data_obj(api_call_info->data(), isolate); - void LoadWithInterceptor(MacroAssembler* masm, - Register receiver, - Register holder, - Handle holder_obj, - Register scratch, - Label* interceptor_succeeded) { - { - FrameScope scope(masm, StackFrame::INTERNAL); + // Put callee in place. + __ li(callee, function); - __ Push(receiver, holder, name_); - CompileCallLoadPropertyWithInterceptor( - masm, receiver, holder, name_, holder_obj, - IC::kLoadPropertyWithInterceptorOnly); - __ pop(name_); - __ pop(holder); - __ pop(receiver); - } - // If interceptor returns no-result sentinel, call the constant function. - __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); - __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); + bool call_data_undefined = false; + // Put call_data in place. + if (isolate->heap()->InNewSpace(*call_data_obj)) { + __ li(call_data, api_call_info); + __ lw(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); + } else if (call_data_obj->IsUndefined()) { + call_data_undefined = true; + __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); + } else { + __ li(call_data, call_data_obj); } + // Put api_function_address in place. + Address function_address = v8::ToCData
(api_call_info->callback()); + ApiFunction fun(function_address); + ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; + ExternalReference ref = + ExternalReference(&fun, + type, + masm->isolate()); + __ li(api_function_address, Operand(ref)); - CallStubCompiler* stub_compiler_; - const ParameterCount& arguments_; - Register name_; -}; + // Jump to stub. + CallApiFunctionStub stub(true, call_data_undefined, argc); + __ TailCallStub(&stub); +} void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle code) { @@ -1353,9 +1064,11 @@ void LoadStubCompiler::GenerateLoadConstant(Handle value) { void LoadStubCompiler::GenerateLoadCallback( - const CallOptimization& call_optimization) { + const CallOptimization& call_optimization, + Handle receiver_map) { GenerateFastApiCall( - masm(), call_optimization, receiver(), scratch3(), 0, NULL); + masm(), call_optimization, receiver_map, + receiver(), scratch3(), 0, NULL); } @@ -1395,37 +1108,17 @@ void LoadStubCompiler::GenerateLoadCallback( __ Addu(scratch2(), sp, 1 * kPointerSize); __ mov(a2, scratch2()); // Saved in case scratch2 == a1. - __ mov(a0, sp); // (first argument - a0) = Handle + // Abi for CallApiGetter. + Register getter_address_reg = a2; - const int kApiStackSpace = 1; - FrameScope frame_scope(masm(), StackFrame::MANUAL); - __ EnterExitFrame(false, kApiStackSpace); - - // Create PropertyAccessorInfo instance on the stack above the exit frame with - // scratch2 (internal::Object** args_) as the data. - __ sw(a2, MemOperand(sp, kPointerSize)); - // (second argument - a1) = AccessorInfo& - __ Addu(a1, sp, kPointerSize); - - const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1; Address getter_address = v8::ToCData
(callback->getter()); ApiFunction fun(getter_address); ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; ExternalReference ref = ExternalReference(&fun, type, isolate()); + __ li(getter_address_reg, Operand(ref)); - Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); - ExternalReference::Type thunk_type = - ExternalReference::PROFILING_GETTER_CALL; - ApiFunction thunk_fun(thunk_address); - ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, - isolate()); - __ CallApiFunctionAndReturn(ref, - getter_address, - thunk_ref, - a2, - kStackUnwindSpace, - MemOperand(fp, 6 * kPointerSize), - NULL); + CallApiGetterStub stub; + __ TailCallStub(&stub); } @@ -1514,129 +1207,6 @@ void LoadStubCompiler::GenerateLoadInterceptor( } -void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { - if (kind_ == Code::KEYED_CALL_IC) { - __ Branch(miss, ne, a2, Operand(name)); - } -} - - -void CallStubCompiler::GenerateFunctionCheck(Register function, - Register scratch, - Label* miss) { - __ JumpIfSmi(function, miss); - __ GetObjectType(function, scratch, scratch); - __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); -} - - -void CallStubCompiler::GenerateLoadFunctionFromCell( - Handle cell, - Handle function, - Label* miss) { - // Get the value from the cell. - __ li(a3, Operand(cell)); - __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); - - // Check that the cell contains the same function. - if (heap()->InNewSpace(*function)) { - // We can't embed a pointer to a function in new space so we have - // to verify that the shared function info is unchanged. This has - // the nice side effect that multiple closures based on the same - // function can all use this call IC. Before we load through the - // function, we have to verify that it still is a function. - GenerateFunctionCheck(a1, a3, miss); - - // Check the shared function info. Make sure it hasn't changed. - __ li(a3, Handle(function->shared())); - __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); - __ Branch(miss, ne, t0, Operand(a3)); - } else { - __ Branch(miss, ne, a1, Operand(function)); - } -} - - -void CallStubCompiler::GenerateMissBranch() { - Handle code = - isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), - kind_, - extra_state()); - __ Jump(code, RelocInfo::CODE_TARGET); -} - - -Handle CallStubCompiler::CompileCallField(Handle object, - Handle holder, - PropertyIndex index, - Handle name) { - Label miss; - - Register reg = HandlerFrontendHeader( - object, holder, name, RECEIVER_MAP_CHECK, &miss); - GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), - index.translate(holder), Representation::Tagged()); - GenerateJumpFunction(object, a1, &miss); - - HandlerFrontendFooter(&miss); - - // Return the generated code. - return GetCode(Code::FAST, name); -} - - -Handle CallStubCompiler::CompileFastApiCall( - const CallOptimization& optimization, - Handle object, - Handle holder, - Handle cell, - Handle function, - Handle name) { - - Counters* counters = isolate()->counters(); - - ASSERT(optimization.is_simple_api_call()); - // Bail out if object is a global object as we don't want to - // repatch it to global receiver. - if (object->IsGlobalObject()) return Handle::null(); - if (!cell.is_null()) return Handle::null(); - if (!object->IsJSObject()) return Handle::null(); - Handle receiver = Handle::cast(object); - CallOptimization::HolderLookup holder_lookup = - CallOptimization::kHolderNotFound; - Handle lookup_map = optimization.LookupHolderOfExpectedType( - receiver, receiver, holder, &holder_lookup); - if (holder_lookup == CallOptimization::kHolderNotFound) { - return Handle::null(); - } - - Label miss; - GenerateNameCheck(name, &miss); - - // Get the receiver from the stack. - const int argc = arguments().immediate(); - __ lw(a1, MemOperand(sp, argc * kPointerSize)); - - // Check that the receiver isn't a smi. - __ JumpIfSmi(a1, &miss); - - __ IncrementCounter(counters->call_const(), 1, a0, a3); - - // Check that the maps haven't changed and find a Holder as a side effect. - CheckPrototypes( - IC::CurrentTypeOf(object, isolate()), - a1, holder, a0, a3, t0, name, &miss); - - GenerateFastApiCall( - masm(), optimization, argc, lookup_map, holder_lookup); - - HandlerFrontendFooter(&miss); - - // Return the generated code. - return GetCode(function); -} - - void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { Label success; // Check that the object is a boolean. @@ -1648,178 +1218,6 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { } -void CallStubCompiler::PatchImplicitReceiver(Handle 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, - Handle holder, - Handle 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 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, - 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 CallStubCompiler::CompileCallInterceptor(Handle object, - Handle holder, - Handle 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 CallStubCompiler::CompileCallGlobal( - Handle object, - Handle holder, - Handle cell, - Handle function, - Handle name) { - if (HasCustomCallGenerator(function)) { - Handle code = CompileCustomCall( - object, holder, cell, function, Handle::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); -} - - Handle StoreStubCompiler::CompileStoreCallback( Handle object, Handle holder, @@ -1832,8 +1230,7 @@ Handle StoreStubCompiler::CompileStoreCallback( // checks. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); - __ push(receiver()); // Receiver. - __ push(holder_reg); + __ Push(receiver(), holder_reg); // Receiver. __ li(at, Operand(callback)); // Callback info. __ push(at); __ li(at, Operand(name)); @@ -1859,7 +1256,8 @@ Handle StoreStubCompiler::CompileStoreCallback( Register values[] = { value() }; GenerateFastApiCall( - masm(), call_optimization, receiver(), scratch3(), 1, values); + masm(), call_optimization, handle(object->map()), + receiver(), scratch3(), 1, values); // Return the generated code. return GetCode(kind(), Code::FAST, name); @@ -1872,6 +1270,7 @@ Handle StoreStubCompiler::CompileStoreCallback( void StoreStubCompiler::GenerateStoreViaSetter( MacroAssembler* masm, + Handle type, Handle setter) { // ----------- S t a t e ------------- // -- a0 : value @@ -1881,14 +1280,21 @@ void StoreStubCompiler::GenerateStoreViaSetter( // ----------------------------------- { FrameScope scope(masm, StackFrame::INTERNAL); + Register receiver = a1; + Register value = a0; // Save value register, so we can restore it later. - __ push(a0); + __ push(value); if (!setter.is_null()) { // Call the JavaScript setter with receiver and value on the stack. - __ push(a1); - __ push(a0); + if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { + // Swap in the global receiver. + __ lw(receiver, + FieldMemOperand( + receiver, JSGlobalObject::kGlobalReceiverOffset)); + } + __ Push(receiver, value); ParameterCount actual(1); ParameterCount expected(setter); __ InvokeFunction(setter, expected, actual, @@ -1994,6 +1400,7 @@ Register* KeyedStoreStubCompiler::registers() { void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, + Handle type, Register receiver, Handle getter) { // ----------- S t a t e ------------- @@ -2006,6 +1413,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, if (!getter.is_null()) { // Call the JavaScript getter with the receiver on the stack. + if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { + // Swap in the global receiver. + __ lw(receiver, + FieldMemOperand( + receiver, JSGlobalObject::kGlobalReceiverOffset)); + } __ push(receiver); ParameterCount actual(0); ParameterCount expected(getter); @@ -2048,13 +1461,13 @@ Handle LoadStubCompiler::CompileLoadGlobal( __ Branch(&miss, eq, t0, Operand(at)); } - HandlerFrontendFooter(name, &miss); - Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); __ Ret(USE_DELAY_SLOT); __ mov(v0, t0); + HandlerFrontendFooter(name, &miss); + // Return the generated code. return GetCode(kind(), Code::NORMAL, name); } @@ -2074,10 +1487,11 @@ Handle BaseLoadStoreStubCompiler::CompilePolymorphicIC( } Label number_case; + Register match = scratch1(); Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; - __ JumpIfSmi(receiver(), smi_target); + __ JumpIfSmi(receiver(), smi_target, match); // Reg match is 0 if Smi. - Register map_reg = scratch1(); + Register map_reg = scratch2(); int receiver_count = types->length(); int number_of_handled_maps = 0; @@ -2087,12 +1501,15 @@ Handle BaseLoadStoreStubCompiler::CompilePolymorphicIC( Handle map = IC::TypeToMap(*type, isolate()); if (!map->is_deprecated()) { number_of_handled_maps++; + // Check map and tail call if there's a match. + // Separate compare from branch, to provide path for above JumpIfSmi(). + __ Subu(match, map_reg, Operand(map)); if (type->Is(HeapType::Number())) { ASSERT(!number_case.is_unused()); __ bind(&number_case); } __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, - eq, map_reg, Operand(map)); + eq, match, Operand(zero_reg)); } } ASSERT(number_of_handled_maps != 0);