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::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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |