Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Side by Side Diff: src/ic/ic.cc

Issue 650073002: vector-based ICs did not update type feedback counts correctly. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: REBASE. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/base/bits.h" 10 #include "src/base/bits.h"
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 484
485 switch (target->kind()) { 485 switch (target->kind()) {
486 case Code::LOAD_IC: 486 case Code::LOAD_IC:
487 return LoadIC::Clear(isolate, address, target, constant_pool); 487 return LoadIC::Clear(isolate, address, target, constant_pool);
488 case Code::KEYED_LOAD_IC: 488 case Code::KEYED_LOAD_IC:
489 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); 489 return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
490 case Code::STORE_IC: 490 case Code::STORE_IC:
491 return StoreIC::Clear(isolate, address, target, constant_pool); 491 return StoreIC::Clear(isolate, address, target, constant_pool);
492 case Code::KEYED_STORE_IC: 492 case Code::KEYED_STORE_IC:
493 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); 493 return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
494 case Code::CALL_IC:
495 return CallIC::Clear(isolate, address, target, constant_pool);
496 case Code::COMPARE_IC: 494 case Code::COMPARE_IC:
497 return CompareIC::Clear(isolate, address, target, constant_pool); 495 return CompareIC::Clear(isolate, address, target, constant_pool);
498 case Code::COMPARE_NIL_IC: 496 case Code::COMPARE_NIL_IC:
499 return CompareNilIC::Clear(address, target, constant_pool); 497 return CompareNilIC::Clear(address, target, constant_pool);
498 case Code::CALL_IC: // CallICs are vector-based and cleared differently.
500 case Code::BINARY_OP_IC: 499 case Code::BINARY_OP_IC:
501 case Code::TO_BOOLEAN_IC: 500 case Code::TO_BOOLEAN_IC:
502 // Clearing these is tricky and does not 501 // Clearing these is tricky and does not
503 // make any performance difference. 502 // make any performance difference.
504 return; 503 return;
505 default: 504 default:
506 UNREACHABLE(); 505 UNREACHABLE();
507 } 506 }
508 } 507 }
509 508
510 509
510 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host,
511 TypeFeedbackVector* vector, FeedbackVectorICSlot slot) {
512 switch (kind) {
513 case Code::CALL_IC:
514 return CallIC::Clear(isolate, host, vector, slot);
515 default:
516 UNREACHABLE();
517 }
518 }
519
520
511 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, 521 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
512 ConstantPoolArray* constant_pool) { 522 ConstantPoolArray* constant_pool) {
513 if (IsCleared(target)) return; 523 if (IsCleared(target)) return;
514 524
515 // Make sure to also clear the map used in inline fast cases. If we 525 // Make sure to also clear the map used in inline fast cases. If we
516 // do not clear these maps, cached code can keep objects alive 526 // do not clear these maps, cached code can keep objects alive
517 // through the embedded maps. 527 // through the embedded maps.
518 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); 528 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
519 } 529 }
520 530
521 531
522 void CallIC::Clear(Isolate* isolate, Address address, Code* target, 532 void CallIC::Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector,
523 ConstantPoolArray* constant_pool) { 533 FeedbackVectorICSlot slot) {
524 // Currently, CallIC doesn't have state changes. 534 DCHECK(vector != NULL && !slot.IsInvalid());
535 Object* feedback = vector->Get(slot);
536 // Determine our state.
537 State state = FeedbackToState(isolate, vector, slot);
538
539 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
540 vector->Set(slot, isolate->heap()->uninitialized_symbol(),
541 SKIP_WRITE_BARRIER);
542 // The change in state must be processed.
543 OnTypeFeedbackChanged(isolate, host, vector, state, UNINITIALIZED);
544 }
525 } 545 }
526 546
527 547
528 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, 548 void LoadIC::Clear(Isolate* isolate, Address address, Code* target,
529 ConstantPoolArray* constant_pool) { 549 ConstantPoolArray* constant_pool) {
530 if (IsCleared(target)) return; 550 if (IsCleared(target)) return;
531 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, 551 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC,
532 target->extra_ic_state()); 552 target->extra_ic_state());
533 SetTargetAtAddress(address, code, constant_pool); 553 SetTargetAtAddress(address, code, constant_pool);
534 } 554 }
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after
1913 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); 1933 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub");
1914 } 1934 }
1915 DCHECK(!stub.is_null()); 1935 DCHECK(!stub.is_null());
1916 set_target(*stub); 1936 set_target(*stub);
1917 TRACE_IC("StoreIC", key); 1937 TRACE_IC("StoreIC", key);
1918 1938
1919 return store_handle; 1939 return store_handle;
1920 } 1940 }
1921 1941
1922 1942
1943 // static
1944 void CallIC::OnTypeFeedbackChanged(Isolate* isolate, Code* host,
1945 TypeFeedbackVector* vector, State old_state,
1946 State new_state) {
1947 if (host->kind() != Code::FUNCTION) return;
1948
1949 if (FLAG_type_info_threshold > 0) {
1950 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
1951 int generic_delta = 0; // "Generic" here includes megamorphic.
1952 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
1953 &generic_delta);
1954 vector->change_ic_with_type_info_count(polymorphic_delta);
1955 vector->change_ic_generic_count(generic_delta);
1956 }
1957 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
1958 info->change_own_type_change_checksum();
1959 host->set_profiler_ticks(0);
1960 isolate->runtime_profiler()->NotifyICChanged();
1961 // TODO(2029): When an optimized function is patched, it would
1962 // be nice to propagate the corresponding type information to its
1963 // unoptimized version for the benefit of later inlining.
1964 }
1965
1966
1923 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, 1967 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
1924 Handle<TypeFeedbackVector> vector, 1968 Handle<TypeFeedbackVector> vector,
1925 Handle<Smi> slot, const CallICState& state) { 1969 FeedbackVectorICSlot slot,
1970 const CallICState& state) {
1926 DCHECK(FLAG_use_ic && function->IsJSFunction()); 1971 DCHECK(FLAG_use_ic && function->IsJSFunction());
1927 1972
1928 // Are we the array function? 1973 // Are we the array function?
1929 Handle<JSFunction> array_function = 1974 Handle<JSFunction> array_function =
1930 Handle<JSFunction>(isolate()->native_context()->array_function()); 1975 Handle<JSFunction>(isolate()->native_context()->array_function());
1931 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { 1976 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
1932 // Alter the slot. 1977 // Alter the slot.
1933 IC::State old_state = FeedbackToState(vector, slot); 1978 IC::State old_state = FeedbackToState(isolate(), *vector, slot);
1934 Object* feedback = vector->get(slot->value()); 1979 Object* feedback = vector->Get(slot);
1935 if (!feedback->IsAllocationSite()) { 1980 if (!feedback->IsAllocationSite()) {
1936 Handle<AllocationSite> new_site = 1981 Handle<AllocationSite> new_site =
1937 isolate()->factory()->NewAllocationSite(); 1982 isolate()->factory()->NewAllocationSite();
1938 vector->set(slot->value(), *new_site); 1983 vector->Set(slot, *new_site);
1939 } 1984 }
1940 1985
1941 CallIC_ArrayStub stub(isolate(), state); 1986 CallIC_ArrayStub stub(isolate(), state);
1942 set_target(*stub.GetCode()); 1987 set_target(*stub.GetCode());
1943 Handle<String> name; 1988 Handle<String> name;
1944 if (array_function->shared()->name()->IsString()) { 1989 if (array_function->shared()->name()->IsString()) {
1945 name = Handle<String>(String::cast(array_function->shared()->name()), 1990 name = Handle<String>(String::cast(array_function->shared()->name()),
1946 isolate()); 1991 isolate());
1947 } 1992 }
1948 1993
1949 IC::State new_state = FeedbackToState(vector, slot); 1994 IC::State new_state = FeedbackToState(isolate(), *vector, slot);
1950 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 1995 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
1951 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state); 1996 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
1952 return true; 1997 return true;
1953 } 1998 }
1954 return false; 1999 return false;
1955 } 2000 }
1956 2001
1957 2002
1958 void CallIC::PatchMegamorphic(Handle<Object> function, 2003 void CallIC::PatchMegamorphic(Handle<Object> function,
1959 Handle<TypeFeedbackVector> vector, 2004 Handle<TypeFeedbackVector> vector,
1960 Handle<Smi> slot) { 2005 FeedbackVectorICSlot slot) {
1961 CallICState state(target()->extra_ic_state()); 2006 CallICState state(target()->extra_ic_state());
1962 IC::State old_state = FeedbackToState(vector, slot); 2007 IC::State old_state = FeedbackToState(isolate(), *vector, slot);
1963 2008
1964 // We are going generic. 2009 // We are going generic.
1965 vector->set(slot->value(), 2010 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()),
1966 *TypeFeedbackVector::MegamorphicSentinel(isolate()),
1967 SKIP_WRITE_BARRIER); 2011 SKIP_WRITE_BARRIER);
1968 2012
1969 CallICStub stub(isolate(), state); 2013 CallICStub stub(isolate(), state);
1970 Handle<Code> code = stub.GetCode(); 2014 Handle<Code> code = stub.GetCode();
1971 set_target(*code); 2015 set_target(*code);
1972 2016
1973 Handle<Object> name = isolate()->factory()->empty_string(); 2017 Handle<Object> name = isolate()->factory()->empty_string();
1974 if (function->IsJSFunction()) { 2018 if (function->IsJSFunction()) {
1975 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); 2019 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1976 name = handle(js_function->shared()->name(), isolate()); 2020 name = handle(js_function->shared()->name(), isolate());
1977 } 2021 }
1978 2022
1979 IC::State new_state = FeedbackToState(vector, slot); 2023 IC::State new_state = FeedbackToState(isolate(), *vector, slot);
1980 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 2024 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
1981 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); 2025 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1982 } 2026 }
1983 2027
1984 2028
1985 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, 2029 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
1986 Handle<TypeFeedbackVector> vector, Handle<Smi> slot) { 2030 Handle<TypeFeedbackVector> vector,
2031 FeedbackVectorICSlot slot) {
1987 CallICState state(target()->extra_ic_state()); 2032 CallICState state(target()->extra_ic_state());
1988 IC::State old_state = FeedbackToState(vector, slot); 2033 IC::State old_state = FeedbackToState(isolate(), *vector, slot);
1989 Handle<Object> name = isolate()->factory()->empty_string(); 2034 Handle<Object> name = isolate()->factory()->empty_string();
1990 Object* feedback = vector->get(slot->value()); 2035 Object* feedback = vector->Get(slot);
1991 2036
1992 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. 2037 // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
1993 DCHECK(!feedback->IsSmi()); 2038 DCHECK(!feedback->IsSmi());
1994 2039
1995 if (feedback->IsJSFunction() || !function->IsJSFunction()) { 2040 if (feedback->IsJSFunction() || !function->IsJSFunction()) {
1996 // We are going generic. 2041 // We are going generic.
1997 vector->set(slot->value(), 2042 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()),
1998 *TypeFeedbackVector::MegamorphicSentinel(isolate()),
1999 SKIP_WRITE_BARRIER); 2043 SKIP_WRITE_BARRIER);
2000 } else { 2044 } else {
2001 // The feedback is either uninitialized or an allocation site. 2045 // The feedback is either uninitialized or an allocation site.
2002 // It might be an allocation site because if we re-compile the full code 2046 // It might be an allocation site because if we re-compile the full code
2003 // to add deoptimization support, we call with the default call-ic, and 2047 // to add deoptimization support, we call with the default call-ic, and
2004 // merely need to patch the target to match the feedback. 2048 // merely need to patch the target to match the feedback.
2005 // TODO(mvstanton): the better approach is to dispense with patching 2049 // TODO(mvstanton): the better approach is to dispense with patching
2006 // altogether, which is in progress. 2050 // altogether, which is in progress.
2007 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || 2051 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) ||
2008 feedback->IsAllocationSite()); 2052 feedback->IsAllocationSite());
2009 2053
2010 // Do we want to install a custom handler? 2054 // Do we want to install a custom handler?
2011 if (FLAG_use_ic && 2055 if (FLAG_use_ic &&
2012 DoCustomHandler(receiver, function, vector, slot, state)) { 2056 DoCustomHandler(receiver, function, vector, slot, state)) {
2013 return; 2057 return;
2014 } 2058 }
2015 2059
2016 vector->set(slot->value(), *function); 2060 vector->Set(slot, *function);
2017 } 2061 }
2018 2062
2019 if (function->IsJSFunction()) { 2063 if (function->IsJSFunction()) {
2020 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); 2064 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2021 name = handle(js_function->shared()->name(), isolate()); 2065 name = handle(js_function->shared()->name(), isolate());
2022 } 2066 }
2023 2067
2024 IC::State new_state = FeedbackToState(vector, slot); 2068 IC::State new_state = FeedbackToState(isolate(), *vector, slot);
2025 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 2069 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state);
2026 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); 2070 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
2027 } 2071 }
2028 2072
2029 2073
2030 #undef TRACE_IC 2074 #undef TRACE_IC
2031 2075
2032 2076
2033 // ---------------------------------------------------------------------------- 2077 // ----------------------------------------------------------------------------
2034 // Static IC stub generators. 2078 // Static IC stub generators.
2035 // 2079 //
2036 2080
2037 // Used from ic-<arch>.cc. 2081 // Used from ic-<arch>.cc.
2038 RUNTIME_FUNCTION(CallIC_Miss) { 2082 RUNTIME_FUNCTION(CallIC_Miss) {
2039 TimerEventScope<TimerEventIcMiss> timer(isolate); 2083 TimerEventScope<TimerEventIcMiss> timer(isolate);
2040 HandleScope scope(isolate); 2084 HandleScope scope(isolate);
2041 DCHECK(args.length() == 4); 2085 DCHECK(args.length() == 4);
2042 CallIC ic(isolate); 2086 CallIC ic(isolate);
2043 Handle<Object> receiver = args.at<Object>(0); 2087 Handle<Object> receiver = args.at<Object>(0);
2044 Handle<Object> function = args.at<Object>(1); 2088 Handle<Object> function = args.at<Object>(1);
2045 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); 2089 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
2046 Handle<Smi> slot = args.at<Smi>(3); 2090 Handle<Smi> slot = args.at<Smi>(3);
2047 ic.HandleMiss(receiver, function, vector, slot); 2091 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
2092 ic.HandleMiss(receiver, function, vector, vector_slot);
2048 return *function; 2093 return *function;
2049 } 2094 }
2050 2095
2051 2096
2052 RUNTIME_FUNCTION(CallIC_Customization_Miss) { 2097 RUNTIME_FUNCTION(CallIC_Customization_Miss) {
2053 TimerEventScope<TimerEventIcMiss> timer(isolate); 2098 TimerEventScope<TimerEventIcMiss> timer(isolate);
2054 HandleScope scope(isolate); 2099 HandleScope scope(isolate);
2055 DCHECK(args.length() == 4); 2100 DCHECK(args.length() == 4);
2056 // A miss on a custom call ic always results in going megamorphic. 2101 // A miss on a custom call ic always results in going megamorphic.
2057 CallIC ic(isolate); 2102 CallIC ic(isolate);
2058 Handle<Object> function = args.at<Object>(1); 2103 Handle<Object> function = args.at<Object>(1);
2059 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); 2104 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
2060 Handle<Smi> slot = args.at<Smi>(3); 2105 Handle<Smi> slot = args.at<Smi>(3);
2061 ic.PatchMegamorphic(function, vector, slot); 2106 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
2107 ic.PatchMegamorphic(function, vector, vector_slot);
2062 return *function; 2108 return *function;
2063 } 2109 }
2064 2110
2065 2111
2066 // Used from ic-<arch>.cc. 2112 // Used from ic-<arch>.cc.
2067 RUNTIME_FUNCTION(LoadIC_Miss) { 2113 RUNTIME_FUNCTION(LoadIC_Miss) {
2068 TimerEventScope<TimerEventIcMiss> timer(isolate); 2114 TimerEventScope<TimerEventIcMiss> timer(isolate);
2069 HandleScope scope(isolate); 2115 HandleScope scope(isolate);
2070 DCHECK(args.length() == 2); 2116 DCHECK(args.length() == 2);
2071 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2117 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after
2690 static const Address IC_utilities[] = { 2736 static const Address IC_utilities[] = {
2691 #define ADDR(name) FUNCTION_ADDR(name), 2737 #define ADDR(name) FUNCTION_ADDR(name),
2692 IC_UTIL_LIST(ADDR) NULL 2738 IC_UTIL_LIST(ADDR) NULL
2693 #undef ADDR 2739 #undef ADDR
2694 }; 2740 };
2695 2741
2696 2742
2697 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } 2743 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; }
2698 } 2744 }
2699 } // namespace v8::internal 2745 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698