| 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 if (new_target->kind() == Code::KEYED_STORE_IC) { | 95 GetTransitionMarkModifier( |
| 96 modifier = GetTransitionMarkModifier( | 96 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
| 97 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | |
| 98 } | |
| 99 PrintF(" (%c->%c%s)", | 97 PrintF(" (%c->%c%s)", |
| 100 TransitionMarkFromState(state()), | 98 TransitionMarkFromState(state()), |
| 101 TransitionMarkFromState(new_state), | 99 TransitionMarkFromState(new_state), |
| 102 modifier); | 100 modifier); |
| 103 name->Print(); | 101 name->Print(); |
| 104 PrintF("]\n"); | 102 PrintF("]\n"); |
| 105 } | 103 } |
| 106 } | 104 } |
| 107 | 105 |
| 108 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 106 #define TRACE_GENERIC_IC(isolate, type, reason) \ |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 Isolate* isolate = target->GetHeap()->isolate(); | 408 Isolate* isolate = target->GetHeap()->isolate(); |
| 411 Code* host = isolate-> | 409 Code* host = isolate-> |
| 412 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 410 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
| 413 if (host->kind() != Code::FUNCTION) return; | 411 if (host->kind() != Code::FUNCTION) return; |
| 414 | 412 |
| 415 if (FLAG_type_info_threshold > 0 && | 413 if (FLAG_type_info_threshold > 0 && |
| 416 old_target->is_inline_cache_stub() && | 414 old_target->is_inline_cache_stub() && |
| 417 target->is_inline_cache_stub()) { | 415 target->is_inline_cache_stub()) { |
| 418 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 416 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
| 419 target->ic_state()); | 417 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 | |
| 424 // Not all Code objects have TypeFeedbackInfo. | 418 // Not all Code objects have TypeFeedbackInfo. |
| 425 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 419 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
| 426 TypeFeedbackInfo* info = | 420 TypeFeedbackInfo* info = |
| 427 TypeFeedbackInfo::cast(host->type_feedback_info()); | 421 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 428 info->change_ic_with_type_info_count(delta); | 422 info->change_ic_with_type_info_count(delta); |
| 429 } | 423 } |
| 430 } | 424 } |
| 431 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 425 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
| 432 TypeFeedbackInfo* info = | 426 TypeFeedbackInfo* info = |
| 433 TypeFeedbackInfo::cast(host->type_feedback_info()); | 427 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 450 | 444 |
| 451 switch (target->kind()) { | 445 switch (target->kind()) { |
| 452 case Code::LOAD_IC: | 446 case Code::LOAD_IC: |
| 453 return LoadIC::Clear(isolate, address, target, constant_pool); | 447 return LoadIC::Clear(isolate, address, target, constant_pool); |
| 454 case Code::KEYED_LOAD_IC: | 448 case Code::KEYED_LOAD_IC: |
| 455 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); | 449 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
| 456 case Code::STORE_IC: | 450 case Code::STORE_IC: |
| 457 return StoreIC::Clear(isolate, address, target, constant_pool); | 451 return StoreIC::Clear(isolate, address, target, constant_pool); |
| 458 case Code::KEYED_STORE_IC: | 452 case Code::KEYED_STORE_IC: |
| 459 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | 453 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
| 460 case Code::CALL_IC: | |
| 461 return CallIC::Clear(isolate, address, target, constant_pool); | |
| 462 case Code::COMPARE_IC: | 454 case Code::COMPARE_IC: |
| 463 return CompareIC::Clear(isolate, address, target, constant_pool); | 455 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 464 case Code::COMPARE_NIL_IC: | 456 case Code::COMPARE_NIL_IC: |
| 465 return CompareNilIC::Clear(address, target, constant_pool); | 457 return CompareNilIC::Clear(address, target, constant_pool); |
| 466 case Code::BINARY_OP_IC: | 458 case Code::BINARY_OP_IC: |
| 467 case Code::TO_BOOLEAN_IC: | 459 case Code::TO_BOOLEAN_IC: |
| 468 // Clearing these is tricky and does not | 460 // Clearing these is tricky and does not |
| 469 // make any performance difference. | 461 // make any performance difference. |
| 470 return; | 462 return; |
| 471 default: UNREACHABLE(); | 463 default: UNREACHABLE(); |
| 472 } | 464 } |
| 473 } | 465 } |
| 474 | 466 |
| 475 | 467 |
| 476 void KeyedLoadIC::Clear(Isolate* isolate, | 468 void KeyedLoadIC::Clear(Isolate* isolate, |
| 477 Address address, | 469 Address address, |
| 478 Code* target, | 470 Code* target, |
| 479 ConstantPoolArray* constant_pool) { | 471 ConstantPoolArray* constant_pool) { |
| 480 if (IsCleared(target)) return; | 472 if (IsCleared(target)) return; |
| 481 // Make sure to also clear the map used in inline fast cases. If we | 473 // Make sure to also clear the map used in inline fast cases. If we |
| 482 // do not clear these maps, cached code can keep objects alive | 474 // do not clear these maps, cached code can keep objects alive |
| 483 // through the embedded maps. | 475 // through the embedded maps. |
| 484 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); | 476 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
| 485 } | 477 } |
| 486 | 478 |
| 487 | 479 |
| 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 | |
| 507 void LoadIC::Clear(Isolate* isolate, | 480 void LoadIC::Clear(Isolate* isolate, |
| 508 Address address, | 481 Address address, |
| 509 Code* target, | 482 Code* target, |
| 510 ConstantPoolArray* constant_pool) { | 483 ConstantPoolArray* constant_pool) { |
| 511 if (IsCleared(target)) return; | 484 if (IsCleared(target)) return; |
| 512 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 485 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 513 Code::LOAD_IC, target->extra_ic_state()); | 486 Code::LOAD_IC, target->extra_ic_state()); |
| 514 SetTargetAtAddress(address, code, constant_pool); | 487 SetTargetAtAddress(address, code, constant_pool); |
| 515 } | 488 } |
| 516 | 489 |
| (...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 // Set the property. | 1269 // Set the property. |
| 1297 Handle<Object> result; | 1270 Handle<Object> result; |
| 1298 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1271 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1299 isolate(), result, | 1272 isolate(), result, |
| 1300 JSReceiver::SetProperty( | 1273 JSReceiver::SetProperty( |
| 1301 receiver, name, value, NONE, strict_mode(), store_mode)); | 1274 receiver, name, value, NONE, strict_mode(), store_mode)); |
| 1302 return *result; | 1275 return *result; |
| 1303 } | 1276 } |
| 1304 | 1277 |
| 1305 | 1278 |
| 1306 void CallIC::State::Print(StringStream* stream) const { | |
| 1307 stream->Add("(args(%d), ", | |
| 1308 argc_); | |
| 1309 stream->Add("%s, ", | |
| 1310 call_type_ == CallIC::METHOD ? "METHOD" : "FUNCTION"); | |
| 1311 stream->Add("%s, ", | |
| 1312 stub_type_ == CallIC::MONOMORPHIC ? | |
| 1313 "MONOMORPHIC" : "NOT_MONOMORPHIC"); | |
| 1314 stream->Add("%s, ", | |
| 1315 argument_check_ == CallIC::ARGUMENTS_MUST_MATCH ? | |
| 1316 "args_must_match" : "args_might_match"); | |
| 1317 stream->Add("%s)", | |
| 1318 strict_mode_ == STRICT ? | |
| 1319 "strict" : "sloppy"); | |
| 1320 } | |
| 1321 | |
| 1322 | |
| 1323 Handle<Code> CallIC::initialize_stub(Isolate* isolate, | |
| 1324 int argc, | |
| 1325 CallType call_type) { | |
| 1326 CallICStub stub(State::DefaultCallState(argc, call_type)); | |
| 1327 Handle<Code> code = stub.GetCode(isolate); | |
| 1328 return code; | |
| 1329 } | |
| 1330 | |
| 1331 | |
| 1332 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1279 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1333 StrictMode strict_mode) { | 1280 StrictMode strict_mode) { |
| 1334 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1281 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
| 1335 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1282 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1336 UNINITIALIZED, extra_state); | 1283 UNINITIALIZED, extra_state); |
| 1337 return ic; | 1284 return ic; |
| 1338 } | 1285 } |
| 1339 | 1286 |
| 1340 | 1287 |
| 1341 Handle<Code> StoreIC::megamorphic_stub() { | 1288 Handle<Code> StoreIC::megamorphic_stub() { |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1794 if (maybe_object) return maybe_object; | 1741 if (maybe_object) return maybe_object; |
| 1795 Handle<Object> result; | 1742 Handle<Object> result; |
| 1796 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1743 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1797 isolate(), result, | 1744 isolate(), result, |
| 1798 Runtime::SetObjectProperty( | 1745 Runtime::SetObjectProperty( |
| 1799 isolate(), object, key, value, NONE, strict_mode())); | 1746 isolate(), object, key, value, NONE, strict_mode())); |
| 1800 return *result; | 1747 return *result; |
| 1801 } | 1748 } |
| 1802 | 1749 |
| 1803 | 1750 |
| 1804 CallIC::State::State(ExtraICState extra_ic_state) | |
| 1805 : argc_(ArgcBits::decode(extra_ic_state)), | |
| 1806 call_type_(CallTypeBits::decode(extra_ic_state)), | |
| 1807 stub_type_(StubTypeBits::decode(extra_ic_state)), | |
| 1808 argument_check_(ArgumentCheckBits::decode(extra_ic_state)), | |
| 1809 strict_mode_(StrictModeBits::decode(extra_ic_state)) { | |
| 1810 } | |
| 1811 | |
| 1812 | |
| 1813 ExtraICState CallIC::State::GetExtraICState() const { | |
| 1814 ExtraICState extra_ic_state = | |
| 1815 ArgcBits::encode(argc_) | | |
| 1816 CallTypeBits::encode(call_type_) | | |
| 1817 StubTypeBits::encode(stub_type_) | | |
| 1818 ArgumentCheckBits::encode(argument_check_) | | |
| 1819 StrictModeBits::encode(strict_mode_); | |
| 1820 return extra_ic_state; | |
| 1821 } | |
| 1822 | |
| 1823 | |
| 1824 CallIC::State CallIC::State::ToGenericState() { | |
| 1825 if (stub_type() == CallIC::MONOMORPHIC) { | |
| 1826 return DefaultCallState(arg_count(), call_type()); | |
| 1827 } | |
| 1828 return *this; | |
| 1829 } | |
| 1830 | |
| 1831 | |
| 1832 CallIC::State CallIC::State::ToMonomorphicState( | |
| 1833 Handle<JSFunction> function) { | |
| 1834 // Choose the right monomorphic handler | |
| 1835 SharedFunctionInfo* shared = function->shared(); | |
| 1836 ArgumentCheck new_argument_check = | |
| 1837 shared->formal_parameter_count() == arg_count() | |
| 1838 ? CallIC::ARGUMENTS_MUST_MATCH | |
| 1839 : CallIC::ARGUMENTS_COUNT_UNKNOWN; | |
| 1840 StrictMode new_strict_mode = shared->strict_mode(); | |
| 1841 if (new_argument_check != argument_check() || | |
| 1842 new_strict_mode != strict_mode()) { | |
| 1843 return MonomorphicCallState(arg_count(), call_type(), new_argument_check, | |
| 1844 new_strict_mode); | |
| 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 Handle<Code> code = stub.GetCode(isolate()); | |
| 1887 // Creating the code above could result in a gc, which clears the type | |
| 1888 // vector. If that happens, our plan to go monomorphic has been | |
| 1889 // pre-empted. | |
| 1890 feedback = vector->get(slot->value()); | |
| 1891 if (feedback == *function) { | |
| 1892 set_target(*code); | |
| 1893 TRACE_IC("CallIC", handle(js_function->shared()->name(), isolate())); | |
| 1894 } | |
| 1895 } | |
| 1896 } | |
| 1897 } | |
| 1898 | |
| 1899 | |
| 1900 #undef TRACE_IC | 1751 #undef TRACE_IC |
| 1901 | 1752 |
| 1902 | 1753 |
| 1903 // ---------------------------------------------------------------------------- | 1754 // ---------------------------------------------------------------------------- |
| 1904 // Static IC stub generators. | 1755 // Static IC stub generators. |
| 1905 // | 1756 // |
| 1906 | 1757 |
| 1907 // Used from ic-<arch>.cc. | 1758 // Used from ic-<arch>.cc. |
| 1908 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | |
| 1909 HandleScope scope(isolate); | |
| 1910 ASSERT(args.length() == 4); | |
| 1911 CallIC ic(isolate); | |
| 1912 Handle<Object> receiver = args.at<Object>(0); | |
| 1913 Handle<Object> function = args.at<Object>(1); | |
| 1914 Handle<FixedArray> vector = args.at<FixedArray>(2); | |
| 1915 Handle<Smi> slot = args.at<Smi>(3); | |
| 1916 ic.HandleMiss(receiver, function, vector, slot); | |
| 1917 return *function; | |
| 1918 } | |
| 1919 | |
| 1920 | |
| 1921 // Used from ic-<arch>.cc. | 1759 // Used from ic-<arch>.cc. |
| 1922 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1760 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
| 1923 HandleScope scope(isolate); | 1761 HandleScope scope(isolate); |
| 1924 ASSERT(args.length() == 2); | 1762 ASSERT(args.length() == 2); |
| 1925 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1763 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 1926 Handle<Object> receiver = args.at<Object>(0); | 1764 Handle<Object> receiver = args.at<Object>(0); |
| 1927 Handle<String> key = args.at<String>(1); | 1765 Handle<String> key = args.at<String>(1); |
| 1928 ic.UpdateState(receiver, key); | 1766 ic.UpdateState(receiver, key); |
| 1929 return ic.Load(receiver, key); | 1767 return ic.Load(receiver, key); |
| 1930 } | 1768 } |
| (...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2999 #undef ADDR | 2837 #undef ADDR |
| 3000 }; | 2838 }; |
| 3001 | 2839 |
| 3002 | 2840 |
| 3003 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2841 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3004 return IC_utilities[id]; | 2842 return IC_utilities[id]; |
| 3005 } | 2843 } |
| 3006 | 2844 |
| 3007 | 2845 |
| 3008 } } // namespace v8::internal | 2846 } } // namespace v8::internal |
| OLD | NEW |