From 93f2ed48d9c5f7377b1dbe705da636d5f2fc50b7 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Thu, 14 Nov 2013 16:25:31 +0000 Subject: [PATCH] Handle all object types (minus smi) in load/store ICs R=ulan@chromium.org Review URL: https://chromiumcodereview.appspot.com/62953007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17755 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/stub-cache-arm.cc | 82 +++++----- src/ia32/stub-cache-ia32.cc | 77 ++++----- src/ic-inl.h | 8 +- src/ic.cc | 124 ++++++++------ src/ic.h | 31 ++-- src/objects-inl.h | 4 +- src/objects.h | 4 +- src/stub-cache.cc | 200 ++++++++++++----------- src/stub-cache.h | 91 +++++------ src/type-info.cc | 7 +- src/x64/stub-cache-x64.cc | 77 ++++----- test/mjsunit/load-callback-from-value-classic.js | 38 +++++ 12 files changed, 390 insertions(+), 353 deletions(-) create mode 100644 test/mjsunit/load-callback-from-value-classic.js diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 0362c1a..a163c53 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -1298,34 +1298,33 @@ Register StubCompiler::CheckPrototypes(Handle object, } -void LoadStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void LoadStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ b(success); + Label success; + __ b(&success); __ bind(miss); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } -void StoreStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void StoreStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ b(success); + Label success; + __ b(&success); GenerateRestoreName(masm(), miss, name); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } Register LoadStubCompiler::CallbackHandlerFrontend( - Handle object, + Handle object, Register object_reg, Handle holder, Handle name, - Label* success, Handle callback) { Label miss; @@ -1362,7 +1361,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( __ b(ne, &miss); } - HandlerFrontendFooter(name, success, &miss); + HandlerFrontendFooter(name, &miss); return reg; } @@ -1468,7 +1467,7 @@ void LoadStubCompiler::GenerateLoadCallback( void LoadStubCompiler::GenerateLoadInterceptor( Register holder_reg, - Handle object, + Handle object, Handle interceptor_holder, LookupResult* lookup, Handle name) { @@ -2539,11 +2538,23 @@ Handle CallStubCompiler::CompileFastApiCall( } +void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { + Label success; + // Check that the object is a boolean. + __ LoadRoot(ip, Heap::kTrueValueRootIndex); + __ cmp(object, ip); + __ b(eq, &success); + __ LoadRoot(ip, Heap::kFalseValueRootIndex); + __ cmp(object, ip); + __ b(ne, miss); + __ bind(&success); +} + + void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, Handle name, - CheckType check, - Label* success) { + CheckType check) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -2619,15 +2630,8 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, break; } case BOOLEAN_CHECK: { - Label fast; - // Check that the object is a boolean. - __ LoadRoot(ip, Heap::kTrueValueRootIndex); - __ cmp(r1, ip); - __ b(eq, &fast); - __ LoadRoot(ip, Heap::kFalseValueRootIndex); - __ cmp(r1, ip); - __ b(ne, &miss); - __ bind(&fast); + GenerateBooleanCheck(r1, &miss); + // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); @@ -2638,11 +2642,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, } } - __ b(success); + Label success; + __ b(&success); // Handle call cache miss. __ bind(&miss); GenerateMissBranch(); + + __ bind(&success); } @@ -2671,10 +2678,7 @@ Handle CallStubCompiler::CompileCallConstant( if (!code.is_null()) return code; } - Label success; - - CompileHandlerFrontend(object, holder, name, check, &success); - __ bind(&success); + CompileHandlerFrontend(object, holder, name, check); CompileHandlerBackend(function); // Return the generated code. @@ -2785,9 +2789,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, Handle callback) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); // Stub never generated for non-global objects that require access checks. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -2813,9 +2815,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, const CallOptimization& call_optimization) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); Register values[] = { value() }; GenerateFastApiCall( @@ -2910,15 +2910,12 @@ Handle StoreStubCompiler::CompileStoreInterceptor( Handle LoadStubCompiler::CompileLoadNonexistent( - Handle object, + Handle object, Handle last, Handle name, Handle global) { - Label success; + NonexistentHandlerFrontend(object, last, name, global); - NonexistentHandlerFrontend(object, last, name, &success, global); - - __ bind(&success); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); @@ -3013,12 +3010,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, Handle LoadStubCompiler::CompileLoadGlobal( - Handle object, + Handle object, Handle global, Handle cell, Handle name, bool is_dont_delete) { - Label success, miss; + Label miss; HandlerFrontendHeader(object, receiver(), global, name, &miss); @@ -3033,8 +3030,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( __ b(eq, &miss); } - HandlerFrontendFooter(name, &success, &miss); - __ bind(&success); + HandlerFrontendFooter(name, &miss); Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 43576d6..66edf2e 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -1267,34 +1267,33 @@ Register StubCompiler::CheckPrototypes(Handle object, } -void LoadStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void LoadStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ jmp(success); + Label success; + __ jmp(&success); __ bind(miss); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } -void StoreStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void StoreStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ jmp(success); + Label success; + __ jmp(&success); GenerateRestoreName(masm(), miss, name); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } Register LoadStubCompiler::CallbackHandlerFrontend( - Handle object, + Handle object, Register object_reg, Handle holder, Handle name, - Label* success, Handle callback) { Label miss; @@ -1344,7 +1343,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( __ j(not_equal, &miss); } - HandlerFrontendFooter(name, success, &miss); + HandlerFrontendFooter(name, &miss); return reg; } @@ -1450,7 +1449,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle value) { void LoadStubCompiler::GenerateLoadInterceptor( Register holder_reg, - Handle object, + Handle object, Handle interceptor_holder, LookupResult* lookup, Handle name) { @@ -2613,11 +2612,21 @@ Handle CallStubCompiler::CompileFastApiCall( } +void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { + Label success; + // Check that the object is a boolean. + __ cmp(object, factory()->true_value()); + __ j(equal, &success); + __ cmp(object, factory()->false_value()); + __ j(not_equal, miss); + __ bind(&success); +} + + void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, Handle name, - CheckType check, - Label* success) { + CheckType check) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2696,13 +2705,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, break; } case BOOLEAN_CHECK: { - Label fast; - // Check that the object is a boolean. - __ cmp(edx, factory()->true_value()); - __ j(equal, &fast); - __ cmp(edx, factory()->false_value()); - __ j(not_equal, &miss); - __ bind(&fast); + GenerateBooleanCheck(edx, &miss); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); @@ -2713,11 +2716,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, } } - __ jmp(success); + Label success; + __ jmp(&success); // Handle call cache miss. __ bind(&miss); GenerateMissBranch(); + + __ bind(&success); } @@ -2747,10 +2753,7 @@ Handle CallStubCompiler::CompileCallConstant( if (!code.is_null()) return code; } - Label success; - - CompileHandlerFrontend(object, holder, name, check, &success); - __ bind(&success); + CompileHandlerFrontend(object, holder, name, check); CompileHandlerBackend(function); // Return the generated code. @@ -2885,9 +2888,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, Handle callback) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); __ pop(scratch1()); // remove the return address __ push(receiver()); @@ -2911,9 +2912,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, const CallOptimization& call_optimization) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); Register values[] = { value() }; GenerateFastApiCall( @@ -3020,15 +3019,12 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( Handle LoadStubCompiler::CompileLoadNonexistent( - Handle object, + Handle object, Handle last, Handle name, Handle global) { - Label success; + NonexistentHandlerFrontend(object, last, name, global); - NonexistentHandlerFrontend(object, last, name, &success, global); - - __ bind(&success); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. __ mov(eax, isolate()->factory()->undefined_value()); @@ -3118,12 +3114,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, Handle LoadStubCompiler::CompileLoadGlobal( - Handle object, + Handle object, Handle global, Handle cell, Handle name, bool is_dont_delete) { - Label success, miss; + Label miss; HandlerFrontendHeader(object, receiver(), global, name, &miss); // Get the value from the cell. @@ -3143,8 +3139,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); } - HandlerFrontendFooter(name, &success, &miss); - __ bind(&success); + HandlerFrontendFooter(name, &miss); Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1); diff --git a/src/ic-inl.h b/src/ic-inl.h index 06cbf2e..c1c5c5e 100644 --- a/src/ic-inl.h +++ b/src/ic-inl.h @@ -100,8 +100,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) { } -InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object, - JSObject* holder) { +InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object) { if (object->IsJSObject()) return OWN_MAP; // If the object is a value, we use the prototype map for the cache. @@ -111,13 +110,12 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object, } -JSObject* IC::GetCodeCacheHolder(Isolate* isolate, +HeapObject* IC::GetCodeCacheHolder(Isolate* isolate, Object* object, InlineCacheHolderFlag holder) { Object* map_owner = holder == OWN_MAP ? object : object->GetPrototype(isolate); - ASSERT(map_owner->IsJSObject()); - return JSObject::cast(map_owner); + return HeapObject::cast(map_owner); } diff --git a/src/ic.cc b/src/ic.cc index 640b188..187023e 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -1005,7 +1005,7 @@ void IC::UpdateMonomorphicIC(Handle receiver, Handle name) { if (!handler->is_handler()) return set_target(*handler); Handle ic = isolate()->stub_cache()->ComputeMonomorphicIC( - receiver, handler, name, strict_mode()); + name, receiver, handler, strict_mode()); set_target(*ic); } @@ -1035,9 +1035,13 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { } -void IC::PatchCache(Handle receiver, +void IC::PatchCache(Handle object, Handle name, Handle code) { + // TODO(verwaest): Handle smi here as well. + if (!object->IsHeapObject()) return; + + Handle receiver = Handle::cast(object); switch (state()) { case UNINITIALIZED: case PREMONOMORPHIC: @@ -1097,13 +1101,6 @@ Handle LoadIC::SimpleFieldLoad(int offset, void LoadIC::UpdateCaches(LookupResult* lookup, Handle object, Handle name) { - // TODO(verwaest): It would be nice to support loading fields from smis as - // well. For now just fail to update the cache. - if (!object->IsHeapObject()) return; - - Handle receiver = Handle::cast(object); - - Handle code; if (state() == UNINITIALIZED) { // This is the first time we execute this inline cache. // Set the target to the pre monomorphic stub to delay @@ -1111,27 +1108,23 @@ void LoadIC::UpdateCaches(LookupResult* lookup, set_target(*pre_monomorphic_stub()); TRACE_IC("LoadIC", name); return; - } else if (!lookup->IsCacheable()) { + } + + Handle code; + if (!lookup->IsCacheable()) { // Bail out if the result is not cacheable. code = slow_stub(); - } else if (object->IsString() && - name->Equals(isolate()->heap()->length_string())) { - int length_index = String::kLengthOffset / kPointerSize; - code = SimpleFieldLoad(length_index); - } else if (!object->IsJSObject()) { - // TODO(jkummerow): It would be nice to support non-JSObjects in - // ComputeLoadHandler, then we wouldn't need to go generic here. - code = slow_stub(); } else if (!lookup->IsProperty()) { - code = kind() == Code::LOAD_IC - ? isolate()->stub_cache()->ComputeLoadNonexistent( - name, Handle::cast(receiver)) - : slow_stub(); + if (kind() == Code::LOAD_IC) { + code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object); + } else { + code = slow_stub(); + } } else { - code = ComputeHandler(lookup, Handle::cast(receiver), name); + code = ComputeHandler(lookup, object, name); } - PatchCache(receiver, name, code); + PatchCache(object, name, code); TRACE_IC("LoadIC", name); } @@ -1144,18 +1137,22 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { Handle IC::ComputeHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, Handle value) { + InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); + Handle stub_holder(GetCodeCacheHolder( + isolate(), *object, cache_holder)); + Handle code = isolate()->stub_cache()->FindHandler( - name, receiver, kind()); + name, stub_holder, kind(), cache_holder, strict_mode()); if (!code.is_null()) return code; - code = CompileHandler(lookup, receiver, name, value); + code = CompileHandler(lookup, object, name, value, cache_holder); ASSERT(code->is_handler()); if (code->type() != Code::NORMAL) { - HeapObject::UpdateMapCodeCache(receiver, name, code); + HeapObject::UpdateMapCodeCache(stub_holder, name, code); } return code; @@ -1163,29 +1160,35 @@ Handle IC::ComputeHandler(LookupResult* lookup, Handle LoadIC::CompileHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, - Handle unused) { + Handle unused, + InlineCacheHolderFlag cache_holder) { + if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { + int length_index = String::kLengthOffset / kPointerSize; + return SimpleFieldLoad(length_index); + } + Handle holder(lookup->holder()); - LoadStubCompiler compiler(isolate(), kind()); + LoadStubCompiler compiler(isolate(), cache_holder, kind()); switch (lookup->type()) { case FIELD: { PropertyIndex field = lookup->GetFieldIndex(); - if (receiver.is_identical_to(holder)) { + if (object.is_identical_to(holder)) { return SimpleFieldLoad(field.translate(holder), field.is_inobject(holder), lookup->representation()); } return compiler.CompileLoadField( - receiver, holder, name, field, lookup->representation()); + object, holder, name, field, lookup->representation()); } case CONSTANT: { Handle constant(lookup->GetConstant(), isolate()); // TODO(2803): Don't compute a stub for cons strings because they cannot // be embedded into code. if (constant->IsConsString()) break; - return compiler.CompileLoadConstant(receiver, holder, name, constant); + return compiler.CompileLoadConstant(object, holder, name, constant); } case NORMAL: if (kind() != Code::LOAD_IC) break; @@ -1194,26 +1197,31 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle cell( global->GetPropertyCell(lookup), isolate()); Handle code = compiler.CompileLoadGlobal( - receiver, global, cell, name, lookup->IsDontDelete()); + object, global, cell, name, lookup->IsDontDelete()); // TODO(verwaest): Move caching of these NORMAL stubs outside as well. - HeapObject::UpdateMapCodeCache(receiver, name, code); + Handle stub_holder(GetCodeCacheHolder( + isolate(), *object, cache_holder)); + HeapObject::UpdateMapCodeCache(stub_holder, name, code); return code; } // There is only one shared stub for loading normalized // properties. It does not traverse the prototype chain, so the - // property must be found in the receiver for the stub to be + // property must be found in the object for the stub to be // applicable. - if (!holder.is_identical_to(receiver)) break; + if (!object.is_identical_to(holder)) break; return isolate()->builtins()->LoadIC_Normal(); case CALLBACKS: { // Use simple field loads for some well-known callback properties. int object_offset; - Handle map(receiver->map()); - if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { - PropertyIndex index = - PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); - return compiler.CompileLoadField( - receiver, receiver, name, index, Representation::Tagged()); + if (object->IsJSObject()) { + Handle receiver = Handle::cast(object); + Handle map(receiver->map()); + if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { + PropertyIndex index = + PropertyIndex::NewHeaderIndex(object_offset / kPointerSize); + return compiler.CompileLoadField( + receiver, receiver, name, index, Representation::Tagged()); + } } Handle callback(lookup->GetCallbackObject(), isolate()); @@ -1221,8 +1229,8 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, Handle info = Handle::cast(callback); if (v8::ToCData
(info->getter()) == 0) break; - if (!info->IsCompatibleReceiver(*receiver)) break; - return compiler.CompileLoadCallback(receiver, holder, name, info); + if (!info->IsCompatibleReceiver(*object)) break; + return compiler.CompileLoadCallback(object, holder, name, info); } else if (callback->IsAccessorPair()) { Handle getter(Handle::cast(callback)->getter(), isolate()); @@ -1230,13 +1238,20 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, if (holder->IsGlobalObject()) break; if (!holder->HasFastProperties()) break; Handle function = Handle::cast(getter); + if (!object->IsJSObject() && + !function->IsBuiltin() && + function->shared()->is_classic_mode()) { + // Calling non-strict non-builtins with a value as the receiver + // requires boxing. + break; + } CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && - call_optimization.IsCompatibleReceiver(*receiver)) { + call_optimization.IsCompatibleReceiver(*object)) { return compiler.CompileLoadCallback( - receiver, holder, name, call_optimization); + object, holder, name, call_optimization); } - return compiler.CompileLoadViaGetter(receiver, holder, name, function); + return compiler.CompileLoadViaGetter(object, holder, name, function); } // TODO(dcarney): Handle correctly. if (callback->IsDeclaredAccessorInfo()) break; @@ -1246,7 +1261,7 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, } case INTERCEPTOR: ASSERT(HasInterceptorGetter(*holder)); - return compiler.CompileLoadInterceptor(receiver, holder, name); + return compiler.CompileLoadInterceptor(object, holder, name); default: break; } @@ -1582,9 +1597,14 @@ void StoreIC::UpdateCaches(LookupResult* lookup, Handle StoreIC::CompileHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, - Handle value) { + Handle value, + InlineCacheHolderFlag cache_holder) { + ASSERT(cache_holder == OWN_MAP); + // This is currently guaranteed by checks in StoreIC::Store. + Handle receiver = Handle::cast(object); + Handle holder(lookup->holder()); StoreStubCompiler compiler(isolate(), strict_mode(), kind()); switch (lookup->type()) { diff --git a/src/ic.h b/src/ic.h index fde4bc7..819cb4b 100644 --- a/src/ic.h +++ b/src/ic.h @@ -132,11 +132,13 @@ class IC { // Determines which map must be used for keeping the code stub. // These methods should not be called with undefined or null. - static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object, - JSObject* holder); - static inline JSObject* GetCodeCacheHolder(Isolate* isolate, - Object* object, - InlineCacheHolderFlag holder); + static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); + // TODO(verwaest): This currently returns a HeapObject rather than JSObject* + // since loading the IC for loading the length from strings are stored on + // the string map directly, rather than on the JSObject-typed prototype. + static inline HeapObject* GetCodeCacheHolder(Isolate* isolate, + Object* object, + InlineCacheHolderFlag holder); static bool IsCleared(Code* code) { InlineCacheState state = code->ic_state(); @@ -180,13 +182,14 @@ class IC { // Compute the handler either by compiling or by retrieving a cached version. Handle ComputeHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, Handle value = Handle::null()); virtual Handle CompileHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, - Handle value) { + Handle value, + InlineCacheHolderFlag cache_holder) { UNREACHABLE(); return Handle::null(); } @@ -200,7 +203,7 @@ class IC { void CopyICToMegamorphicCache(Handle name); bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map); - void PatchCache(Handle receiver, + void PatchCache(Handle object, Handle name, Handle code); virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code); @@ -422,9 +425,10 @@ class LoadIC: public IC { Handle name); virtual Handle CompileHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, - Handle unused); + Handle unused, + InlineCacheHolderFlag cache_holder); private: // Stub accessors. @@ -617,9 +621,10 @@ class StoreIC: public IC { Handle name, Handle value); virtual Handle CompileHandler(LookupResult* lookup, - Handle receiver, + Handle object, Handle name, - Handle value); + Handle value, + InlineCacheHolderFlag cache_holder); private: void set_target(Code* code) { diff --git a/src/objects-inl.h b/src/objects-inl.h index 5014c91..fced7a9 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -4185,9 +4185,9 @@ Code::Flags Code::ComputeFlags(Kind kind, Code::Flags Code::ComputeMonomorphicFlags(Kind kind, ExtraICState extra_ic_state, + InlineCacheHolderFlag holder, StubType type, - int argc, - InlineCacheHolderFlag holder) { + int argc) { return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder); } diff --git a/src/objects.h b/src/objects.h index c912f7c..85627b7 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5253,9 +5253,9 @@ class Code: public HeapObject { static inline Flags ComputeMonomorphicFlags( Kind kind, ExtraICState extra_ic_state = kNoExtraICState, + InlineCacheHolderFlag holder = OWN_MAP, StubType type = NORMAL, - int argc = -1, - InlineCacheHolderFlag holder = OWN_MAP); + int argc = -1); static inline InlineCacheState ExtractICStateFromFlags(Flags flags); static inline StubType ExtractTypeFromFlags(Flags flags); diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 1bc4b13..9dc89c2 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -102,8 +102,10 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) { Handle StubCache::FindIC(Handle name, Handle stub_holder_map, Code::Kind kind, - Code::ExtraICState extra_state) { - Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state); + Code::ExtraICState extra_state, + InlineCacheHolderFlag cache_holder) { + Code::Flags flags = Code::ComputeMonomorphicFlags( + kind, extra_state, cache_holder); Handle probe(stub_holder_map->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); @@ -111,17 +113,10 @@ Handle StubCache::FindIC(Handle name, } -Handle StubCache::FindIC(Handle name, - Handle stub_holder, - Code::Kind kind, - Code::ExtraICState extra_ic_state) { - return FindIC(name, Handle(stub_holder->map()), kind, extra_ic_state); -} - - Handle StubCache::FindHandler(Handle name, - Handle receiver, + Handle stub_holder, Code::Kind kind, + InlineCacheHolderFlag cache_holder, StrictModeFlag strict_mode) { Code::ExtraICState extra_ic_state = Code::kNoExtraICState; if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { @@ -129,28 +124,36 @@ Handle StubCache::FindHandler(Handle name, STANDARD_STORE, strict_mode); } Code::Flags flags = Code::ComputeMonomorphicFlags( - Code::HANDLER, extra_ic_state, Code::NORMAL, kind); - Handle probe(receiver->map()->FindInCodeCache(*name, flags), + Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind); + + Handle probe(stub_holder->map()->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); return Handle::null(); } -Handle StubCache::ComputeMonomorphicIC(Handle receiver, +Handle StubCache::ComputeMonomorphicIC(Handle name, + Handle object, Handle handler, - Handle name, StrictModeFlag strict_mode) { Code::Kind kind = handler->handler_kind(); - Handle map(receiver->map()); - Handle ic = FindIC(name, map, kind, strict_mode); + // Use the same cache holder for the IC as for the handler. + InlineCacheHolderFlag cache_holder = + Code::ExtractCacheHolderFromFlags(handler->flags()); + Handle stub_holder(IC::GetCodeCacheHolder( + isolate(), *object, cache_holder)); + Handle stub_holder_map(stub_holder->map()); + Handle ic = FindIC( + name, stub_holder_map, kind, strict_mode, cache_holder); if (!ic.is_null()) return ic; + Handle map(object->map()); if (kind == Code::LOAD_IC) { - LoadStubCompiler ic_compiler(isolate()); + LoadStubCompiler ic_compiler(isolate(), cache_holder); ic = ic_compiler.CompileMonomorphicIC(map, handler, name); } else if (kind == Code::KEYED_LOAD_IC) { - KeyedLoadStubCompiler ic_compiler(isolate()); + KeyedLoadStubCompiler ic_compiler(isolate(), cache_holder); ic = ic_compiler.CompileMonomorphicIC(map, handler, name); } else if (kind == Code::STORE_IC) { StoreStubCompiler ic_compiler(isolate(), strict_mode); @@ -161,13 +164,16 @@ Handle StubCache::ComputeMonomorphicIC(Handle receiver, ic = ic_compiler.CompileMonomorphicIC(map, handler, name); } - HeapObject::UpdateMapCodeCache(receiver, name, ic); + HeapObject::UpdateMapCodeCache(stub_holder, name, ic); return ic; } Handle StubCache::ComputeLoadNonexistent(Handle name, - Handle receiver) { + Handle object) { + InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); + Handle stub_holder(IC::GetCodeCacheHolder( + isolate(), *object, cache_holder)); // If no global objects are present in the prototype chain, the load // nonexistent IC stub can be shared for all names for a given map // and we use the empty string for the map cache in that case. If @@ -176,7 +182,7 @@ Handle StubCache::ComputeLoadNonexistent(Handle name, // specific to the name. Handle cache_name = factory()->empty_string(); Handle current; - Handle next = receiver; + Handle next = stub_holder; Handle global; do { current = Handle::cast(next); @@ -191,13 +197,14 @@ Handle StubCache::ComputeLoadNonexistent(Handle name, // Compile the stub that is either shared for all names or // name specific if there are global objects involved. - Handle handler = FindHandler(cache_name, receiver, Code::LOAD_IC); + Handle handler = FindHandler( + cache_name, stub_holder, Code::LOAD_IC, cache_holder); if (!handler.is_null()) return handler; - LoadStubCompiler compiler(isolate_); + LoadStubCompiler compiler(isolate_, cache_holder); handler = - compiler.CompileLoadNonexistent(receiver, current, cache_name, global); - HeapObject::UpdateMapCodeCache(receiver, cache_name, handler); + compiler.CompileLoadNonexistent(object, current, cache_name, global); + HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler); return handler; } @@ -257,9 +264,8 @@ Handle StubCache::ComputeCallConstant(int argc, Handle holder, Handle function) { // Compute the check type and the map. - InlineCacheHolderFlag cache_holder = - IC::GetCodeCacheForObject(*object, *holder); - Handle stub_holder(IC::GetCodeCacheHolder( + InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); + Handle stub_holder(IC::GetCodeCacheHolder( isolate_, *object, cache_holder)); // Compute check type based on receiver/holder. @@ -283,7 +289,7 @@ Handle StubCache::ComputeCallConstant(int argc, } Code::Flags flags = Code::ComputeMonomorphicFlags( - kind, extra_state, Code::CONSTANT, argc, cache_holder); + kind, extra_state, cache_holder, Code::CONSTANT, argc); Handle probe(stub_holder->map()->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); @@ -312,9 +318,8 @@ Handle StubCache::ComputeCallField(int argc, Handle holder, PropertyIndex index) { // Compute the check type and the map. - InlineCacheHolderFlag cache_holder = - IC::GetCodeCacheForObject(*object, *holder); - Handle stub_holder(IC::GetCodeCacheHolder( + InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); + Handle stub_holder(IC::GetCodeCacheHolder( isolate_, *object, cache_holder)); // TODO(1233596): We cannot do receiver map check for non-JS objects @@ -326,7 +331,7 @@ Handle StubCache::ComputeCallField(int argc, } Code::Flags flags = Code::ComputeMonomorphicFlags( - kind, extra_state, Code::FIELD, argc, cache_holder); + kind, extra_state, cache_holder, Code::FIELD, argc); Handle probe(stub_holder->map()->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); @@ -351,9 +356,8 @@ Handle StubCache::ComputeCallInterceptor(int argc, Handle object, Handle holder) { // Compute the check type and the map. - InlineCacheHolderFlag cache_holder = - IC::GetCodeCacheForObject(*object, *holder); - Handle stub_holder(IC::GetCodeCacheHolder( + InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); + Handle stub_holder(IC::GetCodeCacheHolder( isolate_, *object, cache_holder)); // TODO(1233596): We cannot do receiver map check for non-JS objects @@ -365,7 +369,7 @@ Handle StubCache::ComputeCallInterceptor(int argc, } Code::Flags flags = Code::ComputeMonomorphicFlags( - kind, extra_state, Code::INTERCEPTOR, argc, cache_holder); + kind, extra_state, cache_holder, Code::INTERCEPTOR, argc); Handle probe(stub_holder->map()->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); @@ -392,7 +396,7 @@ Handle StubCache::ComputeCallGlobal(int argc, Handle cell, Handle function) { Code::Flags flags = Code::ComputeMonomorphicFlags( - kind, extra_state, Code::NORMAL, argc); + kind, extra_state, OWN_MAP, Code::NORMAL, argc); Handle probe(receiver->map()->FindInCodeCache(*name, flags), isolate_); if (probe->IsCode()) return Handle::cast(probe); @@ -1096,10 +1100,7 @@ Handle StubCompiler::GetCodeWithFlags(Code::Flags flags, masm_.GetCode(&desc); Handle code = factory()->NewCode(desc, flags, masm_.CodeObject()); #ifdef ENABLE_DISASSEMBLER - if (FLAG_print_code_stubs) { - CodeTracer::Scope trace_scope(isolate()->GetCodeTracer()); - code->Disassemble(name, trace_scope.file()); - } + if (FLAG_print_code_stubs) code->Disassemble(name); #endif return code; } @@ -1127,55 +1128,82 @@ void StubCompiler::LookupPostInterceptor(Handle holder, Register LoadStubCompiler::HandlerFrontendHeader( - Handle object, + Handle object, Register object_reg, Handle holder, Handle name, Label* miss) { - return CheckPrototypes(object, object_reg, holder, + Handle receiver; + PrototypeCheckType check_type = CHECK_ALL_MAPS; + int function_index = -1; + if (object->IsJSObject()) { + receiver = Handle::cast(object); + check_type = SKIP_RECEIVER; + } else { + if (object->IsString()) { + function_index = Context::STRING_FUNCTION_INDEX; + } else if (object->IsSymbol()) { + function_index = Context::SYMBOL_FUNCTION_INDEX; + } else if (object->IsNumber()) { + function_index = Context::NUMBER_FUNCTION_INDEX; + } else { + ASSERT(object->IsBoolean()); + // Booleans use the generic oddball map, so an additional check is + // needed to ensure the receiver is really a boolean. + GenerateBooleanCheck(object_reg, miss); + function_index = Context::BOOLEAN_FUNCTION_INDEX; + } + + GenerateDirectLoadGlobalFunctionPrototype( + masm(), function_index, scratch1(), miss); + receiver = handle(JSObject::cast(object->GetPrototype(isolate()))); + object_reg = scratch1(); + } + + // Check that the maps starting from the prototype haven't changed. + return CheckPrototypes(receiver, object_reg, holder, scratch1(), scratch2(), scratch3(), - name, miss, SKIP_RECEIVER); + name, miss, check_type); } // HandlerFrontend for store uses the name register. It has to be restored // before a miss. Register StoreStubCompiler::HandlerFrontendHeader( - Handle object, + Handle object, Register object_reg, Handle holder, Handle name, Label* miss) { - return CheckPrototypes(object, object_reg, holder, + return CheckPrototypes(Handle::cast(object), object_reg, holder, this->name(), scratch1(), scratch2(), name, miss, SKIP_RECEIVER); } -Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle object, +Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle object, Register object_reg, Handle holder, - Handle name, - Label* success) { + Handle name) { Label miss; Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); - HandlerFrontendFooter(name, success, &miss); + HandlerFrontendFooter(name, &miss); + return reg; } void LoadStubCompiler::NonexistentHandlerFrontend( - Handle object, + Handle object, Handle last, Handle name, - Label* success, Handle global) { Label miss; - Register holder = - HandlerFrontendHeader(object, receiver(), last, name, &miss); + Register holder = HandlerFrontendHeader( + object, receiver(), last, name, &miss); if (!last->HasFastProperties() && !last->IsJSGlobalObject() && @@ -1196,12 +1224,12 @@ void LoadStubCompiler::NonexistentHandlerFrontend( GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); } - HandlerFrontendFooter(name, success, &miss); + HandlerFrontendFooter(name, &miss); } Handle LoadStubCompiler::CompileLoadField( - Handle object, + Handle object, Handle holder, Handle name, PropertyIndex field, @@ -1221,13 +1249,11 @@ Handle LoadStubCompiler::CompileLoadField( Handle LoadStubCompiler::CompileLoadConstant( - Handle object, + Handle object, Handle holder, Handle name, Handle value) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); GenerateLoadConstant(value); // Return the generated code. @@ -1236,15 +1262,12 @@ Handle LoadStubCompiler::CompileLoadConstant( Handle LoadStubCompiler::CompileLoadCallback( - Handle object, + Handle object, Handle holder, Handle name, Handle callback) { - Label success; - Register reg = CallbackHandlerFrontend( - object, receiver(), holder, name, &success, callback); - __ bind(&success); + object, receiver(), holder, name, callback); GenerateLoadCallback(reg, callback); // Return the generated code. @@ -1253,17 +1276,13 @@ Handle LoadStubCompiler::CompileLoadCallback( Handle LoadStubCompiler::CompileLoadCallback( - Handle object, + Handle object, Handle holder, Handle name, const CallOptimization& call_optimization) { ASSERT(call_optimization.is_simple_api_call()); - Label success; - Handle callback = call_optimization.constant_function(); - CallbackHandlerFrontend( - object, receiver(), holder, name, &success, callback); - __ bind(&success); + CallbackHandlerFrontend(object, receiver(), holder, name, callback); GenerateLoadCallback(call_optimization); // Return the generated code. @@ -1272,16 +1291,13 @@ Handle LoadStubCompiler::CompileLoadCallback( Handle LoadStubCompiler::CompileLoadInterceptor( - Handle object, + Handle object, Handle holder, Handle name) { - Label success; - LookupResult lookup(isolate()); LookupPostInterceptor(holder, name, &lookup); - Register reg = HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + Register reg = HandlerFrontend(object, receiver(), holder, name); // TODO(368): Compile in the whole chain: all the interceptors in // prototypes and ultimate answer. GenerateLoadInterceptor(reg, object, holder, &lookup, name); @@ -1296,7 +1312,6 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( Handle interceptor_holder, Handle name, LookupResult* lookup) { - Label success; Handle holder(lookup->holder()); if (lookup->IsField()) { PropertyIndex field = lookup->GetFieldIndex(); @@ -1307,8 +1322,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( // We found FIELD property in prototype chain of interceptor's holder. // Retrieve a field from field's holder. Register reg = HandlerFrontend( - interceptor_holder, interceptor_reg, holder, name, &success); - __ bind(&success); + interceptor_holder, interceptor_reg, holder, name); GenerateLoadField( reg, holder, field, lookup->representation()); } @@ -1321,8 +1335,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( ASSERT(callback->getter() != NULL); Register reg = CallbackHandlerFrontend( - interceptor_holder, interceptor_reg, holder, name, &success, callback); - __ bind(&success); + interceptor_holder, interceptor_reg, holder, name, callback); GenerateLoadCallback(reg, callback); } } @@ -1342,14 +1355,11 @@ Handle BaseLoadStoreStubCompiler::CompileMonomorphicIC( Handle LoadStubCompiler::CompileLoadViaGetter( - Handle object, + Handle object, Handle holder, Handle name, Handle getter) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); GenerateLoadViaGetter(masm(), receiver(), getter); // Return the generated code. @@ -1442,10 +1452,7 @@ Handle StoreStubCompiler::CompileStoreViaSetter( Handle holder, Handle name, Handle setter) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); GenerateStoreViaSetter(masm(), setter); return GetCode(kind(), Code::CALLBACKS, name); @@ -1555,7 +1562,7 @@ Handle BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, Code::StubType type, Handle name) { Code::Flags flags = Code::ComputeFlags( - Code::HANDLER, MONOMORPHIC, extra_state(), type, kind); + Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_); Handle code = GetCodeWithFlags(flags, name); PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); JitEvent(name, code); @@ -1723,11 +1730,8 @@ Handle CallStubCompiler::CompileCustomCall( Handle CallStubCompiler::GetCode(Code::StubType type, Handle name) { int argc = arguments_.immediate(); - Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, - extra_state_, - type, - argc, - cache_holder_); + Code::Flags flags = Code::ComputeMonomorphicFlags( + kind_, extra_state_, cache_holder_, type, argc); return GetCodeWithFlags(flags, name); } diff --git a/src/stub-cache.h b/src/stub-cache.h index 9a82785..2f78fde 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -83,29 +83,21 @@ class StubCache { Handle FindIC(Handle name, Handle stub_holder_map, Code::Kind kind, - Code::ExtraICState extra_state = Code::kNoExtraICState); - - Handle FindIC(Handle name, - Handle stub_holder, - Code::Kind kind, - Code::ExtraICState extra_state = Code::kNoExtraICState); + Code::ExtraICState extra_state = Code::kNoExtraICState, + InlineCacheHolderFlag cache_holder = OWN_MAP); Handle FindHandler(Handle name, - Handle receiver, + Handle stub_holder, Code::Kind kind, + InlineCacheHolderFlag cache_holder = OWN_MAP, StrictModeFlag strict_mode = kNonStrictMode); - Handle ComputeMonomorphicIC(Handle receiver, + Handle ComputeMonomorphicIC(Handle name, + Handle receiver, Handle handler, - Handle name, StrictModeFlag strict_mode); - // Computes the right stub matching. Inserts the result in the - // cache before returning. This might compile a stub if needed. - Handle ComputeLoadNonexistent(Handle name, - Handle object); - - // --- + Handle ComputeLoadNonexistent(Handle name, Handle object); Handle ComputeKeyedLoadElement(Handle receiver_map); @@ -501,6 +493,7 @@ class StubCompiler BASE_EMBEDDED { Label* miss, PrototypeCheckType check = CHECK_ALL_MAPS); + void GenerateBooleanCheck(Register object, Label* miss); protected: Handle GetCodeWithFlags(Code::Flags flags, const char* name); @@ -531,8 +524,10 @@ enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS }; class BaseLoadStoreStubCompiler: public StubCompiler { public: - BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind) - : StubCompiler(isolate), kind_(kind) { + BaseLoadStoreStubCompiler(Isolate* isolate, + Code::Kind kind, + InlineCacheHolderFlag cache_holder = OWN_MAP) + : StubCompiler(isolate), kind_(kind), cache_holder_(cache_holder) { InitializeRegisters(); } virtual ~BaseLoadStoreStubCompiler() { } @@ -563,21 +558,18 @@ class BaseLoadStoreStubCompiler: public StubCompiler { } protected: - virtual Register HandlerFrontendHeader(Handle object, + virtual Register HandlerFrontendHeader(Handle object, Register object_reg, Handle holder, Handle name, Label* miss) = 0; - virtual void HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) = 0; + virtual void HandlerFrontendFooter(Handle name, Label* miss) = 0; - Register HandlerFrontend(Handle object, + Register HandlerFrontend(Handle object, Register object_reg, Handle holder, - Handle name, - Label* success); + Handle name); Handle GetCode(Code::Kind kind, Code::StubType type, @@ -617,42 +609,45 @@ class BaseLoadStoreStubCompiler: public StubCompiler { void InitializeRegisters(); Code::Kind kind_; + InlineCacheHolderFlag cache_holder_; Register* registers_; }; class LoadStubCompiler: public BaseLoadStoreStubCompiler { public: - LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC) - : BaseLoadStoreStubCompiler(isolate, kind) { } + LoadStubCompiler(Isolate* isolate, + InlineCacheHolderFlag cache_holder = OWN_MAP, + Code::Kind kind = Code::LOAD_IC) + : BaseLoadStoreStubCompiler(isolate, kind, cache_holder) { } virtual ~LoadStubCompiler() { } - Handle CompileLoadField(Handle object, + Handle CompileLoadField(Handle object, Handle holder, Handle name, PropertyIndex index, Representation representation); - Handle CompileLoadCallback(Handle object, + Handle CompileLoadCallback(Handle object, Handle holder, Handle name, Handle callback); - Handle CompileLoadCallback(Handle object, + Handle CompileLoadCallback(Handle object, Handle holder, Handle name, const CallOptimization& call_optimization); - Handle CompileLoadConstant(Handle object, + Handle CompileLoadConstant(Handle object, Handle holder, Handle name, Handle value); - Handle CompileLoadInterceptor(Handle object, + Handle CompileLoadInterceptor(Handle object, Handle holder, Handle name); - Handle CompileLoadViaGetter(Handle object, + Handle CompileLoadViaGetter(Handle object, Handle holder, Handle name, Handle getter); @@ -661,12 +656,12 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { Register receiver, Handle getter); - Handle CompileLoadNonexistent(Handle object, + Handle CompileLoadNonexistent(Handle object, Handle last, Handle name, Handle global); - Handle CompileLoadGlobal(Handle object, + Handle CompileLoadGlobal(Handle object, Handle holder, Handle cell, Handle name, @@ -675,26 +670,22 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { static Register* registers(); protected: - virtual Register HandlerFrontendHeader(Handle object, + virtual Register HandlerFrontendHeader(Handle object, Register object_reg, Handle holder, Handle name, Label* miss); - virtual void HandlerFrontendFooter(Handle name, - Label* success, - Label* miss); + virtual void HandlerFrontendFooter(Handle name, Label* miss); - Register CallbackHandlerFrontend(Handle object, + Register CallbackHandlerFrontend(Handle object, Register object_reg, Handle holder, Handle name, - Label* success, Handle callback); - void NonexistentHandlerFrontend(Handle object, + void NonexistentHandlerFrontend(Handle object, Handle last, Handle name, - Label* success, Handle global); void GenerateLoadField(Register reg, @@ -706,7 +697,7 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { Handle callback); void GenerateLoadCallback(const CallOptimization& call_optimization); void GenerateLoadInterceptor(Register holder_reg, - Handle object, + Handle object, Handle holder, LookupResult* lookup, Handle name); @@ -726,8 +717,9 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { class KeyedLoadStubCompiler: public LoadStubCompiler { public: - explicit KeyedLoadStubCompiler(Isolate* isolate) - : LoadStubCompiler(isolate, Code::KEYED_LOAD_IC) { } + KeyedLoadStubCompiler(Isolate* isolate, + InlineCacheHolderFlag cache_holder = OWN_MAP) + : LoadStubCompiler(isolate, cache_holder, Code::KEYED_LOAD_IC) { } Handle CompileLoadElement(Handle receiver_map); @@ -827,15 +819,13 @@ class StoreStubCompiler: public BaseLoadStoreStubCompiler { } protected: - virtual Register HandlerFrontendHeader(Handle object, + virtual Register HandlerFrontendHeader(Handle object, Register object_reg, Handle holder, Handle name, Label* miss); - virtual void HandlerFrontendFooter(Handle name, - Label* success, - Label* miss); + virtual void HandlerFrontendFooter(Handle name, Label* miss); void GenerateRestoreName(MacroAssembler* masm, Label* label, Handle name); @@ -928,8 +918,7 @@ class CallStubCompiler: public StubCompiler { void CompileHandlerFrontend(Handle object, Handle holder, Handle name, - CheckType check, - Label* success); + CheckType check); void CompileHandlerBackend(Handle function); diff --git a/src/type-info.cc b/src/type-info.cc index 65d1364..c548ad3 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -298,11 +298,8 @@ void TypeFeedbackOracle::CallReceiverTypes(Call* expr, Code::ExtraICState extra_ic_state = CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); - Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, - extra_ic_state, - Code::NORMAL, - arity, - OWN_MAP); + Code::Flags flags = Code::ComputeMonomorphicFlags( + Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity); CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types); } diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index cd5291c..b4222bc 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -1200,34 +1200,33 @@ Register StubCompiler::CheckPrototypes(Handle object, } -void LoadStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void LoadStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ jmp(success); + Label success; + __ jmp(&success); __ bind(miss); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } -void StoreStubCompiler::HandlerFrontendFooter(Handle name, - Label* success, - Label* miss) { +void StoreStubCompiler::HandlerFrontendFooter(Handle name, Label* miss) { if (!miss->is_unused()) { - __ jmp(success); + Label success; + __ jmp(&success); GenerateRestoreName(masm(), miss, name); TailCallBuiltin(masm(), MissBuiltin(kind())); + __ bind(&success); } } Register LoadStubCompiler::CallbackHandlerFrontend( - Handle object, + Handle object, Register object_reg, Handle holder, Handle name, - Label* success, Handle callback) { Label miss; @@ -1268,7 +1267,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( __ j(not_equal, &miss); } - HandlerFrontendFooter(name, success, &miss); + HandlerFrontendFooter(name, &miss); return reg; } @@ -1389,7 +1388,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle value) { void LoadStubCompiler::GenerateLoadInterceptor( Register holder_reg, - Handle object, + Handle object, Handle interceptor_holder, LookupResult* lookup, Handle name) { @@ -2507,11 +2506,21 @@ Handle CallStubCompiler::CompileFastApiCall( } +void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { + Label success; + // Check that the object is a boolean. + __ CompareRoot(object, Heap::kTrueValueRootIndex); + __ j(equal, &success); + __ CompareRoot(object, Heap::kFalseValueRootIndex); + __ j(not_equal, miss); + __ bind(&success); +} + + void CallStubCompiler::CompileHandlerFrontend(Handle object, Handle holder, Handle name, - CheckType check, - Label* success) { + CheckType check) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -2593,13 +2602,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, break; } case BOOLEAN_CHECK: { - Label fast; - // Check that the object is a boolean. - __ CompareRoot(rdx, Heap::kTrueValueRootIndex); - __ j(equal, &fast); - __ CompareRoot(rdx, Heap::kFalseValueRootIndex); - __ j(not_equal, &miss); - __ bind(&fast); + GenerateBooleanCheck(rdx, &miss); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype( masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); @@ -2610,11 +2613,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle object, } } - __ jmp(success); + Label success; + __ jmp(&success); // Handle call cache miss. __ bind(&miss); GenerateMissBranch(); + + __ bind(&success); } @@ -2643,10 +2649,7 @@ Handle CallStubCompiler::CompileCallConstant( if (!code.is_null()) return code; } - Label success; - - CompileHandlerFrontend(object, holder, name, check, &success); - __ bind(&success); + CompileHandlerFrontend(object, holder, name, check); CompileHandlerBackend(function); // Return the generated code. @@ -2782,9 +2785,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, Handle callback) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); __ PopReturnAddressTo(scratch1()); __ push(receiver()); @@ -2808,9 +2809,7 @@ Handle StoreStubCompiler::CompileStoreCallback( Handle holder, Handle name, const CallOptimization& call_optimization) { - Label success; - HandlerFrontend(object, receiver(), holder, name, &success); - __ bind(&success); + HandlerFrontend(object, receiver(), holder, name); Register values[] = { value() }; GenerateFastApiCall( @@ -2924,15 +2923,12 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( Handle LoadStubCompiler::CompileLoadNonexistent( - Handle object, + Handle object, Handle last, Handle name, Handle global) { - Label success; + NonexistentHandlerFrontend(object, last, name, global); - NonexistentHandlerFrontend(object, last, name, &success, global); - - __ bind(&success); // Return undefined if maps of the full prototype chain are still the // same and no global property with this name contains a value. __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); @@ -3027,12 +3023,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, Handle LoadStubCompiler::CompileLoadGlobal( - Handle object, + Handle object, Handle global, Handle cell, Handle name, bool is_dont_delete) { - Label success, miss; + Label miss; // TODO(verwaest): Directly store to rax. Currently we cannot do this, since // rax is used as receiver(), which we would otherwise clobber before a // potential miss. @@ -3051,8 +3047,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); } - HandlerFrontendFooter(name, &success, &miss); - __ bind(&success); + HandlerFrontendFooter(name, &miss); Counters* counters = isolate()->counters(); __ IncrementCounter(counters->named_load_global_stub(), 1); diff --git a/test/mjsunit/load-callback-from-value-classic.js b/test/mjsunit/load-callback-from-value-classic.js new file mode 100644 index 0000000..0030c61 --- /dev/null +++ b/test/mjsunit/load-callback-from-value-classic.js @@ -0,0 +1,38 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Object.defineProperty(Boolean.prototype, "v", + {get:function() { return this; }}); + +function f(b) { + return b.v; +} + +assertEquals("object", typeof f(true)); +assertEquals("object", typeof f(true)); +assertEquals("object", typeof f(true)); +assertEquals("object", typeof f(true)); -- 2.7.4