| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "accessors.h" | 7 #include "accessors.h" |
| 8 #include "api.h" | 8 #include "api.h" |
| 9 #include "arguments.h" | 9 #include "arguments.h" |
| 10 #include "codegen.h" | 10 #include "codegen.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 Code* apply_builtin = isolate()->builtins()->builtin( | 61 Code* apply_builtin = isolate()->builtins()->builtin( |
| 62 Builtins::kFunctionApply); | 62 Builtins::kFunctionApply); |
| 63 if (raw_frame->unchecked_code() == apply_builtin) { | 63 if (raw_frame->unchecked_code() == apply_builtin) { |
| 64 PrintF("apply from "); | 64 PrintF("apply from "); |
| 65 it.Advance(); | 65 it.Advance(); |
| 66 raw_frame = it.frame(); | 66 raw_frame = it.frame(); |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 69 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 70 ExtraICState extra_state = new_target->extra_ic_state(); | 70 ExtraICState extra_state = new_target->extra_ic_state(); |
| 71 const char* modifier = | 71 const char* modifier = ""; |
| 72 GetTransitionMarkModifier( | 72 if (new_target->kind() == Code::KEYED_STORE_IC) { |
| 73 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | 73 modifier = GetTransitionMarkModifier( |
| 74 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
| 75 } |
| 74 PrintF(" (%c->%c%s)", | 76 PrintF(" (%c->%c%s)", |
| 75 TransitionMarkFromState(state()), | 77 TransitionMarkFromState(state()), |
| 76 TransitionMarkFromState(new_state), | 78 TransitionMarkFromState(new_state), |
| 77 modifier); | 79 modifier); |
| 78 name->Print(); | 80 name->Print(); |
| 79 PrintF("]\n"); | 81 PrintF("]\n"); |
| 80 } | 82 } |
| 81 } | 83 } |
| 82 | 84 |
| 83 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 85 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 Isolate* isolate = target->GetHeap()->isolate(); | 385 Isolate* isolate = target->GetHeap()->isolate(); |
| 384 Code* host = isolate-> | 386 Code* host = isolate-> |
| 385 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 387 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
| 386 if (host->kind() != Code::FUNCTION) return; | 388 if (host->kind() != Code::FUNCTION) return; |
| 387 | 389 |
| 388 if (FLAG_type_info_threshold > 0 && | 390 if (FLAG_type_info_threshold > 0 && |
| 389 old_target->is_inline_cache_stub() && | 391 old_target->is_inline_cache_stub() && |
| 390 target->is_inline_cache_stub()) { | 392 target->is_inline_cache_stub()) { |
| 391 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 393 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
| 392 target->ic_state()); | 394 target->ic_state()); |
| 395 // Call ICs don't have interesting state changes from this point |
| 396 // of view. |
| 397 ASSERT(target->kind() != Code::CALL_IC || delta == 0); |
| 398 |
| 393 // Not all Code objects have TypeFeedbackInfo. | 399 // Not all Code objects have TypeFeedbackInfo. |
| 394 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 400 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
| 395 TypeFeedbackInfo* info = | 401 TypeFeedbackInfo* info = |
| 396 TypeFeedbackInfo::cast(host->type_feedback_info()); | 402 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 397 info->change_ic_with_type_info_count(delta); | 403 info->change_ic_with_type_info_count(delta); |
| 398 } | 404 } |
| 399 } | 405 } |
| 400 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 406 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
| 401 TypeFeedbackInfo* info = | 407 TypeFeedbackInfo* info = |
| 402 TypeFeedbackInfo::cast(host->type_feedback_info()); | 408 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 | 461 |
| 456 switch (target->kind()) { | 462 switch (target->kind()) { |
| 457 case Code::LOAD_IC: | 463 case Code::LOAD_IC: |
| 458 return LoadIC::Clear(isolate, address, target, constant_pool); | 464 return LoadIC::Clear(isolate, address, target, constant_pool); |
| 459 case Code::KEYED_LOAD_IC: | 465 case Code::KEYED_LOAD_IC: |
| 460 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 466 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
| 461 case Code::STORE_IC: | 467 case Code::STORE_IC: |
| 462 return StoreIC::Clear(isolate, address, target, constant_pool); | 468 return StoreIC::Clear(isolate, address, target, constant_pool); |
| 463 case Code::KEYED_STORE_IC: | 469 case Code::KEYED_STORE_IC: |
| 464 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 470 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
| 471 case Code::CALL_IC: |
| 472 return CallIC::Clear(isolate, address, target, constant_pool); |
| 465 case Code::COMPARE_IC: | 473 case Code::COMPARE_IC: |
| 466 return CompareIC::Clear(isolate, address, target, constant_pool); | 474 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 467 case Code::COMPARE_NIL_IC: | 475 case Code::COMPARE_NIL_IC: |
| 468 return CompareNilIC::Clear(address, target, constant_pool); | 476 return CompareNilIC::Clear(address, target, constant_pool); |
| 469 case Code::BINARY_OP_IC: | 477 case Code::BINARY_OP_IC: |
| 470 case Code::TO_BOOLEAN_IC: | 478 case Code::TO_BOOLEAN_IC: |
| 471 // Clearing these is tricky and does not | 479 // Clearing these is tricky and does not |
| 472 // make any performance difference. | 480 // make any performance difference. |
| 473 return; | 481 return; |
| 474 default: UNREACHABLE(); | 482 default: UNREACHABLE(); |
| 475 } | 483 } |
| 476 } | 484 } |
| 477 | 485 |
| 478 | 486 |
| 479 void KeyedLoadIC::Clear(Isolate* isolate, | 487 void KeyedLoadIC::Clear(Isolate* isolate, |
| 480 Address address, | 488 Address address, |
| 481 Code* target, | 489 Code* target, |
| 482 ConstantPoolArray* constant_pool) { | 490 ConstantPoolArray* constant_pool) { |
| 483 if (IsCleared(target)) return; | 491 if (IsCleared(target)) return; |
| 484 // Make sure to also clear the map used in inline fast cases. If we | 492 // Make sure to also clear the map used in inline fast cases. If we |
| 485 // do not clear these maps, cached code can keep objects alive | 493 // do not clear these maps, cached code can keep objects alive |
| 486 // through the embedded maps. | 494 // through the embedded maps. |
| 487 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 495 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
| 488 } | 496 } |
| 489 | 497 |
| 490 | 498 |
| 499 void CallIC::Clear(Isolate* isolate, |
| 500 Address address, |
| 501 Code* target, |
| 502 ConstantPoolArray* constant_pool) { |
| 503 // Currently, CallIC doesn't have state changes. |
| 504 ASSERT(target->ic_state() == v8::internal::GENERIC); |
| 505 } |
| 506 |
| 507 |
| 491 void LoadIC::Clear(Isolate* isolate, | 508 void LoadIC::Clear(Isolate* isolate, |
| 492 Address address, | 509 Address address, |
| 493 Code* target, | 510 Code* target, |
| 494 ConstantPoolArray* constant_pool) { | 511 ConstantPoolArray* constant_pool) { |
| 495 if (IsCleared(target)) return; | 512 if (IsCleared(target)) return; |
| 496 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 513 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 497 Code::LOAD_IC, target->extra_ic_state()); | 514 Code::LOAD_IC, target->extra_ic_state()); |
| 498 SetTargetAtAddress(address, code, constant_pool); | 515 SetTargetAtAddress(address, code, constant_pool); |
| 499 } | 516 } |
| 500 | 517 |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 ASSIGN_RETURN_ON_EXCEPTION( | 1326 ASSIGN_RETURN_ON_EXCEPTION( |
| 1310 isolate(), | 1327 isolate(), |
| 1311 result, | 1328 result, |
| 1312 JSReceiver::SetProperty( | 1329 JSReceiver::SetProperty( |
| 1313 receiver, name, value, NONE, strict_mode(), store_mode), | 1330 receiver, name, value, NONE, strict_mode(), store_mode), |
| 1314 Object); | 1331 Object); |
| 1315 return result; | 1332 return result; |
| 1316 } | 1333 } |
| 1317 | 1334 |
| 1318 | 1335 |
| 1336 void CallIC::State::Print(StringStream* stream) const { |
| 1337 stream->Add("(args(%d), ", |
| 1338 argc_); |
| 1339 stream->Add("%s, ", |
| 1340 call_type_ == CallIC::METHOD ? "METHOD" : "FUNCTION"); |
| 1341 } |
| 1342 |
| 1343 |
| 1344 Handle<Code> CallIC::initialize_stub(Isolate* isolate, |
| 1345 int argc, |
| 1346 CallType call_type) { |
| 1347 CallICStub stub(isolate, State::DefaultCallState(argc, call_type)); |
| 1348 Handle<Code> code = stub.GetCode(); |
| 1349 return code; |
| 1350 } |
| 1351 |
| 1352 |
| 1319 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1353 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1320 StrictMode strict_mode) { | 1354 StrictMode strict_mode) { |
| 1321 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1355 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
| 1322 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1356 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1323 UNINITIALIZED, extra_state); | 1357 UNINITIALIZED, extra_state); |
| 1324 return ic; | 1358 return ic; |
| 1325 } | 1359 } |
| 1326 | 1360 |
| 1327 | 1361 |
| 1328 Handle<Code> StoreIC::megamorphic_stub() { | 1362 Handle<Code> StoreIC::megamorphic_stub() { |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1773 ASSIGN_RETURN_ON_EXCEPTION( | 1807 ASSIGN_RETURN_ON_EXCEPTION( |
| 1774 isolate(), | 1808 isolate(), |
| 1775 result, | 1809 result, |
| 1776 Runtime::SetObjectProperty( | 1810 Runtime::SetObjectProperty( |
| 1777 isolate(), object, key, value, NONE, strict_mode()), | 1811 isolate(), object, key, value, NONE, strict_mode()), |
| 1778 Object); | 1812 Object); |
| 1779 return result; | 1813 return result; |
| 1780 } | 1814 } |
| 1781 | 1815 |
| 1782 | 1816 |
| 1817 CallIC::State::State(ExtraICState extra_ic_state) |
| 1818 : argc_(ArgcBits::decode(extra_ic_state)), |
| 1819 call_type_(CallTypeBits::decode(extra_ic_state)) { |
| 1820 } |
| 1821 |
| 1822 |
| 1823 ExtraICState CallIC::State::GetExtraICState() const { |
| 1824 ExtraICState extra_ic_state = |
| 1825 ArgcBits::encode(argc_) | |
| 1826 CallTypeBits::encode(call_type_); |
| 1827 return extra_ic_state; |
| 1828 } |
| 1829 |
| 1830 |
| 1831 void CallIC::HandleMiss(Handle<Object> receiver, |
| 1832 Handle<Object> function, |
| 1833 Handle<FixedArray> vector, |
| 1834 Handle<Smi> slot) { |
| 1835 State state(target()->extra_ic_state()); |
| 1836 Object* feedback = vector->get(slot->value()); |
| 1837 |
| 1838 if (feedback->IsJSFunction() || !function->IsJSFunction()) { |
| 1839 // We are going generic. |
| 1840 ASSERT(!function->IsJSFunction() || *function != feedback); |
| 1841 |
| 1842 vector->set(slot->value(), |
| 1843 *TypeFeedbackInfo::MegamorphicSentinel(isolate()), |
| 1844 SKIP_WRITE_BARRIER); |
| 1845 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); |
| 1846 } else { |
| 1847 // If we came here feedback must be the uninitialized sentinel, |
| 1848 // and we are going monomorphic. |
| 1849 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate())); |
| 1850 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
| 1851 Handle<Object> name(js_function->shared()->name(), isolate()); |
| 1852 TRACE_IC("CallIC", name); |
| 1853 vector->set(slot->value(), *function); |
| 1854 } |
| 1855 } |
| 1856 |
| 1857 |
| 1783 #undef TRACE_IC | 1858 #undef TRACE_IC |
| 1784 | 1859 |
| 1785 | 1860 |
| 1786 // ---------------------------------------------------------------------------- | 1861 // ---------------------------------------------------------------------------- |
| 1787 // Static IC stub generators. | 1862 // Static IC stub generators. |
| 1788 // | 1863 // |
| 1789 | 1864 |
| 1790 // Used from ic-<arch>.cc. | 1865 // Used from ic-<arch>.cc. |
| 1866 RUNTIME_FUNCTION(CallIC_Miss) { |
| 1867 HandleScope scope(isolate); |
| 1868 ASSERT(args.length() == 4); |
| 1869 CallIC ic(isolate); |
| 1870 Handle<Object> receiver = args.at<Object>(0); |
| 1871 Handle<Object> function = args.at<Object>(1); |
| 1872 Handle<FixedArray> vector = args.at<FixedArray>(2); |
| 1873 Handle<Smi> slot = args.at<Smi>(3); |
| 1874 ic.HandleMiss(receiver, function, vector, slot); |
| 1875 return *function; |
| 1876 } |
| 1877 |
| 1878 |
| 1791 // Used from ic-<arch>.cc. | 1879 // Used from ic-<arch>.cc. |
| 1792 RUNTIME_FUNCTION(LoadIC_Miss) { | 1880 RUNTIME_FUNCTION(LoadIC_Miss) { |
| 1793 HandleScope scope(isolate); | 1881 HandleScope scope(isolate); |
| 1794 ASSERT(args.length() == 2); | 1882 ASSERT(args.length() == 2); |
| 1795 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1883 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 1796 Handle<Object> receiver = args.at<Object>(0); | 1884 Handle<Object> receiver = args.at<Object>(0); |
| 1797 Handle<String> key = args.at<String>(1); | 1885 Handle<String> key = args.at<String>(1); |
| 1798 ic.UpdateState(receiver, key); | 1886 ic.UpdateState(receiver, key); |
| 1799 Handle<Object> result; | 1887 Handle<Object> result; |
| 1800 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 1888 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2907 #undef ADDR | 2995 #undef ADDR |
| 2908 }; | 2996 }; |
| 2909 | 2997 |
| 2910 | 2998 |
| 2911 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2999 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2912 return IC_utilities[id]; | 3000 return IC_utilities[id]; |
| 2913 } | 3001 } |
| 2914 | 3002 |
| 2915 | 3003 |
| 2916 } } // namespace v8::internal | 3004 } } // namespace v8::internal |
| OLD | NEW |