OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 Code* apply_builtin = isolate()->builtins()->builtin( | 84 Code* apply_builtin = isolate()->builtins()->builtin( |
85 Builtins::kFunctionApply); | 85 Builtins::kFunctionApply); |
86 if (raw_frame->unchecked_code() == apply_builtin) { | 86 if (raw_frame->unchecked_code() == apply_builtin) { |
87 PrintF("apply from "); | 87 PrintF("apply from "); |
88 it.Advance(); | 88 it.Advance(); |
89 raw_frame = it.frame(); | 89 raw_frame = it.frame(); |
90 } | 90 } |
91 } | 91 } |
92 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 92 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
93 ExtraICState extra_state = new_target->extra_ic_state(); | 93 ExtraICState extra_state = new_target->extra_ic_state(); |
94 const char* modifier = ""; | 94 const char* modifier = |
95 if (new_target->kind() == Code::KEYED_STORE_IC) { | 95 GetTransitionMarkModifier( |
96 modifier = GetTransitionMarkModifier( | 96 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
97 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | |
98 } | |
99 PrintF(" (%c->%c%s)", | 97 PrintF(" (%c->%c%s)", |
100 TransitionMarkFromState(state()), | 98 TransitionMarkFromState(state()), |
101 TransitionMarkFromState(new_state), | 99 TransitionMarkFromState(new_state), |
102 modifier); | 100 modifier); |
103 name->Print(); | 101 name->Print(); |
104 PrintF("]\n"); | 102 PrintF("]\n"); |
105 } | 103 } |
106 } | 104 } |
107 | 105 |
108 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 106 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 Isolate* isolate = target->GetHeap()->isolate(); | 408 Isolate* isolate = target->GetHeap()->isolate(); |
411 Code* host = isolate-> | 409 Code* host = isolate-> |
412 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 410 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
413 if (host->kind() != Code::FUNCTION) return; | 411 if (host->kind() != Code::FUNCTION) return; |
414 | 412 |
415 if (FLAG_type_info_threshold > 0 && | 413 if (FLAG_type_info_threshold > 0 && |
416 old_target->is_inline_cache_stub() && | 414 old_target->is_inline_cache_stub() && |
417 target->is_inline_cache_stub()) { | 415 target->is_inline_cache_stub()) { |
418 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 416 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
419 target->ic_state()); | 417 target->ic_state()); |
420 // Call ICs don't have interesting state changes from this point | |
421 // of view. | |
422 ASSERT(target->kind() != Code::CALL_IC || delta == 0); | |
423 | |
424 // Not all Code objects have TypeFeedbackInfo. | 418 // Not all Code objects have TypeFeedbackInfo. |
425 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 419 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
426 TypeFeedbackInfo* info = | 420 TypeFeedbackInfo* info = |
427 TypeFeedbackInfo::cast(host->type_feedback_info()); | 421 TypeFeedbackInfo::cast(host->type_feedback_info()); |
428 info->change_ic_with_type_info_count(delta); | 422 info->change_ic_with_type_info_count(delta); |
429 } | 423 } |
430 } | 424 } |
431 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 425 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
432 TypeFeedbackInfo* info = | 426 TypeFeedbackInfo* info = |
433 TypeFeedbackInfo::cast(host->type_feedback_info()); | 427 TypeFeedbackInfo::cast(host->type_feedback_info()); |
(...skipping 16 matching lines...) Expand all Loading... |
450 | 444 |
451 switch (target->kind()) { | 445 switch (target->kind()) { |
452 case Code::LOAD_IC: | 446 case Code::LOAD_IC: |
453 return LoadIC::Clear(isolate, address, target, constant_pool); | 447 return LoadIC::Clear(isolate, address, target, constant_pool); |
454 case Code::KEYED_LOAD_IC: | 448 case Code::KEYED_LOAD_IC: |
455 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 449 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
456 case Code::STORE_IC: | 450 case Code::STORE_IC: |
457 return StoreIC::Clear(isolate, address, target, constant_pool); | 451 return StoreIC::Clear(isolate, address, target, constant_pool); |
458 case Code::KEYED_STORE_IC: | 452 case Code::KEYED_STORE_IC: |
459 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 453 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
460 case Code::CALL_IC: | |
461 return CallIC::Clear(isolate, address, target, constant_pool); | |
462 case Code::COMPARE_IC: | 454 case Code::COMPARE_IC: |
463 return CompareIC::Clear(isolate, address, target, constant_pool); | 455 return CompareIC::Clear(isolate, address, target, constant_pool); |
464 case Code::COMPARE_NIL_IC: | 456 case Code::COMPARE_NIL_IC: |
465 return CompareNilIC::Clear(address, target, constant_pool); | 457 return CompareNilIC::Clear(address, target, constant_pool); |
466 case Code::BINARY_OP_IC: | 458 case Code::BINARY_OP_IC: |
467 case Code::TO_BOOLEAN_IC: | 459 case Code::TO_BOOLEAN_IC: |
468 // Clearing these is tricky and does not | 460 // Clearing these is tricky and does not |
469 // make any performance difference. | 461 // make any performance difference. |
470 return; | 462 return; |
471 default: UNREACHABLE(); | 463 default: UNREACHABLE(); |
472 } | 464 } |
473 } | 465 } |
474 | 466 |
475 | 467 |
476 void KeyedLoadIC::Clear(Isolate* isolate, | 468 void KeyedLoadIC::Clear(Isolate* isolate, |
477 Address address, | 469 Address address, |
478 Code* target, | 470 Code* target, |
479 ConstantPoolArray* constant_pool) { | 471 ConstantPoolArray* constant_pool) { |
480 if (IsCleared(target)) return; | 472 if (IsCleared(target)) return; |
481 // Make sure to also clear the map used in inline fast cases. If we | 473 // Make sure to also clear the map used in inline fast cases. If we |
482 // do not clear these maps, cached code can keep objects alive | 474 // do not clear these maps, cached code can keep objects alive |
483 // through the embedded maps. | 475 // through the embedded maps. |
484 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 476 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
485 } | 477 } |
486 | 478 |
487 | 479 |
488 void CallIC::Clear(Isolate* isolate, | |
489 Address address, | |
490 Code* target, | |
491 ConstantPoolArray* constant_pool) { | |
492 // CallIC just has a generic stub and a monomorphic stub. Only clear if we | |
493 // are monomorphic | |
494 if (target->ic_state() != ::v8::internal::MONOMORPHIC) return; | |
495 | |
496 CallIC::State existing_state(target->extra_ic_state()); | |
497 | |
498 // Install default stub with the immutable parts of existing state. | |
499 HandleScope scope(isolate); | |
500 CallICStub stub(State::DefaultCallState(existing_state.arg_count(), | |
501 existing_state.call_type())); | |
502 Code* code = *stub.GetCode(isolate); | |
503 SetTargetAtAddress(address, code, constant_pool); | |
504 } | |
505 | |
506 | |
507 void LoadIC::Clear(Isolate* isolate, | 480 void LoadIC::Clear(Isolate* isolate, |
508 Address address, | 481 Address address, |
509 Code* target, | 482 Code* target, |
510 ConstantPoolArray* constant_pool) { | 483 ConstantPoolArray* constant_pool) { |
511 if (IsCleared(target)) return; | 484 if (IsCleared(target)) return; |
512 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 485 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
513 Code::LOAD_IC, target->extra_ic_state()); | 486 Code::LOAD_IC, target->extra_ic_state()); |
514 SetTargetAtAddress(address, code, constant_pool); | 487 SetTargetAtAddress(address, code, constant_pool); |
515 } | 488 } |
516 | 489 |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 } | 1265 } |
1293 | 1266 |
1294 // Set the property. | 1267 // Set the property. |
1295 Handle<Object> result = JSReceiver::SetProperty( | 1268 Handle<Object> result = JSReceiver::SetProperty( |
1296 receiver, name, value, NONE, strict_mode(), store_mode); | 1269 receiver, name, value, NONE, strict_mode(), store_mode); |
1297 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1270 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1298 return *result; | 1271 return *result; |
1299 } | 1272 } |
1300 | 1273 |
1301 | 1274 |
1302 void CallIC::State::Print(StringStream* stream) const { | |
1303 stream->Add("(args(%d), ", | |
1304 argc_); | |
1305 stream->Add("%s, ", | |
1306 call_type_ == CallIC::METHOD ? "METHOD" : "FUNCTION"); | |
1307 stream->Add("%s, ", | |
1308 stub_type_ == CallIC::MONOMORPHIC ? | |
1309 "MONOMORPHIC" : "NOT_MONOMORPHIC"); | |
1310 stream->Add("%s, ", | |
1311 argument_check_ == CallIC::ARGUMENTS_MUST_MATCH ? | |
1312 "args_must_match" : "args_might_match"); | |
1313 stream->Add("%s)", | |
1314 strict_mode_ == STRICT ? | |
1315 "strict" : "sloppy"); | |
1316 } | |
1317 | |
1318 | |
1319 Handle<Code> CallIC::initialize_stub(Isolate* isolate, | |
1320 int argc, | |
1321 CallType call_type) { | |
1322 CallICStub stub(State::DefaultCallState(argc, call_type)); | |
1323 Handle<Code> code = stub.GetCode(isolate); | |
1324 return code; | |
1325 } | |
1326 | |
1327 | |
1328 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1275 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
1329 StrictMode strict_mode) { | 1276 StrictMode strict_mode) { |
1330 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1277 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
1331 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1278 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
1332 UNINITIALIZED, extra_state); | 1279 UNINITIALIZED, extra_state); |
1333 return ic; | 1280 return ic; |
1334 } | 1281 } |
1335 | 1282 |
1336 | 1283 |
1337 Handle<Code> StoreIC::megamorphic_stub() { | 1284 Handle<Code> StoreIC::megamorphic_stub() { |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1790 if (maybe_object) return maybe_object; | 1737 if (maybe_object) return maybe_object; |
1791 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, | 1738 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, |
1792 value, | 1739 value, |
1793 NONE, | 1740 NONE, |
1794 strict_mode()); | 1741 strict_mode()); |
1795 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1742 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1796 return *result; | 1743 return *result; |
1797 } | 1744 } |
1798 | 1745 |
1799 | 1746 |
1800 CallIC::State::State(ExtraICState extra_ic_state) | |
1801 : argc_(ArgcBits::decode(extra_ic_state)), | |
1802 call_type_(CallTypeBits::decode(extra_ic_state)), | |
1803 stub_type_(StubTypeBits::decode(extra_ic_state)), | |
1804 argument_check_(ArgumentCheckBits::decode(extra_ic_state)), | |
1805 strict_mode_(StrictModeBits::decode(extra_ic_state)) { | |
1806 } | |
1807 | |
1808 | |
1809 ExtraICState CallIC::State::GetExtraICState() const { | |
1810 ExtraICState extra_ic_state = | |
1811 ArgcBits::encode(argc_) | | |
1812 CallTypeBits::encode(call_type_) | | |
1813 StubTypeBits::encode(stub_type_) | | |
1814 ArgumentCheckBits::encode(argument_check_) | | |
1815 StrictModeBits::encode(strict_mode_); | |
1816 return extra_ic_state; | |
1817 } | |
1818 | |
1819 | |
1820 CallIC::State CallIC::State::ToGenericState() { | |
1821 if (stub_type() == CallIC::MONOMORPHIC) { | |
1822 return DefaultCallState(arg_count(), call_type()); | |
1823 } | |
1824 return *this; | |
1825 } | |
1826 | |
1827 | |
1828 CallIC::State CallIC::State::ToMonomorphicState( | |
1829 Handle<JSFunction> function) { | |
1830 // Choose the right monomorphic handler | |
1831 SharedFunctionInfo* shared = function->shared(); | |
1832 ArgumentCheck new_argument_check = | |
1833 shared->formal_parameter_count() == arg_count() | |
1834 ? CallIC::ARGUMENTS_MUST_MATCH | |
1835 : CallIC::ARGUMENTS_COUNT_UNKNOWN; | |
1836 StrictMode new_strict_mode = shared->strict_mode(); | |
1837 if (new_argument_check != argument_check() || | |
1838 new_strict_mode != strict_mode()) { | |
1839 return MonomorphicCallState(arg_count(), call_type(), new_argument_check, | |
1840 new_strict_mode); | |
1841 } | |
1842 | |
1843 return *this; | |
1844 } | |
1845 | |
1846 | |
1847 void CallIC::HandleMiss(Handle<Object> receiver, | |
1848 Handle<Object> function, | |
1849 Handle<FixedArray> vector, | |
1850 Handle<Smi> slot) { | |
1851 State state(target()->extra_ic_state()); | |
1852 Object* feedback = vector->get(slot->value()); | |
1853 | |
1854 if (feedback->IsJSFunction() || !function->IsJSFunction()) { | |
1855 // We are going generic. | |
1856 ASSERT(!function->IsJSFunction() || *function != feedback); | |
1857 | |
1858 vector->set(slot->value(), | |
1859 *TypeFeedbackInfo::MegamorphicSentinel(isolate())); | |
1860 | |
1861 // We only need to patch if we currently don't have the default stub in | |
1862 // place. | |
1863 State new_state = state.ToGenericState(); | |
1864 if (new_state != state) { | |
1865 CallICStub stub(new_state); | |
1866 set_target(*stub.GetCode(isolate())); | |
1867 TRACE_GENERIC_IC(isolate(), "CallIC", "generic"); | |
1868 } | |
1869 } else { | |
1870 // If we came here feedback must be the uninitialized sentinel, | |
1871 // and we are going monomorphic. | |
1872 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate())); | |
1873 ASSERT(state.stub_type() != CallIC::MONOMORPHIC); | |
1874 | |
1875 vector->set(slot->value(), *function); | |
1876 | |
1877 // Choose the right monomorphic handler | |
1878 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | |
1879 State new_state = state.ToMonomorphicState(js_function); | |
1880 if (new_state != state) { | |
1881 CallICStub stub(new_state); | |
1882 set_target(*stub.GetCode(isolate())); | |
1883 TRACE_IC("CallIC", Handle<Object>(js_function->shared()->name(), | |
1884 isolate())); | |
1885 } | |
1886 } | |
1887 } | |
1888 | |
1889 | |
1890 #undef TRACE_IC | 1747 #undef TRACE_IC |
1891 | 1748 |
1892 | 1749 |
1893 // ---------------------------------------------------------------------------- | 1750 // ---------------------------------------------------------------------------- |
1894 // Static IC stub generators. | 1751 // Static IC stub generators. |
1895 // | 1752 // |
1896 | 1753 |
1897 // Used from ic-<arch>.cc. | 1754 // Used from ic-<arch>.cc. |
1898 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | |
1899 HandleScope scope(isolate); | |
1900 ASSERT(args.length() == 4); | |
1901 CallIC ic(isolate); | |
1902 Handle<Object> receiver = args.at<Object>(0); | |
1903 Handle<Object> function = args.at<Object>(1); | |
1904 Handle<FixedArray> vector = args.at<FixedArray>(2); | |
1905 Handle<Smi> slot = args.at<Smi>(3); | |
1906 ic.HandleMiss(receiver, function, vector, slot); | |
1907 return *function; | |
1908 } | |
1909 | |
1910 | |
1911 // Used from ic-<arch>.cc. | 1755 // Used from ic-<arch>.cc. |
1912 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1756 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
1913 HandleScope scope(isolate); | 1757 HandleScope scope(isolate); |
1914 ASSERT(args.length() == 2); | 1758 ASSERT(args.length() == 2); |
1915 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1759 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
1916 Handle<Object> receiver = args.at<Object>(0); | 1760 Handle<Object> receiver = args.at<Object>(0); |
1917 Handle<String> key = args.at<String>(1); | 1761 Handle<String> key = args.at<String>(1); |
1918 ic.UpdateState(receiver, key); | 1762 ic.UpdateState(receiver, key); |
1919 return ic.Load(receiver, key); | 1763 return ic.Load(receiver, key); |
1920 } | 1764 } |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2989 #undef ADDR | 2833 #undef ADDR |
2990 }; | 2834 }; |
2991 | 2835 |
2992 | 2836 |
2993 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2837 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2994 return IC_utilities[id]; | 2838 return IC_utilities[id]; |
2995 } | 2839 } |
2996 | 2840 |
2997 | 2841 |
2998 } } // namespace v8::internal | 2842 } } // namespace v8::internal |
OLD | NEW |