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

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: Addressed comments. 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::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 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 Isolate* isolate = target->GetHeap()->isolate(); 401 Isolate* isolate = target->GetHeap()->isolate();
400 Code* host = isolate-> 402 Code* host = isolate->
401 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 403 inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
402 if (host->kind() != Code::FUNCTION) return; 404 if (host->kind() != Code::FUNCTION) return;
403 405
404 if (FLAG_type_info_threshold > 0 && 406 if (FLAG_type_info_threshold > 0 &&
405 old_target->is_inline_cache_stub() && 407 old_target->is_inline_cache_stub() &&
406 target->is_inline_cache_stub()) { 408 target->is_inline_cache_stub()) {
407 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), 409 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
408 target->ic_state()); 410 target->ic_state());
411 // Call ICs don't have interesting state changes from this point
412 // of view.
413 ASSERT(target->kind() != Code::CALL_IC || delta == 0);
414
409 // Not all Code objects have TypeFeedbackInfo. 415 // Not all Code objects have TypeFeedbackInfo.
410 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { 416 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
411 TypeFeedbackInfo* info = 417 TypeFeedbackInfo* info =
412 TypeFeedbackInfo::cast(host->type_feedback_info()); 418 TypeFeedbackInfo::cast(host->type_feedback_info());
413 info->change_ic_with_type_info_count(delta); 419 info->change_ic_with_type_info_count(delta);
414 } 420 }
415 } 421 }
416 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { 422 if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
417 TypeFeedbackInfo* info = 423 TypeFeedbackInfo* info =
418 TypeFeedbackInfo::cast(host->type_feedback_info()); 424 TypeFeedbackInfo::cast(host->type_feedback_info());
(...skipping 16 matching lines...) Expand all
435 441
436 switch (target->kind()) { 442 switch (target->kind()) {
437 case Code::LOAD_IC: 443 case Code::LOAD_IC:
438 return LoadIC::Clear(isolate, address, target, constant_pool); 444 return LoadIC::Clear(isolate, address, target, constant_pool);
439 case Code::KEYED_LOAD_IC: 445 case Code::KEYED_LOAD_IC:
440 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); 446 return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
441 case Code::STORE_IC: 447 case Code::STORE_IC:
442 return StoreIC::Clear(isolate, address, target, constant_pool); 448 return StoreIC::Clear(isolate, address, target, constant_pool);
443 case Code::KEYED_STORE_IC: 449 case Code::KEYED_STORE_IC:
444 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); 450 return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
451 case Code::CALL_IC:
452 return CallIC::Clear(isolate, address, target, constant_pool);
445 case Code::COMPARE_IC: 453 case Code::COMPARE_IC:
446 return CompareIC::Clear(isolate, address, target, constant_pool); 454 return CompareIC::Clear(isolate, address, target, constant_pool);
447 case Code::COMPARE_NIL_IC: 455 case Code::COMPARE_NIL_IC:
448 return CompareNilIC::Clear(address, target, constant_pool); 456 return CompareNilIC::Clear(address, target, constant_pool);
449 case Code::BINARY_OP_IC: 457 case Code::BINARY_OP_IC:
450 case Code::TO_BOOLEAN_IC: 458 case Code::TO_BOOLEAN_IC:
451 // Clearing these is tricky and does not 459 // Clearing these is tricky and does not
452 // make any performance difference. 460 // make any performance difference.
453 return; 461 return;
454 default: UNREACHABLE(); 462 default: UNREACHABLE();
455 } 463 }
456 } 464 }
457 465
458 466
459 void KeyedLoadIC::Clear(Isolate* isolate, 467 void KeyedLoadIC::Clear(Isolate* isolate,
460 Address address, 468 Address address,
461 Code* target, 469 Code* target,
462 ConstantPoolArray* constant_pool) { 470 ConstantPoolArray* constant_pool) {
463 if (IsCleared(target)) return; 471 if (IsCleared(target)) return;
464 // Make sure to also clear the map used in inline fast cases. If we 472 // Make sure to also clear the map used in inline fast cases. If we
465 // do not clear these maps, cached code can keep objects alive 473 // do not clear these maps, cached code can keep objects alive
466 // through the embedded maps. 474 // through the embedded maps.
467 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); 475 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
468 } 476 }
469 477
470 478
479 void CallIC::Clear(Isolate* isolate,
480 Address address,
481 Code* target,
482 ConstantPoolArray* constant_pool) {
483 // CallIC just has a generic stub and a monomorphic stub. Only clear if we
484 // are monomorphic
485 if (target->ic_state() != ::v8::internal::MONOMORPHIC) return;
486
487 CallIC::State existing_state(target->extra_ic_state());
488
489 // Install default stub with the immutable parts of existing state.
490 HandleScope scope(isolate);
491 CallICStub stub(State::DefaultCallState(existing_state.arg_count(),
492 existing_state.call_type()));
493 Code* code = *stub.GetCode(isolate);
494 SetTargetAtAddress(address, code, constant_pool);
495 }
496
497
471 void LoadIC::Clear(Isolate* isolate, 498 void LoadIC::Clear(Isolate* isolate,
472 Address address, 499 Address address,
473 Code* target, 500 Code* target,
474 ConstantPoolArray* constant_pool) { 501 ConstantPoolArray* constant_pool) {
475 if (IsCleared(target)) return; 502 if (IsCleared(target)) return;
476 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( 503 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
477 Code::LOAD_IC, target->extra_ic_state()); 504 Code::LOAD_IC, target->extra_ic_state());
478 SetTargetAtAddress(address, code, constant_pool); 505 SetTargetAtAddress(address, code, constant_pool);
479 } 506 }
480 507
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 } 1284 }
1258 1285
1259 // Set the property. 1286 // Set the property.
1260 Handle<Object> result = JSReceiver::SetProperty( 1287 Handle<Object> result = JSReceiver::SetProperty(
1261 receiver, name, value, NONE, strict_mode(), store_mode); 1288 receiver, name, value, NONE, strict_mode(), store_mode);
1262 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1289 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1263 return *result; 1290 return *result;
1264 } 1291 }
1265 1292
1266 1293
1294 void CallIC::State::Print(StringStream* stream) const {
1295 stream->Add("(args(%d), ",
1296 argc_);
1297 stream->Add("%s, ",
1298 call_type_ == CallIC::METHOD ? "METHOD" : "FUNCTION");
1299 stream->Add("%s, ",
1300 stub_type_ == CallIC::MONOMORPHIC ?
1301 "MONOMORPHIC" : "NOT_MONOMORPHIC");
1302 stream->Add("%s, ",
1303 argument_check_ == CallIC::ARGUMENTS_MUST_MATCH ?
1304 "args_must_match" : "args_might_match");
1305 stream->Add("%s)",
1306 function_attributes_ == CallIC::STRICT_OR_NATIVE ?
1307 "strict_or_native" : "not_strict_or_native");
1308 }
1309
1310
1311 Handle<Code> CallIC::initialize_stub(Isolate* isolate,
1312 int argc,
1313 CallType call_type) {
1314 CallICStub stub(State::DefaultCallState(argc, call_type));
1315 Handle<Code> code = stub.GetCode(isolate);
1316 return code;
1317 }
1318
1319
1267 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, 1320 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
1268 StrictMode strict_mode) { 1321 StrictMode strict_mode) {
1269 ExtraICState extra_state = ComputeExtraICState(strict_mode); 1322 ExtraICState extra_state = ComputeExtraICState(strict_mode);
1270 Handle<Code> ic = isolate->stub_cache()->ComputeStore( 1323 Handle<Code> ic = isolate->stub_cache()->ComputeStore(
1271 UNINITIALIZED, extra_state); 1324 UNINITIALIZED, extra_state);
1272 return ic; 1325 return ic;
1273 } 1326 }
1274 1327
1275 1328
1276 Handle<Code> StoreIC::megamorphic_stub() { 1329 Handle<Code> StoreIC::megamorphic_stub() {
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 if (maybe_object) return maybe_object; 1791 if (maybe_object) return maybe_object;
1739 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key, 1792 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key,
1740 value, 1793 value,
1741 NONE, 1794 NONE,
1742 strict_mode()); 1795 strict_mode());
1743 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1796 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1744 return *result; 1797 return *result;
1745 } 1798 }
1746 1799
1747 1800
1801 CallIC::State::State(ExtraICState extra_ic_state)
1802 : argc_(ArgBits::decode(extra_ic_state)),
1803 call_type_(CallTypeBits::decode(extra_ic_state)),
1804 stub_type_(StubTypeBits::decode(extra_ic_state)),
1805 argument_check_(ArgumentCheckBits::decode(extra_ic_state)),
1806 function_attributes_(FunctionAttributeBits::decode(extra_ic_state)) {
1807 }
1808
1809
1810 ExtraICState CallIC::State::GetExtraICState() const {
1811 ExtraICState extra_ic_state =
1812 ArgBits::encode(argc_) |
1813 CallTypeBits::encode(call_type_) |
1814 StubTypeBits::encode(stub_type_) |
1815 ArgumentCheckBits::encode(argument_check_) |
1816 FunctionAttributeBits::encode(function_attributes_);
1817 return extra_ic_state;
1818 }
1819
1820
1821 CallIC::State CallIC::State::ToGenericState() {
1822 if (stub_type() == CallIC::MONOMORPHIC) {
1823 return DefaultCallState(arg_count(), call_type());
1824 }
1825 return *this;
1826 }
1827
1828
1829 CallIC::State CallIC::State::ToMonomorphicState(
1830 Handle<JSFunction> function) {
1831 // Choose the right monomorphic handler
1832 SharedFunctionInfo* shared = function->shared();
1833 ArgumentCheck new_argument_check =
1834 shared->formal_parameter_count() == arg_count()
1835 ? CallIC::ARGUMENTS_MUST_MATCH
1836 : CallIC::ARGUMENTS_COUNT_UNKNOWN;
1837 FunctionAttributes new_function_attributes =
1838 (shared->strict_mode() == STRICT || shared->native())
1839 ? CallIC::STRICT_OR_NATIVE
1840 : CallIC::SLOPPY_OR_NONNATIVE;
1841 if (new_argument_check != argument_check() ||
1842 new_function_attributes != function_attributes()) {
1843 return MonomorphicCallState(arg_count(), call_type(), new_argument_check,
1844 new_function_attributes);
1845 }
1846
1847 return *this;
1848 }
1849
1850
1851 void CallIC::HandleMiss(Handle<Object> receiver,
1852 Handle<Object> function,
1853 Handle<FixedArray> vector,
1854 Handle<Smi> slot) {
1855 State state(target()->extra_ic_state());
1856 Object* feedback = vector->get(slot->value());
1857
1858 if (feedback->IsJSFunction() || !function->IsJSFunction()) {
1859 // We are going generic.
1860 ASSERT(!function->IsJSFunction() || *function != feedback);
1861
1862 vector->set(slot->value(),
1863 *TypeFeedbackInfo::MegamorphicSentinel(isolate()));
1864
1865 // We only need to patch if we currently don't have the default stub in
1866 // place.
1867 State new_state = state.ToGenericState();
1868 if (new_state != state) {
1869 CallICStub stub(new_state);
1870 set_target(*stub.GetCode(isolate()));
1871 TRACE_GENERIC_IC(isolate(), "CallIC", "generic");
1872 }
1873 } else {
1874 // If we came here feedback must be the uninitialized sentinel,
1875 // and we are going monomorphic.
1876 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()));
1877 ASSERT(state.stub_type() != CallIC::MONOMORPHIC);
1878
1879 vector->set(slot->value(), *function);
1880
1881 // Choose the right monomorphic handler
1882 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1883 State new_state = state.ToMonomorphicState(js_function);
1884 if (new_state != state) {
1885 CallICStub stub(new_state);
1886 set_target(*stub.GetCode(isolate()));
1887 TRACE_IC("CallIC", Handle<Object>(js_function->shared()->name(),
1888 isolate()));
1889 }
1890 }
1891 }
1892
1893
1748 #undef TRACE_IC 1894 #undef TRACE_IC
1749 1895
1750 1896
1751 // ---------------------------------------------------------------------------- 1897 // ----------------------------------------------------------------------------
1752 // Static IC stub generators. 1898 // Static IC stub generators.
1753 // 1899 //
1754 1900
1755 // Used from ic-<arch>.cc. 1901 // Used from ic-<arch>.cc.
1902 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
1903 HandleScope scope(isolate);
1904 ASSERT(args.length() == 4);
1905 CallIC ic(isolate);
1906 Handle<Object> receiver = args.at<Object>(0);
1907 Handle<Object> function = args.at<Object>(1);
1908 Handle<FixedArray> vector = args.at<FixedArray>(2);
1909 Handle<Smi> slot = args.at<Smi>(3);
1910 ic.HandleMiss(receiver, function, vector, slot);
1911 return *function;
1912 }
1913
1914
1756 // Used from ic-<arch>.cc. 1915 // Used from ic-<arch>.cc.
1757 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 1916 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
1758 HandleScope scope(isolate); 1917 HandleScope scope(isolate);
1759 ASSERT(args.length() == 2); 1918 ASSERT(args.length() == 2);
1760 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 1919 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
1761 Handle<Object> receiver = args.at<Object>(0); 1920 Handle<Object> receiver = args.at<Object>(0);
1762 Handle<String> key = args.at<String>(1); 1921 Handle<String> key = args.at<String>(1);
1763 ic.UpdateState(receiver, key); 1922 ic.UpdateState(receiver, key);
1764 return ic.Load(receiver, key); 1923 return ic.Load(receiver, key);
1765 } 1924 }
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after
2834 #undef ADDR 2993 #undef ADDR
2835 }; 2994 };
2836 2995
2837 2996
2838 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2997 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2839 return IC_utilities[id]; 2998 return IC_utilities[id];
2840 } 2999 }
2841 3000
2842 3001
2843 } } // namespace v8::internal 3002 } } // 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