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

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, 8 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
« no previous file with comments | « 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::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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 Isolate* isolate = target->GetHeap()->isolate(); 410 Isolate* isolate = target->GetHeap()->isolate();
409 Code* host = isolate-> 411 Code* host = isolate->
410 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 412 inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
411 if (host->kind() != Code::FUNCTION) return; 413 if (host->kind() != Code::FUNCTION) return;
412 414
413 if (FLAG_type_info_threshold > 0 && 415 if (FLAG_type_info_threshold > 0 &&
414 old_target->is_inline_cache_stub() && 416 old_target->is_inline_cache_stub() &&
415 target->is_inline_cache_stub()) { 417 target->is_inline_cache_stub()) {
416 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), 418 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
417 target->ic_state()); 419 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
418 // Not all Code objects have TypeFeedbackInfo. 424 // Not all Code objects have TypeFeedbackInfo.
419 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { 425 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
420 TypeFeedbackInfo* info = 426 TypeFeedbackInfo* info =
421 TypeFeedbackInfo::cast(host->type_feedback_info()); 427 TypeFeedbackInfo::cast(host->type_feedback_info());
422 info->change_ic_with_type_info_count(delta); 428 info->change_ic_with_type_info_count(delta);
423 } 429 }
424 } 430 }
425 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { 431 if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
426 TypeFeedbackInfo* info = 432 TypeFeedbackInfo* info =
427 TypeFeedbackInfo::cast(host->type_feedback_info()); 433 TypeFeedbackInfo::cast(host->type_feedback_info());
(...skipping 16 matching lines...) Expand all
444 450
445 switch (target->kind()) { 451 switch (target->kind()) {
446 case Code::LOAD_IC: 452 case Code::LOAD_IC:
447 return LoadIC::Clear(isolate, address, target, constant_pool); 453 return LoadIC::Clear(isolate, address, target, constant_pool);
448 case Code::KEYED_LOAD_IC: 454 case Code::KEYED_LOAD_IC:
449 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); 455 return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
450 case Code::STORE_IC: 456 case Code::STORE_IC:
451 return StoreIC::Clear(isolate, address, target, constant_pool); 457 return StoreIC::Clear(isolate, address, target, constant_pool);
452 case Code::KEYED_STORE_IC: 458 case Code::KEYED_STORE_IC:
453 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); 459 return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
460 case Code::CALL_IC:
461 return CallIC::Clear(isolate, address, target, constant_pool);
454 case Code::COMPARE_IC: 462 case Code::COMPARE_IC:
455 return CompareIC::Clear(isolate, address, target, constant_pool); 463 return CompareIC::Clear(isolate, address, target, constant_pool);
456 case Code::COMPARE_NIL_IC: 464 case Code::COMPARE_NIL_IC:
457 return CompareNilIC::Clear(address, target, constant_pool); 465 return CompareNilIC::Clear(address, target, constant_pool);
458 case Code::BINARY_OP_IC: 466 case Code::BINARY_OP_IC:
459 case Code::TO_BOOLEAN_IC: 467 case Code::TO_BOOLEAN_IC:
460 // Clearing these is tricky and does not 468 // Clearing these is tricky and does not
461 // make any performance difference. 469 // make any performance difference.
462 return; 470 return;
463 default: UNREACHABLE(); 471 default: UNREACHABLE();
464 } 472 }
465 } 473 }
466 474
467 475
468 void KeyedLoadIC::Clear(Isolate* isolate, 476 void KeyedLoadIC::Clear(Isolate* isolate,
469 Address address, 477 Address address,
470 Code* target, 478 Code* target,
471 ConstantPoolArray* constant_pool) { 479 ConstantPoolArray* constant_pool) {
472 if (IsCleared(target)) return; 480 if (IsCleared(target)) return;
473 // Make sure to also clear the map used in inline fast cases. If we 481 // Make sure to also clear the map used in inline fast cases. If we
474 // do not clear these maps, cached code can keep objects alive 482 // do not clear these maps, cached code can keep objects alive
475 // through the embedded maps. 483 // through the embedded maps.
476 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); 484 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
477 } 485 }
478 486
479 487
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
480 void LoadIC::Clear(Isolate* isolate, 507 void LoadIC::Clear(Isolate* isolate,
481 Address address, 508 Address address,
482 Code* target, 509 Code* target,
483 ConstantPoolArray* constant_pool) { 510 ConstantPoolArray* constant_pool) {
484 if (IsCleared(target)) return; 511 if (IsCleared(target)) return;
485 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( 512 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
486 Code::LOAD_IC, target->extra_ic_state()); 513 Code::LOAD_IC, target->extra_ic_state());
487 SetTargetAtAddress(address, code, constant_pool); 514 SetTargetAtAddress(address, code, constant_pool);
488 } 515 }
489 516
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 } 1292 }
1266 1293
1267 // Set the property. 1294 // Set the property.
1268 Handle<Object> result = JSReceiver::SetProperty( 1295 Handle<Object> result = JSReceiver::SetProperty(
1269 receiver, name, value, NONE, strict_mode(), store_mode); 1296 receiver, name, value, NONE, strict_mode(), store_mode);
1270 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1297 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1271 return *result; 1298 return *result;
1272 } 1299 }
1273 1300
1274 1301
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
1275 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, 1328 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
1276 StrictMode strict_mode) { 1329 StrictMode strict_mode) {
1277 ExtraICState extra_state = ComputeExtraICState(strict_mode); 1330 ExtraICState extra_state = ComputeExtraICState(strict_mode);
1278 Handle<Code> ic = isolate->stub_cache()->ComputeStore( 1331 Handle<Code> ic = isolate->stub_cache()->ComputeStore(
1279 UNINITIALIZED, extra_state); 1332 UNINITIALIZED, extra_state);
1280 return ic; 1333 return ic;
1281 } 1334 }
1282 1335
1283 1336
1284 Handle<Code> StoreIC::megamorphic_stub() { 1337 Handle<Code> StoreIC::megamorphic_stub() {
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 if (maybe_object) return maybe_object; 1790 if (maybe_object) return maybe_object;
1738 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, 1791 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key,
1739 value, 1792 value,
1740 NONE, 1793 NONE,
1741 strict_mode()); 1794 strict_mode());
1742 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1795 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1743 return *result; 1796 return *result;
1744 } 1797 }
1745 1798
1746 1799
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
1747 #undef TRACE_IC 1890 #undef TRACE_IC
1748 1891
1749 1892
1750 // ---------------------------------------------------------------------------- 1893 // ----------------------------------------------------------------------------
1751 // Static IC stub generators. 1894 // Static IC stub generators.
1752 // 1895 //
1753 1896
1754 // Used from ic-<arch>.cc. 1897 // 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
1755 // Used from ic-<arch>.cc. 1911 // Used from ic-<arch>.cc.
1756 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 1912 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
1757 HandleScope scope(isolate); 1913 HandleScope scope(isolate);
1758 ASSERT(args.length() == 2); 1914 ASSERT(args.length() == 2);
1759 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 1915 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
1760 Handle<Object> receiver = args.at<Object>(0); 1916 Handle<Object> receiver = args.at<Object>(0);
1761 Handle<String> key = args.at<String>(1); 1917 Handle<String> key = args.at<String>(1);
1762 ic.UpdateState(receiver, key); 1918 ic.UpdateState(receiver, key);
1763 return ic.Load(receiver, key); 1919 return ic.Load(receiver, key);
1764 } 1920 }
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after
2833 #undef ADDR 2989 #undef ADDR
2834 }; 2990 };
2835 2991
2836 2992
2837 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2993 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2838 return IC_utilities[id]; 2994 return IC_utilities[id];
2839 } 2995 }
2840 2996
2841 2997
2842 } } // namespace v8::internal 2998 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698