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 GetTransitionMarkModifier( | 95 if (new_target->kind() == Code::KEYED_STORE_IC) { |
96 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | 96 modifier = GetTransitionMarkModifier( |
97 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | |
98 } | |
97 PrintF(" (%c->%c%s)", | 99 PrintF(" (%c->%c%s)", |
98 TransitionMarkFromState(state()), | 100 TransitionMarkFromState(state()), |
99 TransitionMarkFromState(new_state), | 101 TransitionMarkFromState(new_state), |
100 modifier); | 102 modifier); |
101 name->Print(); | 103 name->Print(); |
102 PrintF("]\n"); | 104 PrintF("]\n"); |
103 } | 105 } |
104 } | 106 } |
105 | 107 |
106 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 108 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 Isolate* isolate = target->GetHeap()->isolate(); | 384 Isolate* isolate = target->GetHeap()->isolate(); |
383 Code* host = isolate-> | 385 Code* host = isolate-> |
384 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 386 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
385 if (host->kind() != Code::FUNCTION) return; | 387 if (host->kind() != Code::FUNCTION) return; |
386 | 388 |
387 if (FLAG_type_info_threshold > 0 && | 389 if (FLAG_type_info_threshold > 0 && |
388 old_target->is_inline_cache_stub() && | 390 old_target->is_inline_cache_stub() && |
389 target->is_inline_cache_stub()) { | 391 target->is_inline_cache_stub()) { |
390 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 392 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
391 target->ic_state()); | 393 target->ic_state()); |
394 // Call ICs don't have interesting state changes from this point | |
395 // of view. | |
396 ASSERT(target->kind() != Code::CALL_IC || delta == 0); | |
397 | |
392 // Not all Code objects have TypeFeedbackInfo. | 398 // Not all Code objects have TypeFeedbackInfo. |
393 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 399 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
394 TypeFeedbackInfo* info = | 400 TypeFeedbackInfo* info = |
395 TypeFeedbackInfo::cast(host->type_feedback_info()); | 401 TypeFeedbackInfo::cast(host->type_feedback_info()); |
396 info->change_ic_with_type_info_count(delta); | 402 info->change_ic_with_type_info_count(delta); |
397 } | 403 } |
398 } | 404 } |
399 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 405 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
400 TypeFeedbackInfo* info = | 406 TypeFeedbackInfo* info = |
401 TypeFeedbackInfo::cast(host->type_feedback_info()); | 407 TypeFeedbackInfo::cast(host->type_feedback_info()); |
(...skipping 13 matching lines...) Expand all Loading... | |
415 // Don't clear debug break inline cache as it will remove the break point. | 421 // Don't clear debug break inline cache as it will remove the break point. |
416 if (target->is_debug_stub()) return; | 422 if (target->is_debug_stub()) return; |
417 | 423 |
418 switch (target->kind()) { | 424 switch (target->kind()) { |
419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); | 425 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); |
420 case Code::KEYED_LOAD_IC: | 426 case Code::KEYED_LOAD_IC: |
421 return KeyedLoadIC::Clear(isolate, address, target); | 427 return KeyedLoadIC::Clear(isolate, address, target); |
422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); | 428 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); |
423 case Code::KEYED_STORE_IC: | 429 case Code::KEYED_STORE_IC: |
424 return KeyedStoreIC::Clear(isolate, address, target); | 430 return KeyedStoreIC::Clear(isolate, address, target); |
431 case Code::CALL_IC: return CallIC::Clear(isolate, address, target); | |
425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); | 432 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); |
426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); | 433 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); |
427 case Code::BINARY_OP_IC: | 434 case Code::BINARY_OP_IC: |
428 case Code::TO_BOOLEAN_IC: | 435 case Code::TO_BOOLEAN_IC: |
429 // Clearing these is tricky and does not | 436 // Clearing these is tricky and does not |
430 // make any performance difference. | 437 // make any performance difference. |
431 return; | 438 return; |
432 default: UNREACHABLE(); | 439 default: UNREACHABLE(); |
433 } | 440 } |
434 } | 441 } |
435 | 442 |
436 | 443 |
444 void CallIC::Clear(Isolate* isolate, Address address, Code* target) { | |
445 // CallIC just has a generic stub and a monomorphic stub. Only clear if we | |
446 // are monomorphic | |
447 if (target->ic_state() != ::v8::internal::MONOMORPHIC) return; | |
448 | |
449 CallIC::State existing_state(target->extra_ic_state()); | |
450 | |
451 // Install default stub with the immutable parts of existing state. | |
452 HandleScope scope(isolate); | |
453 CallICStub stub(State(existing_state.arg_count(), | |
454 existing_state.call_type())); | |
455 Code* code = *stub.GetCode(isolate); | |
456 SetTargetAtAddress(address, code); | |
457 } | |
458 | |
459 | |
437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 460 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
438 if (IsCleared(target)) return; | 461 if (IsCleared(target)) return; |
439 // Make sure to also clear the map used in inline fast cases. If we | 462 // Make sure to also clear the map used in inline fast cases. If we |
440 // do not clear these maps, cached code can keep objects alive | 463 // do not clear these maps, cached code can keep objects alive |
441 // through the embedded maps. | 464 // through the embedded maps. |
442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 465 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
443 } | 466 } |
444 | 467 |
445 | 468 |
446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 469 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1257 } | 1280 } |
1258 | 1281 |
1259 // Set the property. | 1282 // Set the property. |
1260 Handle<Object> result = JSReceiver::SetProperty( | 1283 Handle<Object> result = JSReceiver::SetProperty( |
1261 receiver, name, value, NONE, strict_mode(), store_mode); | 1284 receiver, name, value, NONE, strict_mode(), store_mode); |
1262 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1285 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1263 return *result; | 1286 return *result; |
1264 } | 1287 } |
1265 | 1288 |
1266 | 1289 |
1290 void CallIC::State::Print(StringStream* stream) const { | |
1291 stream->Add("(args(%d), ", | |
1292 argc_); | |
1293 stream->Add("%s, ", | |
1294 call_type_ == CallIC::METHOD ? "METHOD" : "FUNCTION"); | |
1295 stream->Add("%s, ", | |
1296 stub_type_ == CallIC::MONOMORPHIC ? | |
1297 "MONOMORPHIC" : "NOT_MONOMORPHIC"); | |
1298 stream->Add("%s, ", | |
1299 argument_check_ == CallIC::ARGUMENTS_MATCH ? | |
1300 "args_match" : "args_dont_match"); | |
1301 stream->Add("%s)", | |
1302 function_attributes_ == CallIC::STRICT_OR_NATIVE ? | |
1303 "strict_or_native" : "not_strict_or_native"); | |
1304 } | |
1305 | |
1306 | |
1307 void CallIC::GenerateNormal(MacroAssembler* masm, | |
1308 int argc, | |
1309 CallType call_type) { | |
1310 CallICStub stub(State(argc, | |
1311 call_type, | |
1312 CallIC::GENERIC, | |
1313 CallIC::ARGUMENTS_MATCH, | |
1314 CallIC::NOT_STRICT_OR_NATIVE)); | |
1315 stub.GetCode(masm->isolate()); | |
1316 } | |
1317 | |
1318 | |
1319 Handle<Code> CallIC::initialize_stub(Isolate* isolate, | |
1320 int argc, | |
1321 CallType call_type) { | |
1322 CallICStub stub(State(argc, | |
1323 call_type, | |
1324 CallIC::GENERIC, | |
1325 CallIC::ARGUMENTS_MATCH, | |
1326 CallIC::NOT_STRICT_OR_NATIVE)); | |
1327 Handle<Code> code = stub.GetCode(isolate); | |
1328 return code; | |
1329 } | |
1330 | |
1331 | |
1267 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1332 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
1268 StrictModeFlag strict_mode) { | 1333 StrictModeFlag strict_mode) { |
1269 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1334 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
1270 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1335 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
1271 UNINITIALIZED, extra_state); | 1336 UNINITIALIZED, extra_state); |
1272 return ic; | 1337 return ic; |
1273 } | 1338 } |
1274 | 1339 |
1275 | 1340 |
1276 Handle<Code> StoreIC::megamorphic_stub() { | 1341 Handle<Code> StoreIC::megamorphic_stub() { |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1725 if (maybe_object) return maybe_object; | 1790 if (maybe_object) return maybe_object; |
1726 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, | 1791 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, |
1727 value, | 1792 value, |
1728 NONE, | 1793 NONE, |
1729 strict_mode()); | 1794 strict_mode()); |
1730 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1795 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1731 return *result; | 1796 return *result; |
1732 } | 1797 } |
1733 | 1798 |
1734 | 1799 |
1800 CallIC::State::State(ExtraICState extra_ic_state) { | |
1801 argc_ = ArgBits::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 function_attributes_ = FunctionAttributeBits::decode(extra_ic_state); | |
1806 } | |
1807 | |
1808 | |
1809 ExtraICState CallIC::State::GetExtraICState() const { | |
1810 ExtraICState extra_ic_state = | |
1811 ArgBits::encode(argc_) | | |
1812 CallTypeBits::encode(call_type_) | | |
1813 StubTypeBits::encode(stub_type_) | | |
1814 ArgumentCheckBits::encode(argument_check_) | | |
1815 FunctionAttributeBits::encode(function_attributes_); | |
1816 return extra_ic_state; | |
1817 } | |
1818 | |
1819 | |
1820 void CallIC::PatchMegamorphic(int arg_count, CallType call_type) { | |
1821 CallICStub stub(State(arg_count, call_type)); | |
1822 set_target(*stub.GetCode(isolate())); | |
1823 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); | |
1824 } | |
1825 | |
1826 | |
1827 void CallIC::HandleMiss(Handle<Object> receiver, | |
1828 Handle<Object> function, | |
1829 Handle<FixedArray> vector, | |
1830 Handle<Smi> slot) { | |
1831 State state(target()->extra_ic_state()); | |
1832 Object* feedback = vector->get(slot->value()); | |
1833 | |
1834 // If we weren't called with a JSFunction, just return. | |
1835 if (!function->IsJSFunction()) { | |
1836 return; | |
Toon Verwaest
2014/03/24 10:25:44
Patch in the generic case, which doesn't record an
mvstanton
2014/03/25 15:34:50
I fixed this to patch to megamorphic in this case,
| |
1837 } | |
1838 | |
1839 if (feedback->IsJSFunction()) { | |
1840 // We are going megamorphic | |
1841 ASSERT(*function != feedback); | |
1842 | |
1843 vector->set(slot->value(), | |
1844 *TypeFeedbackInfo::MegamorphicSentinel(isolate())); | |
1845 | |
1846 // We only need to patch if we currently don't have the default stub in | |
1847 // place. | |
1848 if (state.stub_type() == CallIC::MONOMORPHIC) { | |
1849 PatchMegamorphic(state.arg_count(), state.call_type()); | |
1850 } | |
1851 } else { | |
1852 // If we came here feedback must be the uninitialized sentinel, | |
1853 // and we are going monomorphic. | |
1854 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate())); | |
1855 ASSERT(state.stub_type() != CallIC::MONOMORPHIC); | |
1856 | |
1857 vector->set(slot->value(), *function); | |
1858 | |
1859 // Choose the right monomorphic handler | |
1860 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | |
1861 SharedFunctionInfo* shared = js_function->shared(); | |
1862 ArgumentCheck argument_check = | |
1863 shared->formal_parameter_count() == state.arg_count() | |
1864 ? CallIC::ARGUMENTS_MATCH | |
1865 : CallIC::ARGUMENTS_DONT_MATCH; | |
1866 FunctionAttributes function_attributes = | |
1867 (shared->language_mode() == STRICT_MODE || shared->native()) | |
1868 ? CallIC::STRICT_OR_NATIVE | |
1869 : CallIC::NOT_STRICT_OR_NATIVE; | |
1870 | |
1871 bool must_patch = (argument_check == CallIC::ARGUMENTS_DONT_MATCH) || | |
1872 (function_attributes == CallIC::STRICT_OR_NATIVE); | |
1873 if (must_patch) { | |
1874 CallICStub stub(State(state.arg_count(), | |
1875 state.call_type(), | |
1876 CallIC::MONOMORPHIC, | |
1877 argument_check, | |
1878 function_attributes)); | |
1879 set_target(*stub.GetCode(isolate())); | |
1880 TRACE_IC("CallIC", Handle<Object>(js_function->shared()->name(), | |
1881 isolate())); | |
1882 } | |
1883 } | |
1884 } | |
1885 | |
1886 | |
1735 #undef TRACE_IC | 1887 #undef TRACE_IC |
1736 | 1888 |
1737 | 1889 |
1738 // ---------------------------------------------------------------------------- | 1890 // ---------------------------------------------------------------------------- |
1739 // Static IC stub generators. | 1891 // Static IC stub generators. |
1740 // | 1892 // |
1741 | 1893 |
1742 // Used from ic-<arch>.cc. | 1894 // Used from ic-<arch>.cc. |
1895 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | |
1896 HandleScope scope(isolate); | |
1897 ASSERT(args.length() == 4); | |
1898 CallIC ic(isolate); | |
1899 Handle<Object> receiver = args.at<Object>(0); | |
1900 Handle<Object> function = args.at<Object>(1); | |
1901 Handle<FixedArray> vector = args.at<FixedArray>(2); | |
1902 Handle<Smi> slot = args.at<Smi>(3); | |
1903 ic.HandleMiss(receiver, function, vector, slot); | |
1904 return *function; | |
1905 } | |
1906 | |
1907 | |
1743 // Used from ic-<arch>.cc. | 1908 // Used from ic-<arch>.cc. |
1744 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1909 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
1745 HandleScope scope(isolate); | 1910 HandleScope scope(isolate); |
1746 ASSERT(args.length() == 2); | 1911 ASSERT(args.length() == 2); |
1747 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1912 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
1748 Handle<Object> receiver = args.at<Object>(0); | 1913 Handle<Object> receiver = args.at<Object>(0); |
1749 Handle<String> key = args.at<String>(1); | 1914 Handle<String> key = args.at<String>(1); |
1750 ic.UpdateState(receiver, key); | 1915 ic.UpdateState(receiver, key); |
1751 return ic.Load(receiver, key); | 1916 return ic.Load(receiver, key); |
1752 } | 1917 } |
(...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2818 #undef ADDR | 2983 #undef ADDR |
2819 }; | 2984 }; |
2820 | 2985 |
2821 | 2986 |
2822 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2987 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2823 return IC_utilities[id]; | 2988 return IC_utilities[id]; |
2824 } | 2989 } |
2825 | 2990 |
2826 | 2991 |
2827 } } // namespace v8::internal | 2992 } } // namespace v8::internal |
OLD | NEW |