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::CALL_IC) { |
Toon Verwaest
2014/03/10 13:50:44
Isn't this only relevant for KEYED_STORE_IC?
mvstanton
2014/03/20 15:51:53
Done.
| |
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 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 // Don't clear debug break inline cache as it will remove the break point. | 417 // Don't clear debug break inline cache as it will remove the break point. |
416 if (target->is_debug_stub()) return; | 418 if (target->is_debug_stub()) return; |
417 | 419 |
418 switch (target->kind()) { | 420 switch (target->kind()) { |
419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); | 421 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); |
420 case Code::KEYED_LOAD_IC: | 422 case Code::KEYED_LOAD_IC: |
421 return KeyedLoadIC::Clear(isolate, address, target); | 423 return KeyedLoadIC::Clear(isolate, address, target); |
422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); | 424 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); |
423 case Code::KEYED_STORE_IC: | 425 case Code::KEYED_STORE_IC: |
424 return KeyedStoreIC::Clear(isolate, address, target); | 426 return KeyedStoreIC::Clear(isolate, address, target); |
427 case Code::CALL_IC: return CallIC::Clear(address, target); | |
425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); | 428 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); |
426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); | 429 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); |
427 case Code::BINARY_OP_IC: | 430 case Code::BINARY_OP_IC: |
428 case Code::TO_BOOLEAN_IC: | 431 case Code::TO_BOOLEAN_IC: |
429 // Clearing these is tricky and does not | 432 // Clearing these is tricky and does not |
430 // make any performance difference. | 433 // make any performance difference. |
431 return; | 434 return; |
432 default: UNREACHABLE(); | 435 default: UNREACHABLE(); |
433 } | 436 } |
434 } | 437 } |
435 | 438 |
436 | 439 |
440 void CallIC::Clear(Address address, Code* target) { | |
441 // TODO(mvstanton): What does it mean to clear this hybrid? | |
442 } | |
443 | |
444 | |
437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 445 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
438 if (IsCleared(target)) return; | 446 if (IsCleared(target)) return; |
439 // Make sure to also clear the map used in inline fast cases. If we | 447 // 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 | 448 // do not clear these maps, cached code can keep objects alive |
441 // through the embedded maps. | 449 // through the embedded maps. |
442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 450 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
443 } | 451 } |
444 | 452 |
445 | 453 |
446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 454 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1257 } | 1265 } |
1258 | 1266 |
1259 // Set the property. | 1267 // Set the property. |
1260 Handle<Object> result = JSReceiver::SetProperty( | 1268 Handle<Object> result = JSReceiver::SetProperty( |
1261 receiver, name, value, NONE, strict_mode(), store_mode); | 1269 receiver, name, value, NONE, strict_mode(), store_mode); |
1262 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1270 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1263 return *result; | 1271 return *result; |
1264 } | 1272 } |
1265 | 1273 |
1266 | 1274 |
1275 void CallIC::State::Print(StringStream* stream) const { | |
1276 stream->Add("(args(%d), ", | |
1277 argc_); | |
1278 stream->Add("%s, ", | |
1279 call_as_method_ ? "METHOD" : "FUNCTION"); | |
1280 stream->Add("%s, ", | |
1281 monomorphic_ ? "MONOMORPHIC" : "NOT_MONOMORPHIC"); | |
1282 stream->Add("%s, ", | |
1283 args_match_ ? "args_match" : "args_dont_match"); | |
1284 stream->Add("%s)", | |
1285 strict_native_ ? "strict_or_native" : "not_strict_or_native"); | |
1286 } | |
1287 | |
1288 | |
1289 void CallIC::GenerateNormal(MacroAssembler* masm, int argc, | |
1290 bool call_as_method) { | |
1291 CallICStub stub(State(argc, call_as_method, false, true, false)); | |
1292 stub.GetCode(masm->isolate()); | |
1293 } | |
1294 | |
1295 | |
1296 Handle<Code> CallIC::initialize_stub(Isolate* isolate, | |
1297 int argc, | |
1298 bool call_as_method) { | |
1299 CallICStub stub(State(argc, call_as_method, false, true, false)); | |
1300 ASSERT(stub.call_as_method() == call_as_method); | |
1301 Handle<Code> code = stub.GetCode(isolate); | |
1302 return code; | |
1303 } | |
1304 | |
1305 | |
1267 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1306 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
1268 StrictModeFlag strict_mode) { | 1307 StrictModeFlag strict_mode) { |
1269 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1308 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
1270 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1309 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
1271 UNINITIALIZED, extra_state); | 1310 UNINITIALIZED, extra_state); |
1272 return ic; | 1311 return ic; |
1273 } | 1312 } |
1274 | 1313 |
1275 | 1314 |
1276 Handle<Code> StoreIC::megamorphic_stub() { | 1315 Handle<Code> StoreIC::megamorphic_stub() { |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1718 if (maybe_object) return maybe_object; | 1757 if (maybe_object) return maybe_object; |
1719 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, | 1758 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, |
1720 value, | 1759 value, |
1721 NONE, | 1760 NONE, |
1722 strict_mode()); | 1761 strict_mode()); |
1723 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1762 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1724 return *result; | 1763 return *result; |
1725 } | 1764 } |
1726 | 1765 |
1727 | 1766 |
1767 CallIC::State::State(ExtraICState extra_ic_state) { | |
1768 argc_ = ArgBits::decode(extra_ic_state); | |
1769 call_as_method_ = CallAsMethodBits::decode(extra_ic_state); | |
1770 monomorphic_ = MonomorphicBits::decode(extra_ic_state); | |
1771 args_match_ = ArgsMatchBits::decode(extra_ic_state); | |
1772 strict_native_ = StrictNativeBits::decode(extra_ic_state); | |
1773 } | |
1774 | |
1775 | |
1776 ExtraICState CallIC::State::GetExtraICState() const { | |
1777 ExtraICState extra_ic_state = | |
1778 ArgBits::encode(argc_) | | |
1779 CallAsMethodBits::encode(call_as_method_) | | |
1780 MonomorphicBits::encode(monomorphic_) | | |
1781 ArgsMatchBits::encode(args_match_) | | |
1782 StrictNativeBits::encode(strict_native_); | |
1783 return extra_ic_state; | |
1784 } | |
1785 | |
1786 | |
1787 void CallIC::PatchMegamorphic(int arg_count, bool call_as_method) { | |
1788 CallICStub stub(State(arg_count, call_as_method)); | |
1789 set_target(*stub.GetCode(isolate())); | |
1790 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); | |
1791 } | |
1792 | |
1793 | |
1794 void CallIC::HandleMiss(Handle<Object> receiver, | |
1795 Handle<Object> function, | |
1796 Handle<FixedArray> vector, | |
1797 Handle<Smi> slot) { | |
1798 State state(target()->extra_ic_state()); | |
1799 Object* feedback = vector->get(slot->value()); | |
1800 if (feedback->IsJSFunction()) { | |
Toon Verwaest
2014/03/10 13:50:44
Shouldn't this be feedback->IsJSFunction() && func
mvstanton
2014/03/20 15:51:53
I went ahead and just returned without changing an
| |
1801 // We are going megamorphic, only if we were given a real function, | |
1802 // otherwise the slow path will be taken. | |
Toon Verwaest
2014/03/10 13:50:44
Weird sentence
mvstanton
2014/03/20 15:51:53
Removed.
| |
1803 vector->set(slot->value(), | |
1804 *TypeFeedbackInfo::MegamorphicSentinel(isolate())); | |
1805 // Do we need to patch? Only if we currently don't have the default stub | |
Toon Verwaest
2014/03/10 13:50:44
We only need to patch if ...
mvstanton
2014/03/20 15:51:53
Done.
| |
1806 // in place. | |
1807 if (state.monomorphic()) { | |
1808 PatchMegamorphic(state.arg_count(), state.call_as_method()); | |
1809 } | |
1810 } else { | |
1811 // If we came here feedback must be the uninitialized sentinel, | |
1812 // and we are going monomorphic. | |
1813 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate())); | |
1814 | |
1815 // Ugh. Do nothing if the function isn't a function, the slow path is taken. | |
Toon Verwaest
2014/03/10 13:50:44
Remove ugh.
mvstanton
2014/03/20 15:51:53
Done.
| |
1816 if (!function->IsJSFunction()) { | |
1817 // If we don't have a function, just go megamorphic. | |
1818 vector->set(slot->value(), | |
1819 *TypeFeedbackInfo::MegamorphicSentinel(isolate())); | |
1820 if (state.monomorphic()) { | |
1821 PatchMegamorphic(state.arg_count(), state.call_as_method()); | |
1822 } | |
1823 } else { | |
1824 vector->set(slot->value(), *function); | |
1825 SharedFunctionInfo* shared = Handle<JSFunction>::cast(function)->shared(); | |
1826 // Choose the right monomorphic handler | |
1827 bool arg_count_match = | |
1828 shared->formal_parameter_count() == state.arg_count(); | |
1829 bool strict_or_native = shared->language_mode() == STRICT_MODE || | |
1830 shared->native(); | |
1831 | |
1832 bool must_patch = false; | |
1833 if (state.monomorphic()) { | |
1834 // We are here because we are in snapshot code that went monomorphic but | |
1835 // now our cell is cleared because we are running an application. | |
1836 // Ideally we can just patch the cell and return. | |
Toon Verwaest
2014/03/10 13:50:44
Are we sure that we can only get here because of s
mvstanton
2014/03/20 15:51:53
I went to objects-visiting-inl.h and make sure tha
| |
1837 must_patch = arg_count_match != state.args_match() || | |
1838 strict_or_native != state.strict_native(); | |
1839 } else { | |
1840 // We need to patch only if attributes differ from the monomorphic case | |
1841 // built into the generic stub (with arg_count_match = true and | |
1842 // !strict_or_native) | |
1843 must_patch = !arg_count_match || strict_or_native; | |
1844 } | |
1845 | |
1846 Handle<String> name; | |
Toon Verwaest
2014/03/10 13:50:44
Don't you want to initialize this to something lik
mvstanton
2014/03/20 15:51:53
Yes, I could simplify that even more.
| |
1847 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | |
1848 if (js_function->shared()->name()->IsString()) { | |
1849 name = Handle<String>(String::cast(js_function->shared()->name()), | |
1850 isolate()); | |
1851 } | |
1852 | |
1853 if (must_patch) { | |
1854 CallICStub stub(State(state.arg_count(), | |
1855 state.call_as_method(), | |
1856 true, | |
1857 arg_count_match, | |
1858 strict_or_native)); | |
1859 set_target(*stub.GetCode(isolate())); | |
1860 #ifdef DEBUG | |
1861 const char *str = state.monomorphic() | |
1862 ? "CallIC (snapshot miss)" | |
1863 : "CallIC"; | |
1864 #endif | |
1865 TRACE_IC(str, name); | |
1866 } | |
1867 } | |
1868 } | |
1869 } | |
1870 | |
1871 | |
1728 #undef TRACE_IC | 1872 #undef TRACE_IC |
1729 | 1873 |
1730 | 1874 |
1731 // ---------------------------------------------------------------------------- | 1875 // ---------------------------------------------------------------------------- |
1732 // Static IC stub generators. | 1876 // Static IC stub generators. |
1733 // | 1877 // |
1734 | 1878 |
1735 // Used from ic-<arch>.cc. | 1879 // Used from ic-<arch>.cc. |
1880 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | |
1881 HandleScope scope(isolate); | |
1882 ASSERT(args.length() == 4); | |
1883 CallIC ic(isolate); | |
1884 Handle<Object> receiver = args.at<Object>(0); | |
1885 Handle<Object> function = args.at<Object>(1); | |
1886 Handle<FixedArray> vector = args.at<FixedArray>(2); | |
1887 Handle<Smi> slot = args.at<Smi>(3); | |
1888 ic.HandleMiss(receiver, function, vector, slot); | |
1889 return *function; | |
1890 } | |
1891 | |
1892 | |
1736 // Used from ic-<arch>.cc. | 1893 // Used from ic-<arch>.cc. |
1737 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1894 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
1738 HandleScope scope(isolate); | 1895 HandleScope scope(isolate); |
1739 ASSERT(args.length() == 2); | 1896 ASSERT(args.length() == 2); |
1740 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1897 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
1741 Handle<Object> receiver = args.at<Object>(0); | 1898 Handle<Object> receiver = args.at<Object>(0); |
1742 Handle<String> key = args.at<String>(1); | 1899 Handle<String> key = args.at<String>(1); |
1743 ic.UpdateState(receiver, key); | 1900 ic.UpdateState(receiver, key); |
1744 return ic.Load(receiver, key); | 1901 return ic.Load(receiver, key); |
1745 } | 1902 } |
(...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2811 #undef ADDR | 2968 #undef ADDR |
2812 }; | 2969 }; |
2813 | 2970 |
2814 | 2971 |
2815 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2972 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2816 return IC_utilities[id]; | 2973 return IC_utilities[id]; |
2817 } | 2974 } |
2818 | 2975 |
2819 | 2976 |
2820 } } // namespace v8::internal | 2977 } } // namespace v8::internal |
OLD | NEW |