From b38b81bbfe4daeed2602de93d6a0674f7e46d251 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Tue, 1 Oct 2013 09:47:18 +0000 Subject: [PATCH] Always cache the original target in a handle on the IC. This requires us to always open a handle-scope in the miss handlers. BUG= R=ulan@chromium.org Review URL: https://chromiumcodereview.appspot.com/25238002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17037 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ic.cc | 56 +++++++++++++++++++++++------------------------ src/ic.h | 7 +++++- src/stub-cache.cc | 2 +- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/ic.cc b/src/ic.cc index 68fc4c2f66..9af56bfb59 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -118,7 +118,7 @@ void IC::TraceIC(const char* type, #endif // DEBUG #define TRACE_IC(type, name, old_state, new_target) \ - ASSERT((TraceIC(type, name, old_state, new_target), true)) + ASSERT((TraceIC(type, name, old_state, *new_target), true)) IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { // To improve the performance of the (much used) IC code, we unfold a few @@ -145,6 +145,7 @@ IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { #endif fp_ = fp; pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); + target_ = handle(raw_target(), isolate); } @@ -752,7 +753,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup, TryUpdateExtraICState(lookup, object, &extra_ic_state)) { code = ComputeMonomorphicStub(lookup, state, extra_ic_state, object, name); - } else if (TryRemoveInvalidPrototypeDependentStub(target(), + } else if (TryRemoveInvalidPrototypeDependentStub(*target(), *object, *name)) { state = MONOMORPHIC_PROTOTYPE_FAILURE; @@ -1087,8 +1088,6 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { } -// Since GC may have been invoked, by the time PatchCache is called, |state| is -// not necessarily equal to target()->state(). void IC::PatchCache(State state, Handle receiver, Handle name, @@ -1100,7 +1099,7 @@ void IC::PatchCache(State state, UpdateMonomorphicIC(receiver, code, name); break; case MONOMORPHIC: - ASSERT(target() != *code); + ASSERT(!target().is_identical_to(code)); if (!target()->is_keyed_stub()) { bool is_same_handler = false; { @@ -1365,11 +1364,10 @@ Handle KeyedLoadIC::LoadElementStub(Handle receiver) { return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); } - if (target() == *string_stub()) { + if (target().is_identical_to(string_stub())) { target_receiver_maps.Add(isolate()->factory()->string_map()); } else { - GetReceiverMapsForStub(Handle(target(), isolate()), - &target_receiver_maps); + GetReceiverMapsForStub(target(), &target_receiver_maps); if (target_receiver_maps.length() == 0) { return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); } @@ -1447,7 +1445,7 @@ MaybeObject* KeyedLoadIC::Load(State state, } else if (receiver->HasIndexedInterceptor()) { stub = indexed_interceptor_stub(); } else if (!key->ToSmi()->IsFailure() && - (target() != *non_strict_arguments_stub())) { + (!target().is_identical_to(non_strict_arguments_stub()))) { stub = LoadElementStub(receiver); } } @@ -1658,7 +1656,7 @@ MaybeObject* StoreIC::Store(State state, Handle stub = StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); set_target(*stub); - TRACE_IC("StoreIC", name, state, *stub); + TRACE_IC("StoreIC", name, state, stub); Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode(), store_mode); RETURN_IF_EMPTY_HANDLE(isolate(), result); @@ -1671,7 +1669,7 @@ MaybeObject* StoreIC::Store(State state, // proxy as receiver. Handle stub = global_proxy_stub(); set_target(*stub); - TRACE_IC("StoreIC", name, state, *stub); + TRACE_IC("StoreIC", name, state, stub); } Handle result = JSReceiver::SetProperty( receiver, name, value, NONE, strict_mode(), store_mode); @@ -1692,7 +1690,7 @@ MaybeObject* StoreIC::Store(State state, if (state == UNINITIALIZED) { Handle stub = pre_monomorphic_stub(); set_target(*stub); - TRACE_IC("StoreIC", name, state, *stub); + TRACE_IC("StoreIC", name, state, stub); } else if (can_store) { UpdateCaches(&lookup, state, receiver, name, value); } else if (!name->IsCacheable(isolate()) || @@ -2103,7 +2101,7 @@ MaybeObject* KeyedStoreIC::Store(State state, isolate()->heap()->non_strict_arguments_elements_map()) { stub = non_strict_arguments_stub(); } else if (key_is_smi_like && - (target() != *non_strict_arguments_stub())) { + (!target().is_identical_to(non_strict_arguments_stub()))) { KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); stub = StoreElementStub(receiver, store_mode); } else { @@ -2180,7 +2178,7 @@ RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 2); CallIC ic(isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); MaybeObject* maybe_result = ic.LoadFunction(state, extra_ic_state, @@ -2207,7 +2205,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 2); KeyedCallIC ic(isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); MaybeObject* maybe_result = ic.LoadFunction(state, args.at(0), args.at(1)); // Result could be a function or a failure. @@ -2227,7 +2225,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 2); LoadIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Load(state, args.at(0), args.at(1)); } @@ -2237,7 +2235,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 2); KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Load(state, args.at(0), args.at(1), MISS); } @@ -2246,7 +2244,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { HandleScope scope(isolate); ASSERT(args.length() == 2); KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Load(state, args.at(0), args.at(1), MISS); } @@ -2255,7 +2253,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { HandleScope scope(isolate); ASSERT(args.length() == 2); KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Load(state, args.at(0), args.at(1), @@ -2268,7 +2266,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 3); StoreIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Store(state, args.at(0), args.at(1), @@ -2280,7 +2278,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { HandleScope scope(isolate); ASSERT(args.length() == 3); StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Store(state, args.at(0), args.at(1), @@ -2367,7 +2365,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { HandleScope scope(isolate); ASSERT(args.length() == 3); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Store(state, args.at(0), args.at(1), @@ -2380,7 +2378,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { HandleScope scope(isolate); ASSERT(args.length() == 3); KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Store(state, args.at(0), args.at(1), @@ -2390,7 +2388,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 3); StoreIC ic(IC::NO_EXTRA_FRAME, isolate); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); @@ -2408,7 +2406,7 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 3); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); @@ -2429,7 +2427,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { HandleScope scope(isolate); ASSERT(args.length() == 3); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); - IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); + IC::State state = IC::StateFrom(*ic.target(), args[0], args[1]); return ic.Store(state, args.at(0), args.at(1), @@ -2439,7 +2437,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { - SealHandleScope scope(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 4); KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); @@ -2951,11 +2949,11 @@ void CompareIC::UpdateCaches(Handle x, Handle y) { // Used from ICCompareStub::GenerateMiss in code-stubs-.cc. RUNTIME_FUNCTION(Code*, CompareIC_Miss) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 3); CompareIC ic(isolate, static_cast(args.smi_at(2))); ic.UpdateCaches(args.at(0), args.at(1)); - return ic.target(); + return ic.raw_target(); } diff --git a/src/ic.h b/src/ic.h index f82382bbad..e410e302a7 100644 --- a/src/ic.h +++ b/src/ic.h @@ -95,7 +95,9 @@ class IC { virtual ~IC() {} // Get the call-site target; used for determining the state. - Code* target() const { return GetTargetAtAddress(address()); } + Handle target() const { return target_; } + Code* raw_target() const { return GetTargetAtAddress(address()); } + inline Address address() const; // Compute the current IC state based on the target stub, receiver and name. @@ -210,6 +212,9 @@ class IC { Isolate* isolate_; + // The original code target that missed. + Handle target_; + DISALLOW_IMPLICIT_CONSTRUCTORS(IC); }; diff --git a/src/stub-cache.cc b/src/stub-cache.cc index eec879983b..f78ab73106 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -1257,12 +1257,12 @@ static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) { // If the load is non-contextual, just return the undefined result. // Note that both keyed and non-keyed loads may end up here, so we // can't use either LoadIC or KeyedLoadIC constructors. + HandleScope scope(isolate); IC ic(IC::NO_EXTRA_FRAME, isolate); ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub()); if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value(); // Throw a reference error. - HandleScope scope(isolate); Handle name_handle(name); Handle error = isolate->factory()->NewReferenceError("not_defined",