Chromium Code Reviews| 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 Code* new_target = raw_target(); | 92 State new_state = |
| 93 State new_state = new_target->ic_state(); | 93 UseVector() ? nexus()->StateFromFeedback() : raw_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 | |
| 137 #define TRACE_IC(type, name) TraceIC(type, name) | 138 #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) | |
| 140 | 139 |
| 141 IC::IC(FrameDepth depth, Isolate* isolate) | 140 |
| 142 : isolate_(isolate), target_set_(false), target_maps_set_(false) { | 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) { | |
| 143 // To improve the performance of the (much used) IC code, we unfold a few | 147 // To improve the performance of the (much used) IC code, we unfold a few |
| 144 // levels of the stack frame iteration code. This yields a ~35% speedup when | 148 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 145 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 149 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 146 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); | 150 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); |
| 147 Address constant_pool = NULL; | 151 Address constant_pool = NULL; |
| 148 if (FLAG_enable_ool_constant_pool) { | 152 if (FLAG_enable_ool_constant_pool) { |
| 149 constant_pool = | 153 constant_pool = |
| 150 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); | 154 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset); |
| 151 } | 155 } |
| 152 Address* pc_address = | 156 Address* pc_address = |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 171 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); | 175 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); |
| 172 #endif | 176 #endif |
| 173 fp_ = fp; | 177 fp_ = fp; |
| 174 if (FLAG_enable_ool_constant_pool) { | 178 if (FLAG_enable_ool_constant_pool) { |
| 175 raw_constant_pool_ = handle( | 179 raw_constant_pool_ = handle( |
| 176 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), | 180 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), |
| 177 isolate); | 181 isolate); |
| 178 } | 182 } |
| 179 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 183 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
| 180 target_ = handle(raw_target(), isolate); | 184 target_ = handle(raw_target(), isolate); |
| 181 state_ = target_->ic_state(); | |
| 182 kind_ = target_->kind(); | 185 kind_ = target_->kind(); |
| 186 state_ = (!for_queries_only && UseVector()) ? nexus->StateFromFeedback() | |
| 187 : target_->ic_state(); | |
| 188 old_state_ = state_; | |
| 183 extra_ic_state_ = target_->extra_ic_state(); | 189 extra_ic_state_ = target_->extra_ic_state(); |
| 184 } | 190 } |
| 185 | 191 |
| 186 | 192 |
| 187 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { | 193 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { |
| 188 // Compute the JavaScript frame for the frame pointer of this IC | 194 // Compute the JavaScript frame for the frame pointer of this IC |
| 189 // structure. We need this to be able to find the function | 195 // structure. We need this to be able to find the function |
| 190 // corresponding to the frame. | 196 // corresponding to the frame. |
| 191 StackFrameIterator it(isolate()); | 197 StackFrameIterator it(isolate()); |
| 192 while (it.frame()->fp() != this->fp()) it.Advance(); | 198 while (it.frame()->fp() != this->fp()) it.Advance(); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 info->change_own_type_change_checksum(); | 418 info->change_own_type_change_checksum(); |
| 413 } | 419 } |
| 414 host->set_profiler_ticks(0); | 420 host->set_profiler_ticks(0); |
| 415 isolate->runtime_profiler()->NotifyICChanged(); | 421 isolate->runtime_profiler()->NotifyICChanged(); |
| 416 // TODO(2029): When an optimized function is patched, it would | 422 // TODO(2029): When an optimized function is patched, it would |
| 417 // be nice to propagate the corresponding type information to its | 423 // be nice to propagate the corresponding type information to its |
| 418 // unoptimized version for the benefit of later inlining. | 424 // unoptimized version for the benefit of later inlining. |
| 419 } | 425 } |
| 420 | 426 |
| 421 | 427 |
| 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 | |
| 422 void IC::PostPatching(Address address, Code* target, Code* old_target) { | 452 void IC::PostPatching(Address address, Code* target, Code* old_target) { |
| 423 // Type vector based ICs update these statistics at a different time because | 453 // Type vector based ICs update these statistics at a different time because |
| 424 // they don't always patch on state change. | 454 // they don't always patch on state change. |
| 425 if (target->kind() == Code::CALL_IC) return; | 455 if (target->kind() == Code::CALL_IC) return; |
| 426 | 456 |
| 427 Isolate* isolate = target->GetHeap()->isolate(); | 457 Isolate* isolate = target->GetHeap()->isolate(); |
| 428 State old_state = UNINITIALIZED; | 458 State old_state = UNINITIALIZED; |
| 429 State new_state = UNINITIALIZED; | 459 State new_state = UNINITIALIZED; |
| 430 bool target_remains_ic_stub = false; | 460 bool target_remains_ic_stub = false; |
| 431 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { | 461 if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 // Clearing these is tricky and does not | 531 // Clearing these is tricky and does not |
| 502 // make any performance difference. | 532 // make any performance difference. |
| 503 return; | 533 return; |
| 504 default: | 534 default: |
| 505 UNREACHABLE(); | 535 UNREACHABLE(); |
| 506 } | 536 } |
| 507 } | 537 } |
| 508 | 538 |
| 509 | 539 |
| 510 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, | 540 void IC::Clear(Isolate* isolate, Code::Kind kind, Code* host, |
| 511 TypeFeedbackVector* vector, FeedbackVectorICSlot slot) { | 541 FeedbackNexus* nexus) { |
| 512 switch (kind) { | 542 switch (kind) { |
| 513 case Code::CALL_IC: | 543 case Code::CALL_IC: |
| 514 return CallIC::Clear(isolate, host, vector, slot); | 544 return CallIC::Clear(isolate, host, |
| 545 reinterpret_cast<CallICNexus*>(nexus)); | |
|
Igor Sheludko
2014/10/28 11:12:36
static_cast?
mvstanton
2014/10/28 13:23:28
I hated the cast anyway, so I've changed this to a
| |
| 515 default: | 546 default: |
| 516 UNREACHABLE(); | 547 UNREACHABLE(); |
| 517 } | 548 } |
| 518 } | 549 } |
| 519 | 550 |
| 520 | 551 |
| 521 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, | 552 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target, |
| 522 ConstantPoolArray* constant_pool) { | 553 ConstantPoolArray* constant_pool) { |
| 523 if (IsCleared(target)) return; | 554 if (IsCleared(target)) return; |
| 524 | 555 |
| 525 // Make sure to also clear the map used in inline fast cases. If we | 556 // Make sure to also clear the map used in inline fast cases. If we |
| 526 // do not clear these maps, cached code can keep objects alive | 557 // do not clear these maps, cached code can keep objects alive |
| 527 // through the embedded maps. | 558 // through the embedded maps. |
| 528 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 559 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
| 529 } | 560 } |
| 530 | 561 |
| 531 | 562 |
| 532 void CallIC::Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector, | 563 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) { |
| 533 FeedbackVectorICSlot slot) { | |
| 534 DCHECK(vector != NULL && !slot.IsInvalid()); | |
| 535 Object* feedback = vector->Get(slot); | |
| 536 // Determine our state. | 564 // Determine our state. |
| 537 State state = FeedbackToState(isolate, vector, slot); | 565 Object* feedback = nexus->vector()->Get(nexus->slot()); |
| 566 State state = nexus->StateFromFeedback(); | |
| 538 | 567 |
| 539 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { | 568 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) { |
| 540 vector->Set(slot, isolate->heap()->uninitialized_symbol(), | 569 nexus->ConfigureUninitialized(); |
|
Igor Sheludko
2014/10/28 11:12:36
Does it make sense to proceed skipping write barri
mvstanton
2014/10/28 13:23:28
It does indeed, I've make that fix in type-feedbac
| |
| 541 SKIP_WRITE_BARRIER); | |
| 542 // The change in state must be processed. | 570 // The change in state must be processed. |
| 543 OnTypeFeedbackChanged(isolate, host, vector, state, UNINITIALIZED); | 571 OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED); |
| 544 } | 572 } |
| 545 } | 573 } |
| 546 | 574 |
| 547 | 575 |
| 548 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, | 576 void LoadIC::Clear(Isolate* isolate, Address address, Code* target, |
| 549 ConstantPoolArray* constant_pool) { | 577 ConstantPoolArray* constant_pool) { |
| 550 if (IsCleared(target)) return; | 578 if (IsCleared(target)) return; |
| 551 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, | 579 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, |
| 552 target->extra_ic_state()); | 580 target->extra_ic_state()); |
| 553 SetTargetAtAddress(address, code, constant_pool); | 581 SetTargetAtAddress(address, code, constant_pool); |
| (...skipping 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1933 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); | 1961 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); |
| 1934 } | 1962 } |
| 1935 DCHECK(!stub.is_null()); | 1963 DCHECK(!stub.is_null()); |
| 1936 set_target(*stub); | 1964 set_target(*stub); |
| 1937 TRACE_IC("StoreIC", key); | 1965 TRACE_IC("StoreIC", key); |
| 1938 | 1966 |
| 1939 return store_handle; | 1967 return store_handle; |
| 1940 } | 1968 } |
| 1941 | 1969 |
| 1942 | 1970 |
| 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 | |
| 1967 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, | 1971 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function, |
| 1968 Handle<TypeFeedbackVector> vector, | 1972 const CallICState& callic_state) { |
| 1969 FeedbackVectorICSlot slot, | |
| 1970 const CallICState& state) { | |
| 1971 DCHECK(FLAG_use_ic && function->IsJSFunction()); | 1973 DCHECK(FLAG_use_ic && function->IsJSFunction()); |
| 1972 | 1974 |
| 1973 // Are we the array function? | 1975 // Are we the array function? |
| 1974 Handle<JSFunction> array_function = | 1976 Handle<JSFunction> array_function = |
| 1975 Handle<JSFunction>(isolate()->native_context()->array_function()); | 1977 Handle<JSFunction>(isolate()->native_context()->array_function()); |
| 1976 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { | 1978 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { |
| 1977 // Alter the slot. | 1979 // Alter the slot. |
| 1978 IC::State old_state = FeedbackToState(isolate(), *vector, slot); | 1980 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
| 1979 Object* feedback = vector->Get(slot); | 1981 nexus->ConfigureMonomorphicArray(); |
| 1980 if (!feedback->IsAllocationSite()) { | |
| 1981 Handle<AllocationSite> new_site = | |
| 1982 isolate()->factory()->NewAllocationSite(); | |
| 1983 vector->Set(slot, *new_site); | |
| 1984 } | |
| 1985 | 1982 |
| 1986 CallIC_ArrayStub stub(isolate(), state); | 1983 CallIC_ArrayStub stub(isolate(), callic_state); |
| 1987 set_target(*stub.GetCode()); | 1984 set_target(*stub.GetCode()); |
| 1988 Handle<String> name; | 1985 Handle<String> name; |
| 1989 if (array_function->shared()->name()->IsString()) { | 1986 if (array_function->shared()->name()->IsString()) { |
| 1990 name = Handle<String>(String::cast(array_function->shared()->name()), | 1987 name = Handle<String>(String::cast(array_function->shared()->name()), |
| 1991 isolate()); | 1988 isolate()); |
| 1992 } | 1989 } |
| 1993 | 1990 TRACE_IC("CallIC", name); |
| 1994 IC::State new_state = FeedbackToState(isolate(), *vector, slot); | 1991 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), |
| 1995 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); | 1992 MONOMORPHIC); |
| 1996 TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state); | |
| 1997 return true; | 1993 return true; |
| 1998 } | 1994 } |
| 1999 return false; | 1995 return false; |
| 2000 } | 1996 } |
| 2001 | 1997 |
| 2002 | 1998 |
| 2003 void CallIC::PatchMegamorphic(Handle<Object> function, | 1999 void CallIC::PatchMegamorphic(Handle<Object> function) { |
| 2004 Handle<TypeFeedbackVector> vector, | 2000 CallICState callic_state(target()->extra_ic_state()); |
| 2005 FeedbackVectorICSlot slot) { | |
| 2006 CallICState state(target()->extra_ic_state()); | |
| 2007 IC::State old_state = FeedbackToState(isolate(), *vector, slot); | |
| 2008 | 2001 |
| 2009 // We are going generic. | 2002 // We are going generic. |
| 2010 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()), | 2003 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
| 2011 SKIP_WRITE_BARRIER); | 2004 nexus->ConfigureGeneric(); |
| 2012 | 2005 |
| 2013 CallICStub stub(isolate(), state); | 2006 CallICStub stub(isolate(), callic_state); |
| 2014 Handle<Code> code = stub.GetCode(); | 2007 Handle<Code> code = stub.GetCode(); |
| 2015 set_target(*code); | 2008 set_target(*code); |
| 2016 | 2009 |
| 2017 Handle<Object> name = isolate()->factory()->empty_string(); | 2010 Handle<Object> name = isolate()->factory()->empty_string(); |
| 2018 if (function->IsJSFunction()) { | 2011 if (function->IsJSFunction()) { |
| 2019 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2012 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
| 2020 name = handle(js_function->shared()->name(), isolate()); | 2013 name = handle(js_function->shared()->name(), isolate()); |
| 2021 } | 2014 } |
| 2022 | 2015 |
| 2023 IC::State new_state = FeedbackToState(isolate(), *vector, slot); | 2016 TRACE_IC("CallIC", name); |
| 2024 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); | 2017 OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(), |
| 2025 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); | 2018 GENERIC); |
| 2026 } | 2019 } |
| 2027 | 2020 |
| 2028 | 2021 |
| 2029 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function, | 2022 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function) { |
| 2030 Handle<TypeFeedbackVector> vector, | 2023 CallICState callic_state(target()->extra_ic_state()); |
| 2031 FeedbackVectorICSlot slot) { | |
| 2032 CallICState state(target()->extra_ic_state()); | |
| 2033 IC::State old_state = FeedbackToState(isolate(), *vector, slot); | |
| 2034 Handle<Object> name = isolate()->factory()->empty_string(); | 2024 Handle<Object> name = isolate()->factory()->empty_string(); |
| 2035 Object* feedback = vector->Get(slot); | 2025 CallICNexus* nexus = casted_nexus<CallICNexus>(); |
| 2026 Object* feedback = nexus->GetFeedback(); | |
| 2036 | 2027 |
| 2037 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. | 2028 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. |
| 2038 DCHECK(!feedback->IsSmi()); | 2029 DCHECK(!feedback->IsSmi()); |
| 2039 | 2030 |
| 2040 if (feedback->IsJSFunction() || !function->IsJSFunction()) { | 2031 if (feedback->IsJSFunction() || !function->IsJSFunction()) { |
| 2041 // We are going generic. | 2032 // We are going generic. |
| 2042 vector->Set(slot, *TypeFeedbackVector::MegamorphicSentinel(isolate()), | 2033 nexus->ConfigureGeneric(); |
| 2043 SKIP_WRITE_BARRIER); | |
| 2044 } else { | 2034 } else { |
| 2045 // The feedback is either uninitialized or an allocation site. | 2035 // The feedback is either uninitialized or an allocation site. |
| 2046 // It might be an allocation site because if we re-compile the full code | 2036 // It might be an allocation site because if we re-compile the full code |
| 2047 // to add deoptimization support, we call with the default call-ic, and | 2037 // to add deoptimization support, we call with the default call-ic, and |
| 2048 // merely need to patch the target to match the feedback. | 2038 // merely need to patch the target to match the feedback. |
| 2049 // TODO(mvstanton): the better approach is to dispense with patching | 2039 // TODO(mvstanton): the better approach is to dispense with patching |
| 2050 // altogether, which is in progress. | 2040 // altogether, which is in progress. |
| 2051 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || | 2041 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) || |
| 2052 feedback->IsAllocationSite()); | 2042 feedback->IsAllocationSite()); |
| 2053 | 2043 |
| 2054 // Do we want to install a custom handler? | 2044 // Do we want to install a custom handler? |
| 2055 if (FLAG_use_ic && | 2045 if (FLAG_use_ic && DoCustomHandler(receiver, function, callic_state)) { |
| 2056 DoCustomHandler(receiver, function, vector, slot, state)) { | |
| 2057 return; | 2046 return; |
| 2058 } | 2047 } |
| 2059 | 2048 |
| 2060 vector->Set(slot, *function); | 2049 nexus->ConfigureMonomorphic(Handle<JSFunction>::cast(function)); |
| 2061 } | 2050 } |
| 2062 | 2051 |
| 2063 if (function->IsJSFunction()) { | 2052 if (function->IsJSFunction()) { |
| 2064 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 2053 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
| 2065 name = handle(js_function->shared()->name(), isolate()); | 2054 name = handle(js_function->shared()->name(), isolate()); |
| 2066 } | 2055 } |
| 2067 | 2056 |
| 2068 IC::State new_state = FeedbackToState(isolate(), *vector, slot); | 2057 IC::State new_state = nexus->StateFromFeedback(); |
| 2069 OnTypeFeedbackChanged(isolate(), get_host(), *vector, old_state, new_state); | 2058 OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state); |
| 2070 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); | 2059 TRACE_IC("CallIC", name); |
| 2071 } | 2060 } |
| 2072 | 2061 |
| 2073 | 2062 |
| 2074 #undef TRACE_IC | 2063 #undef TRACE_IC |
| 2075 | 2064 |
| 2076 | 2065 |
| 2077 // ---------------------------------------------------------------------------- | 2066 // ---------------------------------------------------------------------------- |
| 2078 // Static IC stub generators. | 2067 // Static IC stub generators. |
| 2079 // | 2068 // |
| 2080 | 2069 |
| 2081 // Used from ic-<arch>.cc. | 2070 // Used from ic-<arch>.cc. |
| 2082 RUNTIME_FUNCTION(CallIC_Miss) { | 2071 RUNTIME_FUNCTION(CallIC_Miss) { |
| 2083 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2072 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2084 HandleScope scope(isolate); | 2073 HandleScope scope(isolate); |
| 2085 DCHECK(args.length() == 4); | 2074 DCHECK(args.length() == 4); |
| 2086 CallIC ic(isolate); | |
| 2087 Handle<Object> receiver = args.at<Object>(0); | 2075 Handle<Object> receiver = args.at<Object>(0); |
| 2088 Handle<Object> function = args.at<Object>(1); | 2076 Handle<Object> function = args.at<Object>(1); |
| 2089 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 2077 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
| 2090 Handle<Smi> slot = args.at<Smi>(3); | 2078 Handle<Smi> slot = args.at<Smi>(3); |
| 2091 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2079 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2092 ic.HandleMiss(receiver, function, vector, vector_slot); | 2080 CallICNexus nexus(vector, vector_slot); |
| 2081 CallIC ic(isolate, &nexus); | |
| 2082 ic.HandleMiss(receiver, function); | |
| 2093 return *function; | 2083 return *function; |
| 2094 } | 2084 } |
| 2095 | 2085 |
| 2096 | 2086 |
| 2097 RUNTIME_FUNCTION(CallIC_Customization_Miss) { | 2087 RUNTIME_FUNCTION(CallIC_Customization_Miss) { |
| 2098 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2088 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2099 HandleScope scope(isolate); | 2089 HandleScope scope(isolate); |
| 2100 DCHECK(args.length() == 4); | 2090 DCHECK(args.length() == 4); |
| 2101 // A miss on a custom call ic always results in going megamorphic. | 2091 // A miss on a custom call ic always results in going megamorphic. |
|
Igor Sheludko
2014/10/28 11:12:36
This comment can be removed from here.
mvstanton
2014/10/28 13:23:28
Done.
| |
| 2102 CallIC ic(isolate); | |
| 2103 Handle<Object> function = args.at<Object>(1); | 2092 Handle<Object> function = args.at<Object>(1); |
| 2104 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); | 2093 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); |
| 2105 Handle<Smi> slot = args.at<Smi>(3); | 2094 Handle<Smi> slot = args.at<Smi>(3); |
| 2106 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); | 2095 FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); |
| 2107 ic.PatchMegamorphic(function, vector, vector_slot); | 2096 CallICNexus nexus(vector, vector_slot); |
| 2097 // A miss on a custom call ic always results in going megamorphic. | |
| 2098 CallIC ic(isolate, &nexus); | |
| 2099 ic.PatchMegamorphic(function); | |
| 2108 return *function; | 2100 return *function; |
| 2109 } | 2101 } |
| 2110 | 2102 |
| 2111 | 2103 |
| 2112 // Used from ic-<arch>.cc. | 2104 // Used from ic-<arch>.cc. |
| 2113 RUNTIME_FUNCTION(LoadIC_Miss) { | 2105 RUNTIME_FUNCTION(LoadIC_Miss) { |
| 2114 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2106 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2115 HandleScope scope(isolate); | 2107 HandleScope scope(isolate); |
| 2116 DCHECK(args.length() == 2); | 2108 DCHECK(args.length() == 2); |
| 2117 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2109 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[] = { | 2728 static const Address IC_utilities[] = { |
| 2737 #define ADDR(name) FUNCTION_ADDR(name), | 2729 #define ADDR(name) FUNCTION_ADDR(name), |
| 2738 IC_UTIL_LIST(ADDR) NULL | 2730 IC_UTIL_LIST(ADDR) NULL |
| 2739 #undef ADDR | 2731 #undef ADDR |
| 2740 }; | 2732 }; |
| 2741 | 2733 |
| 2742 | 2734 |
| 2743 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2735 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 2744 } | 2736 } |
| 2745 } // namespace v8::internal | 2737 } // namespace v8::internal |
| OLD | NEW |