OLD | NEW |
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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 PrintF("[%s patching generic stub in ", type); \ | 82 PrintF("[%s patching generic stub in ", type); \ |
83 PrintF("(see below) (%s)]\n", reason); \ | 83 PrintF("(see below) (%s)]\n", reason); \ |
84 } \ | 84 } \ |
85 } while (false) | 85 } while (false) |
86 | 86 |
87 #endif // DEBUG | 87 #endif // DEBUG |
88 | 88 |
89 | 89 |
90 void IC::TraceIC(const char* type, Handle<Object> name) { | 90 void IC::TraceIC(const char* type, Handle<Object> name) { |
91 if (FLAG_trace_ic) { | 91 if (FLAG_trace_ic) { |
92 State new_state = | 92 Code* new_target = raw_target(); |
93 UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state(); | 93 State new_state = new_target->ic_state(); |
94 TraceIC(type, name, state(), new_state); | 94 TraceIC(type, name, state(), new_state); |
95 } | 95 } |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 void IC::TraceIC(const char* type, Handle<Object> name, State old_state, | 99 void IC::TraceIC(const char* type, Handle<Object> name, State old_state, |
100 State new_state) { | 100 State new_state) { |
101 if (FLAG_trace_ic) { | 101 if (FLAG_trace_ic) { |
102 Code* new_target = raw_target(); | 102 Code* new_target = raw_target(); |
103 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); | 103 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); |
(...skipping 23 matching lines...) Expand all Loading... |
127 #ifdef OBJECT_PRINT | 127 #ifdef OBJECT_PRINT |
128 OFStream os(stdout); | 128 OFStream os(stdout); |
129 name->Print(os); | 129 name->Print(os); |
130 #else | 130 #else |
131 name->ShortPrint(stdout); | 131 name->ShortPrint(stdout); |
132 #endif | 132 #endif |
133 PrintF("]\n"); | 133 PrintF("]\n"); |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
| 137 #define TRACE_IC(type, name) TraceIC(type, name) |
| 138 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \ |
| 139 TraceIC(type, name, old_state, new_state) |
137 | 140 |
138 #define TRACE_IC(type, name) TraceIC(type, name) | 141 IC::IC(FrameDepth depth, Isolate* isolate) |
139 | 142 : isolate_(isolate), target_set_(false), target_maps_set_(false) { |
140 | |
141 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus, | |
142 bool for_queries_only) | |
143 : isolate_(isolate), | |
144 target_set_(false), | |
145 target_maps_set_(false), | |
146 nexus_(nexus) { | |
147 // To improve the performance of the (much used) IC code, we unfold a few | 143 // To improve the performance of the (much used) IC code, we unfold a few |
148 // levels of the stack frame iteration code. This yields a ~35% speedup when | 144 // levels of the stack frame iteration code. This yields a ~35% speedup when |
149 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 145 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
150 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); | 146 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); |
151 Address constant_pool = NULL; | 147 Address constant_pool = NULL; |
152 if (FLAG_enable_ool_constant_pool) { | 148 if (FLAG_enable_ool_constant_pool) { |
153 constant_pool = | 149 constant_pool = |
154 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); | 150 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); |
155 } | 151 } |
156 Address* pc_address = | 152 Address* pc_address = |
(...skipping 18 matching lines...) Expand all Loading... |
175 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); | 171 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); |
176 #endif | 172 #endif |
177 fp_ = fp; | 173 fp_ = fp; |
178 if (FLAG_enable_ool_constant_pool) { | 174 if (FLAG_enable_ool_constant_pool) { |
179 raw_constant_pool_ = handle( | 175 raw_constant_pool_ = handle( |
180 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), | 176 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), |
181 isolate); | 177 isolate); |
182 } | 178 } |
183 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 179 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
184 target_ = handle(raw_target(), isolate); | 180 target_ = handle(raw_target(), isolate); |
| 181 state_ = target_->ic_state(); |
185 kind_ = target_->kind(); | 182 kind_ = target_->kind(); |
186 state_ = (!for_queries_only && UseVector()) ? nexus->StateFromFeedback() | |
187 : target_->ic_state(); | |
188 old_state_ = state_; | |
189 extra_ic_state_ = target_->extra_ic_state(); | 183 extra_ic_state_ = target_->extra_ic_state(); |
190 } | 184 } |
191 | 185 |
192 | 186 |
193 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { | 187 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { |
194 // Compute the JavaScript frame for the frame pointer of this IC | 188 // Compute the JavaScript frame for the frame pointer of this IC |
195 // structure. We need this to be able to find the function | 189 // structure. We need this to be able to find the function |
196 // corresponding to the frame. | 190 // corresponding to the frame. |
197 StackFrameIterator it(isolate()); | 191 StackFrameIterator it(isolate()); |
198 while (it.frame()->fp() != this->fp()) it.Advance(); | 192 while (it.frame()->fp() != this->fp()) it.Advance(); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 info->change_own_type_change_checksum(); | 412 info->change_own_type_change_checksum(); |
419 } | 413 } |
420 host->set_profiler_ticks(0); | 414 host->set_profiler_ticks(0); |
421 isolate->runtime_profiler()->NotifyICChanged(); | 415 isolate->runtime_profiler()->NotifyICChanged(); |
422 // TODO(2029): When an optimized function is patched, it would | 416 // TODO(2029): When an optimized function is patched, it would |
423 // be nice to propagate the corresponding type information to its | 417 // be nice to propagate the corresponding type information to its |
424 // unoptimized version for the benefit of later inlining. | 418 // unoptimized version for the benefit of later inlining. |
425 } | 419 } |
426 | 420 |
427 | 421 |
428 // static | |
429 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host, | |
430 TypeFeedbackVector* vector, State old_state, | |
431 State new_state) { | |
432 if (host->kind() != Code::FUNCTION) return; | |
433 | |
434 if (FLAG_type_info_threshold > 0) { | |
435 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. | |
436 int generic_delta = 0; // "Generic" here includes megamorphic. | |
437 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, | |
438 &generic_delta); | |
439 vector->change_ic_with_type_info_count(polymorphic_delta); | |
440 vector->change_ic_generic_count(generic_delta); | |
441 } | |
442 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); | |
443 info->change_own_type_change_checksum(); | |
444 host->set_profiler_ticks(0); | |
445 isolate->runtime_profiler()->NotifyICChanged(); | |
446 // TODO(2029): When an optimized function is patched, it would | |
447 // be nice to propagate the corresponding type information to its | |
448 // unoptimized version for the benefit of later inlining. | |
449 } | |
450 | |
451 | |
452 void IC::PostPatching(Address address, Code* target, Code* old_target) { | 422 void IC::PostPatching(Address address, Code* target, Code* old_target) { |
453 // Type vector based ICs update these statistics at a different time because | 423 // Type vector based ICs update these statistics at a different time because |
454 // they don't always patch on state change. | 424 // they don't always patch on state change. |
455 if (target->kind() == Code::CALL_IC) return; | 425 if (target->kind() == Code::CALL_IC) return; |
456 | 426 |
457 Isolate* isolate = target->GetHeap()->isolate(); | 427 Isolate* isolate = target->GetHeap()->isolate(); |
458 State old_state = UNINITIALIZED; | 428 State old_state = UNINITIALIZED; |
459 State new_state = UNINITIALIZED; | 429 State new_state = UNINITIALIZED; |
460 bool target_remains_ic_stub = false; | 430 bool target_remains_ic_stub = false; |
461 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { | 431 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 case Code::TO_BOOLEAN_IC: | 500 case Code::TO_BOOLEAN_IC: |
531 // Clearing these is tricky and does not | 501 // Clearing these is tricky and does not |
532 // make any performance difference. | 502 // make any performance difference. |
533 return; | 503 return; |
534 default: | 504 default: |
535 UNREACHABLE(); | 505 UNREACHABLE(); |
536 } | 506 } |
537 } | 507 } |
538 | 508 |
539 | 509 |
540 template <class Nexus> | 510 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, |
541 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, Nexus* nexus) { | 511 TypeFeedbackVector* vector, FeedbackVectorICSlot slot) { |
542 switch (kind) { | 512 switch (kind) { |
543 case Code::CALL_IC: | 513 case Code::CALL_IC: |
544 return CallIC::Clear(isolate, host, nexus); | 514 return CallIC::Clear(isolate, host, vector, slot); |
545 default: | 515 default: |
546 UNREACHABLE(); | 516 UNREACHABLE(); |
547 } | 517 } |
548 } | 518 } |
549 | 519 |
550 | 520 |
551 // Force instantiation of template instances for vector-based IC clearing. | |
552 template void IC::Clear(Isolate*, Code::Kind, Code*, CallICNexus*); | |
553 | |
554 | |
555 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 521 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, |
556 ConstantPoolArray* constant_pool) { | 522 ConstantPoolArray* constant_pool) { |
557 if (IsCleared(target)) return; | 523 if (IsCleared(target)) return; |
558 | 524 |
559 // 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 |
560 // do not clear these maps, cached code can keep objects alive | 526 // do not clear these maps, cached code can keep objects alive |
561 // through the embedded maps. | 527 // through the embedded maps. |
562 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 528 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
563 } | 529 } |
564 | 530 |
565 | 531 |
566 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { | 532 void CallIC::Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector, |
| 533 FeedbackVectorICSlot slot) { |
| 534 DCHECK(vector != NULL && !slot.IsInvalid()); |
| 535 Object* feedback = vector->Get(slot); |
567 // Determine our state. | 536 // Determine our state. |
568 Object* feedback = nexus->vector()->Get(nexus->slot()); | 537 State state = FeedbackToState(isolate, vector, slot); |
569 State state = nexus->StateFromFeedback(); | |
570 | 538 |
571 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 539 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
572 nexus->ConfigureUninitialized(); | 540 vector->Set(slot, isolate->heap()->uninitialized_symbol(), |
| 541 SKIP_WRITE_BARRIER); |
573 // The change in state must be processed. | 542 // The change in state must be processed. |
574 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); | 543 OnTypeFeedbackChanged(isolate, host, vector, state, UNINITIALIZED); |
575 } | 544 } |
576 } | 545 } |
577 | 546 |
578 | 547 |
579 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 548 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, |
580 ConstantPoolArray* constant_pool) { | 549 ConstantPoolArray* constant_pool) { |
581 if (IsCleared(target)) return; | 550 if (IsCleared(target)) return; |
582 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | 551 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, |
583 target->extra_ic_state()); | 552 target->extra_ic_state()); |
584 SetTargetAtAddress(address, code, constant_pool); | 553 SetTargetAtAddress(address, code, constant_pool); |
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1970 } | 1939 } |
1971 | 1940 |
1972 | 1941 |
1973 // static | 1942 // static |
1974 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 1943 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
1975 StrictMode strict_mode) { | 1944 StrictMode strict_mode) { |
1976 PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); | 1945 PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); |
1977 } | 1946 } |
1978 | 1947 |
1979 | 1948 |
| 1949 // static |
| 1950 void CallIC::OnTypeFeedbackChanged(Isolate* isolate, Code* host, |
| 1951 TypeFeedbackVector* vector, State old_state, |
| 1952 State new_state) { |
| 1953 if (host->kind() != Code::FUNCTION) return; |
| 1954 |
| 1955 if (FLAG_type_info_threshold > 0) { |
| 1956 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. |
| 1957 int generic_delta = 0; // "Generic" here includes megamorphic. |
| 1958 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, |
| 1959 &generic_delta); |
| 1960 vector->change_ic_with_type_info_count(polymorphic_delta); |
| 1961 vector->change_ic_generic_count(generic_delta); |
| 1962 } |
| 1963 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 1964 info->change_own_type_change_checksum(); |
| 1965 host->set_profiler_ticks(0); |
| 1966 isolate->runtime_profiler()->NotifyICChanged(); |
| 1967 // TODO(2029): When an optimized function is patched, it would |
| 1968 // be nice to propagate the corresponding type information to its |
| 1969 // unoptimized version for the benefit of later inlining. |
| 1970 } |
| 1971 |
| 1972 |
1980 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, | 1973 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, |
1981 const CallICState& callic_state) { | 1974 Handle<TypeFeedbackVector> vector, |
| 1975 FeedbackVectorICSlot slot, |
| 1976 const CallICState& state) { |
1982 DCHECK(FLAG_use_ic && function->IsJSFunction()); | 1977 DCHECK(FLAG_use_ic && function->IsJSFunction()); |
1983 | 1978 |
1984 // Are we the array function? | 1979 // Are we the array function? |
1985 Handle<JSFunction> array_function = | 1980 Handle<JSFunction> array_function = |
1986 Handle<JSFunction>(isolate()->native_context()->array_function()); | 1981 Handle<JSFunction>(isolate()->native_context()->array_function()); |
1987 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { | 1982 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { |
1988 // Alter the slot. | 1983 // Alter the slot. |
1989 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 1984 IC::State old_state = FeedbackToState(isolate(), *vector, slot); |
1990 nexus->ConfigureMonomorphicArray(); | 1985 Object* feedback = vector->Get(slot); |
| 1986 if (!feedback->IsAllocationSite()) { |
| 1987 Handle<AllocationSite> new_site = |
| 1988 isolate()->factory()->NewAllocationSite(); |
| 1989 vector->Set(slot, *new_site); |
| 1990 } |
1991 | 1991 |
1992 CallIC_ArrayStub stub(isolate(), callic_state); | 1992 CallIC_ArrayStub stub(isolate(), state); |
1993 set_target(*stub.GetCode()); | 1993 set_target(*stub.GetCode()); |
1994 Handle<String> name; | 1994 Handle<String> name; |
1995 if (array_function->shared()->name()->IsString()) { | 1995 if (array_function->shared()->name()->IsString()) { |
1996 name = Handle<String>(String::cast(array_function->shared()->name()), | 1996 name = Handle<String>(String::cast(array_function->shared()->name()), |
1997 isolate()); | 1997 isolate()); |
1998 } | 1998 } |
1999 TRACE_IC("CallIC", name); | 1999 |
2000 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | 2000 IC::State new_state = FeedbackToState(isolate(), *vector, slot); |
2001 MONOMORPHIC); | 2001 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); |
| 2002 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state); |
2002 return true; | 2003 return true; |
2003 } | 2004 } |
2004 return false; | 2005 return false; |
2005 } | 2006 } |
2006 | 2007 |
2007 | 2008 |
2008 void CallIC::PatchMegamorphic(Handle<Object> function) { | 2009 void CallIC::PatchMegamorphic(Handle<Object> function, |
2009 CallICState callic_state(target()->extra_ic_state()); | 2010 Handle<TypeFeedbackVector> vector, |
| 2011 FeedbackVectorICSlot slot) { |
| 2012 CallICState state(target()->extra_ic_state()); |
| 2013 IC::State old_state = FeedbackToState(isolate(), *vector, slot); |
2010 | 2014 |
2011 // We are going generic. | 2015 // We are going generic. |
2012 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2016 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()), |
2013 nexus->ConfigureGeneric(); | 2017 SKIP_WRITE_BARRIER); |
2014 | 2018 |
2015 CallICStub stub(isolate(), callic_state); | 2019 CallICStub stub(isolate(), state); |
2016 Handle<Code> code = stub.GetCode(); | 2020 Handle<Code> code = stub.GetCode(); |
2017 set_target(*code); | 2021 set_target(*code); |
2018 | 2022 |
2019 Handle<Object> name = isolate()->factory()->empty_string(); | 2023 Handle<Object> name = isolate()->factory()->empty_string(); |
2020 if (function->IsJSFunction()) { | 2024 if (function->IsJSFunction()) { |
2021 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2025 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
2022 name = handle(js_function->shared()->name(), isolate()); | 2026 name = handle(js_function->shared()->name(), isolate()); |
2023 } | 2027 } |
2024 | 2028 |
2025 TRACE_IC("CallIC", name); | 2029 IC::State new_state = FeedbackToState(isolate(), *vector, slot); |
2026 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), | 2030 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); |
2027 GENERIC); | 2031 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); |
2028 } | 2032 } |
2029 | 2033 |
2030 | 2034 |
2031 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function) { | 2035 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, |
2032 CallICState callic_state(target()->extra_ic_state()); | 2036 Handle<TypeFeedbackVector> vector, |
| 2037 FeedbackVectorICSlot slot) { |
| 2038 CallICState state(target()->extra_ic_state()); |
| 2039 IC::State old_state = FeedbackToState(isolate(), *vector, slot); |
2033 Handle<Object> name = isolate()->factory()->empty_string(); | 2040 Handle<Object> name = isolate()->factory()->empty_string(); |
2034 CallICNexus* nexus = casted_nexus<CallICNexus>(); | 2041 Object* feedback = vector->Get(slot); |
2035 Object* feedback = nexus->GetFeedback(); | |
2036 | 2042 |
2037 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. | 2043 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. |
2038 DCHECK(!feedback->IsSmi()); | 2044 DCHECK(!feedback->IsSmi()); |
2039 | 2045 |
2040 if (feedback->IsJSFunction() || !function->IsJSFunction()) { | 2046 if (feedback->IsJSFunction() || !function->IsJSFunction()) { |
2041 // We are going generic. | 2047 // We are going generic. |
2042 nexus->ConfigureGeneric(); | 2048 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()), |
| 2049 SKIP_WRITE_BARRIER); |
2043 } else { | 2050 } else { |
2044 // The feedback is either uninitialized or an allocation site. | 2051 // The feedback is either uninitialized or an allocation site. |
2045 // It might be an allocation site because if we re-compile the full code | 2052 // It might be an allocation site because if we re-compile the full code |
2046 // to add deoptimization support, we call with the default call-ic, and | 2053 // to add deoptimization support, we call with the default call-ic, and |
2047 // merely need to patch the target to match the feedback. | 2054 // merely need to patch the target to match the feedback. |
2048 // TODO(mvstanton): the better approach is to dispense with patching | 2055 // TODO(mvstanton): the better approach is to dispense with patching |
2049 // altogether, which is in progress. | 2056 // altogether, which is in progress. |
2050 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || | 2057 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || |
2051 feedback->IsAllocationSite()); | 2058 feedback->IsAllocationSite()); |
2052 | 2059 |
2053 // Do we want to install a custom handler? | 2060 // Do we want to install a custom handler? |
2054 if (FLAG_use_ic && DoCustomHandler(receiver, function, callic_state)) { | 2061 if (FLAG_use_ic && |
| 2062 DoCustomHandler(receiver, function, vector, slot, state)) { |
2055 return; | 2063 return; |
2056 } | 2064 } |
2057 | 2065 |
2058 nexus->ConfigureMonomorphic(Handle<JSFunction>::cast(function)); | 2066 vector->Set(slot, *function); |
2059 } | 2067 } |
2060 | 2068 |
2061 if (function->IsJSFunction()) { | 2069 if (function->IsJSFunction()) { |
2062 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2070 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
2063 name = handle(js_function->shared()->name(), isolate()); | 2071 name = handle(js_function->shared()->name(), isolate()); |
2064 } | 2072 } |
2065 | 2073 |
2066 IC::State new_state = nexus->StateFromFeedback(); | 2074 IC::State new_state = FeedbackToState(isolate(), *vector, slot); |
2067 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); | 2075 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); |
2068 TRACE_IC("CallIC", name); | 2076 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); |
2069 } | 2077 } |
2070 | 2078 |
2071 | 2079 |
2072 #undef TRACE_IC | 2080 #undef TRACE_IC |
2073 | 2081 |
2074 | 2082 |
2075 // ---------------------------------------------------------------------------- | 2083 // ---------------------------------------------------------------------------- |
2076 // Static IC stub generators. | 2084 // Static IC stub generators. |
2077 // | 2085 // |
2078 | 2086 |
2079 // Used from ic-<arch>.cc. | 2087 // Used from ic-<arch>.cc. |
2080 RUNTIME_FUNCTION(CallIC_Miss) { | 2088 RUNTIME_FUNCTION(CallIC_Miss) { |
2081 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2089 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2082 HandleScope scope(isolate); | 2090 HandleScope scope(isolate); |
2083 DCHECK(args.length() == 4); | 2091 DCHECK(args.length() == 4); |
| 2092 CallIC ic(isolate); |
2084 Handle<Object> receiver = args.at<Object>(0); | 2093 Handle<Object> receiver = args.at<Object>(0); |
2085 Handle<Object> function = args.at<Object>(1); | 2094 Handle<Object> function = args.at<Object>(1); |
2086 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 2095 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
2087 Handle<Smi> slot = args.at<Smi>(3); | 2096 Handle<Smi> slot = args.at<Smi>(3); |
2088 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2097 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
2089 CallICNexus nexus(vector, vector_slot); | 2098 ic.HandleMiss(receiver, function, vector, vector_slot); |
2090 CallIC ic(isolate, &nexus); | |
2091 ic.HandleMiss(receiver, function); | |
2092 return *function; | 2099 return *function; |
2093 } | 2100 } |
2094 | 2101 |
2095 | 2102 |
2096 RUNTIME_FUNCTION(CallIC_Customization_Miss) { | 2103 RUNTIME_FUNCTION(CallIC_Customization_Miss) { |
2097 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2104 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2098 HandleScope scope(isolate); | 2105 HandleScope scope(isolate); |
2099 DCHECK(args.length() == 4); | 2106 DCHECK(args.length() == 4); |
| 2107 // A miss on a custom call ic always results in going megamorphic. |
| 2108 CallIC ic(isolate); |
2100 Handle<Object> function = args.at<Object>(1); | 2109 Handle<Object> function = args.at<Object>(1); |
2101 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 2110 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
2102 Handle<Smi> slot = args.at<Smi>(3); | 2111 Handle<Smi> slot = args.at<Smi>(3); |
2103 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2112 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
2104 CallICNexus nexus(vector, vector_slot); | 2113 ic.PatchMegamorphic(function, vector, vector_slot); |
2105 // A miss on a custom call ic always results in going megamorphic. | |
2106 CallIC ic(isolate, &nexus); | |
2107 ic.PatchMegamorphic(function); | |
2108 return *function; | 2114 return *function; |
2109 } | 2115 } |
2110 | 2116 |
2111 | 2117 |
2112 // Used from ic-<arch>.cc. | 2118 // Used from ic-<arch>.cc. |
2113 RUNTIME_FUNCTION(LoadIC_Miss) { | 2119 RUNTIME_FUNCTION(LoadIC_Miss) { |
2114 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2120 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2115 HandleScope scope(isolate); | 2121 HandleScope scope(isolate); |
2116 DCHECK(args.length() == 2); | 2122 DCHECK(args.length() == 2); |
2117 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2123 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2736 static const Address IC_utilities[] = { | 2742 static const Address IC_utilities[] = { |
2737 #define ADDR(name) FUNCTION_ADDR(name), | 2743 #define ADDR(name) FUNCTION_ADDR(name), |
2738 IC_UTIL_LIST(ADDR) NULL | 2744 IC_UTIL_LIST(ADDR) NULL |
2739 #undef ADDR | 2745 #undef ADDR |
2740 }; | 2746 }; |
2741 | 2747 |
2742 | 2748 |
2743 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2749 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
2744 } | 2750 } |
2745 } // namespace v8::internal | 2751 } // namespace v8::internal |
OLD | NEW |