Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: src/ic.cc

Issue 172523002: Create a function call IC (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/ic.h ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« src/ic.h ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698