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

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: Comments addressed. 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
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::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
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
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
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
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
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
OLDNEW
« src/ia32/code-stubs-ia32.cc ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698