From: dcarney@chromium.org Date: Mon, 3 Feb 2014 15:19:38 +0000 (+0000) Subject: let load and store api callbacks use global proxy as receiver X-Git-Tag: upstream/4.7.83~10903 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ef2ca4ac09fae95ed8ab4ceffa8739c1bdd35047;p=platform%2Fupstream%2Fv8.git let load and store api callbacks use global proxy as receiver R=verwaest@chromium.org BUG= Review URL: https://codereview.chromium.org/151063003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19033 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 9951659..ca63052 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -782,11 +782,23 @@ static void CompileCallLoadPropertyWithInterceptor( } -static void GenerateFastApiCallBody(MacroAssembler* masm, - const CallOptimization& optimization, - int argc, - Register holder_in, - bool restore_context) { +// Generate call to api function. +static void GenerateFastApiCall(MacroAssembler* masm, + const CallOptimization& optimization, + Handle receiver_map, + Register receiver, + Register scratch_in, + int argc, + Register* values) { + ASSERT(!receiver.is(scratch_in)); + __ 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_in.is(arg)); + __ push(arg); + } ASSERT(optimization.is_simple_api_call()); // Abi for CallApiFunctionStub. @@ -796,7 +808,21 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, Register api_function_address = r1; // Put holder in place. - __ Move(holder, holder_in); + 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: + __ Move(holder, api_holder); + break; + case CallOptimization::kHolderNotFound: + UNREACHABLE(); + break; + } Isolate* isolate = masm->isolate(); Handle function = optimization.constant_function(); @@ -828,36 +854,11 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, __ mov(api_function_address, Operand(ref)); // Jump to stub. - CallApiFunctionStub stub(restore_context, call_data_undefined, argc); + CallApiFunctionStub stub(true, call_data_undefined, argc); __ TailCallStub(&stub); } -// Generate call to api function. -static void GenerateFastApiCall(MacroAssembler* masm, - const CallOptimization& optimization, - Register receiver, - Register scratch, - int argc, - Register* values) { - ASSERT(!receiver.is(scratch)); - __ 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); - } - // Stack now matches JSFunction abi. - GenerateFastApiCallBody(masm, - optimization, - argc, - receiver, - true); -} - - void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle code) { __ Jump(code, RelocInfo::CODE_TARGET); } @@ -1075,9 +1076,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); } @@ -1267,7 +1270,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); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index d12e682..f91cee2 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -418,11 +418,30 @@ static void CompileCallLoadPropertyWithInterceptor( } -static void GenerateFastApiCallBody(MacroAssembler* masm, - const CallOptimization& optimization, - int argc, - Register holder_in, - bool restore_context) { +// Generate call to api function. +// This function uses push() to generate smaller, faster code than +// the version above. It is an optimization that should will be removed +// when api call ICs are generated in hydrogen. +static void GenerateFastApiCall(MacroAssembler* masm, + const CallOptimization& optimization, + Handle receiver_map, + Register receiver, + Register scratch_in, + int argc, + Register* values) { + // Copy return value. + __ pop(scratch_in); + // receiver + __ 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_in.is(arg)); + __ push(arg); + } + __ push(scratch_in); + // Stack now matches JSFunction abi. ASSERT(optimization.is_simple_api_call()); // Abi for CallApiFunctionStub. @@ -430,11 +449,24 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, Register call_data = ebx; Register holder = ecx; Register api_function_address = edx; + Register scratch = edi; // scratch_in is no longer valid. // Put holder in place. - __ Move(holder, holder_in); - - Register scratch = edi; + 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: + __ LoadHeapObject(holder, api_holder); + break; + case CallOptimization::kHolderNotFound: + UNREACHABLE(); + break; + } Isolate* isolate = masm->isolate(); Handle function = optimization.constant_function(); @@ -461,42 +493,11 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, __ mov(api_function_address, Immediate(function_address)); // Jump to stub. - CallApiFunctionStub stub(restore_context, call_data_undefined, argc); + CallApiFunctionStub stub(true, call_data_undefined, argc); __ TailCallStub(&stub); } -// Generate call to api function. -// This function uses push() to generate smaller, faster code than -// the version above. It is an optimization that should will be removed -// when api call ICs are generated in hydrogen. -static void GenerateFastApiCall(MacroAssembler* masm, - const CallOptimization& optimization, - Register receiver, - Register scratch1, - int argc, - Register* values) { - // Copy return value. - __ pop(scratch1); - // receiver - __ 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(!scratch1.is(arg)); - __ push(arg); - } - __ push(scratch1); - // Stack now matches JSFunction abi. - GenerateFastApiCallBody(masm, - optimization, - argc, - receiver, - true); -} - - void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, Label* label, Handle name) { @@ -1065,10 +1066,11 @@ void LoadStubCompiler::GenerateLoadField(Register reg, void LoadStubCompiler::GenerateLoadCallback( - const CallOptimization& call_optimization) { + const CallOptimization& call_optimization, + Handle receiver_map) { GenerateFastApiCall( - masm(), call_optimization, receiver(), - scratch1(), 0, NULL); + masm(), call_optimization, receiver_map, + receiver(), scratch1(), 0, NULL); } @@ -1271,8 +1273,8 @@ Handle StoreStubCompiler::CompileStoreCallback( Register values[] = { value() }; GenerateFastApiCall( - masm(), call_optimization, receiver(), - scratch1(), 1, values); + masm(), call_optimization, handle(object->map()), + receiver(), scratch1(), 1, values); // Return the generated code. return GetCode(kind(), Code::FAST, name); diff --git a/src/ic.cc b/src/ic.cc index c79ea2c..9e9aa93 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -938,7 +938,7 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, } CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && - call_optimization.IsCompatibleReceiver(*object)) { + call_optimization.IsCompatibleReceiver(object, holder)) { return compiler.CompileLoadCallback( type, holder, name, call_optimization); } @@ -1364,7 +1364,7 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, Handle function = Handle::cast(setter); CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && - call_optimization.IsCompatibleReceiver(*receiver)) { + call_optimization.IsCompatibleReceiver(receiver, holder)) { return compiler.CompileStoreCallback( receiver, holder, name, call_optimization); } diff --git a/src/stub-cache.cc b/src/stub-cache.cc index b83a5e1..4cf85c3 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -951,7 +951,7 @@ Handle LoadStubCompiler::CompileLoadCallback( ASSERT(call_optimization.is_simple_api_call()); Handle callback = call_optimization.constant_function(); CallbackHandlerFrontend(type, receiver(), holder, name, callback); - GenerateLoadCallback(call_optimization); + GenerateLoadCallback(call_optimization, IC::TypeToMap(*type, isolate())); // Return the generated code. return GetCode(kind(), Code::FAST, name); @@ -1357,7 +1357,6 @@ Handle CallOptimization::LookupHolderOfExpectedType( Handle object_map, HolderLookup* holder_lookup) const { ASSERT(is_simple_api_call()); - ASSERT_EQ(kHolderNotFound, *holder_lookup); if (!object_map->IsJSObjectMap()) { *holder_lookup = kHolderNotFound; return Handle::null(); @@ -1382,6 +1381,38 @@ Handle CallOptimization::LookupHolderOfExpectedType( } +bool CallOptimization::IsCompatibleReceiver(Handle receiver, + Handle holder) const { + ASSERT(is_simple_api_call()); + if (!receiver->IsJSObject()) return false; + Handle map(JSObject::cast(*receiver)->map()); + HolderLookup holder_lookup; + Handle api_holder = + LookupHolderOfExpectedType(map, &holder_lookup); + switch (holder_lookup) { + case kHolderNotFound: + return false; + case kHolderIsReceiver: + return true; + case kHolderFound: + if (api_holder.is_identical_to(holder)) return true; + // Check if holder is in prototype chain of api_holder. + { + JSObject* object = *api_holder; + while (true) { + Object* prototype = object->map()->prototype(); + if (!prototype->IsJSObject()) return false; + if (prototype == *holder) return true; + object = JSObject::cast(prototype); + } + } + break; + } + UNREACHABLE(); + return false; +} + + void CallOptimization::Initialize(Handle function) { constant_function_ = Handle::null(); is_simple_api_call_ = false; diff --git a/src/stub-cache.h b/src/stub-cache.h index daa1e6e..d893349 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -611,7 +611,8 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { void GenerateLoadConstant(Handle value); void GenerateLoadCallback(Register reg, Handle callback); - void GenerateLoadCallback(const CallOptimization& call_optimization); + void GenerateLoadCallback(const CallOptimization& call_optimization, + Handle receiver_map); void GenerateLoadInterceptor(Register holder_reg, Handle object, Handle holder, @@ -827,11 +828,9 @@ class CallOptimization BASE_EMBEDDED { Handle receiver_map, HolderLookup* holder_lookup) const; - bool IsCompatibleReceiver(Object* receiver) { - ASSERT(is_simple_api_call()); - if (expected_receiver_type_.is_null()) return true; - return expected_receiver_type_->IsTemplateFor(receiver); - } + // Check if the api holder is between the receiver and the holder. + bool IsCompatibleReceiver(Handle receiver, + Handle holder) const; private: void Initialize(Handle function); diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index b7e7b48..3e06865 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -392,23 +392,52 @@ static void CompileCallLoadPropertyWithInterceptor( } -static void GenerateFastApiCallBody(MacroAssembler* masm, - const CallOptimization& optimization, - int argc, - Register holder_in, - bool restore_context) { +// Generate call to api function. +static void GenerateFastApiCall(MacroAssembler* masm, + const CallOptimization& optimization, + Handle receiver_map, + Register receiver, + Register scratch_in, + int argc, + Register* values) { ASSERT(optimization.is_simple_api_call()); + __ PopReturnAddressTo(scratch_in); + // receiver + __ 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_in.is(arg)); + __ push(arg); + } + __ PushReturnAddressFrom(scratch_in); + // Stack now matches JSFunction abi. + // Abi for CallApiFunctionStub. Register callee = rax; Register call_data = rbx; Register holder = rcx; Register api_function_address = rdx; + Register scratch = rdi; // scratch_in is no longer valid. // Put holder in place. - __ Move(holder, holder_in); - - Register scratch = rdi; + 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: + __ Move(holder, api_holder); + break; + case CallOptimization::kHolderNotFound: + UNREACHABLE(); + break; + } Isolate* isolate = masm->isolate(); Handle function = optimization.constant_function(); @@ -436,38 +465,11 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); // Jump to stub. - CallApiFunctionStub stub(restore_context, call_data_undefined, argc); + CallApiFunctionStub stub(true, call_data_undefined, argc); __ TailCallStub(&stub); } -// Generate call to api function. -static void GenerateFastApiCall(MacroAssembler* masm, - const CallOptimization& optimization, - Register receiver, - Register scratch1, - int argc, - Register* values) { - __ PopReturnAddressTo(scratch1); - // receiver - __ 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(!scratch1.is(arg)); - __ push(arg); - } - __ PushReturnAddressFrom(scratch1); - // Stack now matches JSFunction abi. - GenerateFastApiCallBody(masm, - optimization, - argc, - receiver, - true); -} - - void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, Label* label, Handle name) { @@ -968,10 +970,11 @@ void LoadStubCompiler::GenerateLoadField(Register reg, void LoadStubCompiler::GenerateLoadCallback( - const CallOptimization& call_optimization) { + const CallOptimization& call_optimization, + Handle receiver_map) { GenerateFastApiCall( - masm(), call_optimization, receiver(), - scratch1(), 0, NULL); + masm(), call_optimization, receiver_map, + receiver(), scratch1(), 0, NULL); } @@ -1165,8 +1168,8 @@ Handle StoreStubCompiler::CompileStoreCallback( Register values[] = { value() }; GenerateFastApiCall( - masm(), call_optimization, receiver(), - scratch1(), 1, values); + masm(), call_optimization, handle(object->map()), + receiver(), scratch1(), 1, values); // Return the generated code. return GetCode(kind(), Code::FAST, name);