| 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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 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  Loading... | 
| 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 779 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1269   // Set the property. | 1296   // Set the property. | 
| 1270   Handle<Object> result; | 1297   Handle<Object> result; | 
| 1271   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1298   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
| 1272       isolate(), result, | 1299       isolate(), result, | 
| 1273       JSReceiver::SetProperty( | 1300       JSReceiver::SetProperty( | 
| 1274           receiver, name, value, NONE, strict_mode(), store_mode)); | 1301           receiver, name, value, NONE, strict_mode(), store_mode)); | 
| 1275   return *result; | 1302   return *result; | 
| 1276 } | 1303 } | 
| 1277 | 1304 | 
| 1278 | 1305 | 
|  | 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 | 
| 1279 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1332 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 
| 1280                                       StrictMode strict_mode) { | 1333                                       StrictMode strict_mode) { | 
| 1281   ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1334   ExtraICState extra_state = ComputeExtraICState(strict_mode); | 
| 1282   Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1335   Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 
| 1283       UNINITIALIZED, extra_state); | 1336       UNINITIALIZED, extra_state); | 
| 1284   return ic; | 1337   return ic; | 
| 1285 } | 1338 } | 
| 1286 | 1339 | 
| 1287 | 1340 | 
| 1288 Handle<Code> StoreIC::megamorphic_stub() { | 1341 Handle<Code> StoreIC::megamorphic_stub() { | 
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1741   if (maybe_object) return maybe_object; | 1794   if (maybe_object) return maybe_object; | 
| 1742   Handle<Object> result; | 1795   Handle<Object> result; | 
| 1743   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1796   ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 
| 1744       isolate(), result, | 1797       isolate(), result, | 
| 1745       Runtime::SetObjectProperty( | 1798       Runtime::SetObjectProperty( | 
| 1746           isolate(), object, key, value,  NONE, strict_mode())); | 1799           isolate(), object, key, value,  NONE, strict_mode())); | 
| 1747   return *result; | 1800   return *result; | 
| 1748 } | 1801 } | 
| 1749 | 1802 | 
| 1750 | 1803 | 
|  | 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 | 
| 1751 #undef TRACE_IC | 1900 #undef TRACE_IC | 
| 1752 | 1901 | 
| 1753 | 1902 | 
| 1754 // ---------------------------------------------------------------------------- | 1903 // ---------------------------------------------------------------------------- | 
| 1755 // Static IC stub generators. | 1904 // Static IC stub generators. | 
| 1756 // | 1905 // | 
| 1757 | 1906 | 
| 1758 // Used from ic-<arch>.cc. | 1907 // 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 | 
| 1759 // Used from ic-<arch>.cc. | 1921 // Used from ic-<arch>.cc. | 
| 1760 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1922 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 
| 1761   HandleScope scope(isolate); | 1923   HandleScope scope(isolate); | 
| 1762   ASSERT(args.length() == 2); | 1924   ASSERT(args.length() == 2); | 
| 1763   LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1925   LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 
| 1764   Handle<Object> receiver = args.at<Object>(0); | 1926   Handle<Object> receiver = args.at<Object>(0); | 
| 1765   Handle<String> key = args.at<String>(1); | 1927   Handle<String> key = args.at<String>(1); | 
| 1766   ic.UpdateState(receiver, key); | 1928   ic.UpdateState(receiver, key); | 
| 1767   return ic.Load(receiver, key); | 1929   return ic.Load(receiver, key); | 
| 1768 } | 1930 } | 
| (...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2837 #undef ADDR | 2999 #undef ADDR | 
| 2838 }; | 3000 }; | 
| 2839 | 3001 | 
| 2840 | 3002 | 
| 2841 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3003 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 
| 2842   return IC_utilities[id]; | 3004   return IC_utilities[id]; | 
| 2843 } | 3005 } | 
| 2844 | 3006 | 
| 2845 | 3007 | 
| 2846 } }  // namespace v8::internal | 3008 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|