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

Side by Side Diff: src/ic.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 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
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "accessors.h" 30 #include "accessors.h"
31 #include "api.h" 31 #include "api.h"
32 #include "arguments.h" 32 #include "arguments.h"
33 #include "codegen.h"
33 #include "execution.h" 34 #include "execution.h"
34 #include "ic-inl.h" 35 #include "ic-inl.h"
35 #include "runtime.h" 36 #include "runtime.h"
36 #include "stub-cache.h" 37 #include "stub-cache.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
40 41
41 #ifdef DEBUG 42 #ifdef DEBUG
42 static char TransitionMarkFromState(IC::State state) { 43 static char TransitionMarkFromState(IC::State state) {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 } 152 }
152 } 153 }
153 154
154 return false; 155 return false;
155 } 156 }
156 157
157 158
158 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { 159 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
159 IC::State state = target->ic_state(); 160 IC::State state = target->ic_state();
160 161
161 if (state != MONOMORPHIC) return state; 162 if (state != MONOMORPHIC || !name->IsString()) return state;
162 if (receiver->IsUndefined() || receiver->IsNull()) return state; 163 if (receiver->IsUndefined() || receiver->IsNull()) return state;
163 164
164 InlineCacheHolderFlag cache_holder = 165 InlineCacheHolderFlag cache_holder =
165 Code::ExtractCacheHolderFromFlags(target->flags()); 166 Code::ExtractCacheHolderFromFlags(target->flags());
166 167
167 168
168 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { 169 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
169 // The stub was generated for JSObject but called for non-JSObject. 170 // The stub was generated for JSObject but called for non-JSObject.
170 // IC::GetCodeCacheHolder is not applicable. 171 // IC::GetCodeCacheHolder is not applicable.
171 return MONOMORPHIC; 172 return MONOMORPHIC;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 // Don't clear debug break inline cache as it will remove the break point. 255 // Don't clear debug break inline cache as it will remove the break point.
255 if (target->ic_state() == DEBUG_BREAK) return; 256 if (target->ic_state() == DEBUG_BREAK) return;
256 257
257 switch (target->kind()) { 258 switch (target->kind()) {
258 case Code::LOAD_IC: return LoadIC::Clear(address, target); 259 case Code::LOAD_IC: return LoadIC::Clear(address, target);
259 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); 260 case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
260 case Code::STORE_IC: return StoreIC::Clear(address, target); 261 case Code::STORE_IC: return StoreIC::Clear(address, target);
261 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); 262 case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
262 case Code::CALL_IC: return CallIC::Clear(address, target); 263 case Code::CALL_IC: return CallIC::Clear(address, target);
263 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); 264 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
264 case Code::BINARY_OP_IC: return; // Clearing these is tricky and does not 265 case Code::BINARY_OP_IC:
265 // make any performance difference. 266 case Code::TYPE_RECORDING_BINARY_OP_IC:
267 case Code::COMPARE_IC:
268 // Clearing these is tricky and does not
269 // make any performance difference.
270 return;
266 default: UNREACHABLE(); 271 default: UNREACHABLE();
267 } 272 }
268 } 273 }
269 274
270 275
271 void CallICBase::Clear(Address address, Code* target) { 276 void CallICBase::Clear(Address address, Code* target) {
272 State state = target->ic_state(); 277 State state = target->ic_state();
273 if (state == UNINITIALIZED) return; 278 if (state == UNINITIALIZED) return;
274 Code* code = 279 Code* code =
275 Isolate::Current()->stub_cache()->FindCallInitialize( 280 Isolate::Current()->stub_cache()->FindCallInitialize(
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 if (use_ic) { 1165 if (use_ic) {
1161 Code* stub = generic_stub(); 1166 Code* stub = generic_stub();
1162 if (object->IsString() && key->IsNumber()) { 1167 if (object->IsString() && key->IsNumber()) {
1163 stub = string_stub(); 1168 stub = string_stub();
1164 } else if (object->IsJSObject()) { 1169 } else if (object->IsJSObject()) {
1165 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1170 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1166 if (receiver->HasExternalArrayElements()) { 1171 if (receiver->HasExternalArrayElements()) {
1167 stub = external_array_stub(receiver->GetElementsKind()); 1172 stub = external_array_stub(receiver->GetElementsKind());
1168 } else if (receiver->HasIndexedInterceptor()) { 1173 } else if (receiver->HasIndexedInterceptor()) {
1169 stub = indexed_interceptor_stub(); 1174 stub = indexed_interceptor_stub();
1175 } else if (state == UNINITIALIZED &&
1176 key->IsSmi() &&
1177 receiver->map()->has_fast_elements()) {
1178 StubCache* stub_cache = isolate()->stub_cache();
1179 MaybeObject* probe = stub_cache->ComputeKeyedLoadSpecialized(*receiver);
1180 stub =
1181 probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
1170 } 1182 }
1171 } 1183 }
1172 set_target(stub); 1184 if (stub != NULL) set_target(stub);
1185
1186 #ifdef DEBUG
1187 TraceIC("KeyedLoadIC", key, state, target());
1188 #endif // DEBUG
1189
1173 // For JSObjects with fast elements that are not value wrappers 1190 // For JSObjects with fast elements that are not value wrappers
1174 // and that do not have indexed interceptors, we initialize the 1191 // and that do not have indexed interceptors, we initialize the
1175 // inlined fast case (if present) by patching the inlined map 1192 // inlined fast case (if present) by patching the inlined map
1176 // check. 1193 // check.
1177 if (object->IsJSObject() && 1194 if (object->IsJSObject() &&
1178 !object->IsJSValue() && 1195 !object->IsJSValue() &&
1179 !JSObject::cast(*object)->HasIndexedInterceptor() && 1196 !JSObject::cast(*object)->HasIndexedInterceptor() &&
1180 JSObject::cast(*object)->HasFastElements()) { 1197 JSObject::cast(*object)->HasFastElements()) {
1181 Map* map = JSObject::cast(*object)->map(); 1198 Map* map = JSObject::cast(*object)->map();
1182 PatchInlinedLoad(address(), map); 1199 PatchInlinedLoad(address(), map);
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 } 1399 }
1383 } 1400 }
1384 } 1401 }
1385 1402
1386 // If no inlined store ic was patched, generate a stub for this 1403 // If no inlined store ic was patched, generate a stub for this
1387 // store. 1404 // store.
1388 UpdateCaches(&lookup, state, receiver, name, value); 1405 UpdateCaches(&lookup, state, receiver, name, value);
1389 } 1406 }
1390 } 1407 }
1391 1408
1409 if (receiver->IsJSGlobalProxy()) {
1410 // Generate a generic stub that goes to the runtime when we see a global
1411 // proxy as receiver.
1412 if (target() != global_proxy_stub()) {
1413 set_target(global_proxy_stub());
1414 #ifdef DEBUG
1415 TraceIC("StoreIC", name, state, target());
1416 #endif
1417 }
1418 }
1419
1392 // Set the property. 1420 // Set the property.
1393 return receiver->SetProperty(*name, *value, NONE); 1421 return receiver->SetProperty(*name, *value, NONE);
1394 } 1422 }
1395 1423
1396 1424
1397 void StoreIC::UpdateCaches(LookupResult* lookup, 1425 void StoreIC::UpdateCaches(LookupResult* lookup,
1398 State state, 1426 State state,
1399 Handle<JSObject> receiver, 1427 Handle<JSObject> receiver,
1400 Handle<String> name, 1428 Handle<String> name,
1401 Handle<Object> value) { 1429 Handle<Object> value) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 // the global object). 1559 // the global object).
1532 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1560 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1533 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1561 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1534 1562
1535 if (use_ic) { 1563 if (use_ic) {
1536 Code* stub = generic_stub(); 1564 Code* stub = generic_stub();
1537 if (object->IsJSObject()) { 1565 if (object->IsJSObject()) {
1538 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1566 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1539 if (receiver->HasExternalArrayElements()) { 1567 if (receiver->HasExternalArrayElements()) {
1540 stub = external_array_stub(receiver->GetElementsKind()); 1568 stub = external_array_stub(receiver->GetElementsKind());
1569 } else if (state == UNINITIALIZED &&
1570 key->IsSmi() &&
1571 receiver->map()->has_fast_elements()) {
1572 MaybeObject* probe =
1573 isolate()->stub_cache()->ComputeKeyedStoreSpecialized(*receiver);
1574 stub =
1575 probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked());
1541 } 1576 }
1542 } 1577 }
1543 set_target(stub); 1578 if (stub != NULL) set_target(stub);
1544 } 1579 }
1545 1580
1546 // Set the property. 1581 // Set the property.
1547 return Runtime::SetObjectProperty(isolate(), object, key, value, NONE); 1582 return Runtime::SetObjectProperty(isolate(), object, key, value, NONE);
1548 } 1583 }
1549 1584
1550 1585
1551 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1586 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1552 State state, 1587 State state,
1553 Handle<JSObject> receiver, 1588 Handle<JSObject> receiver,
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
1787 } 1822 }
1788 1823
1789 1824
1790 void BinaryOpIC::patch(Code* code) { 1825 void BinaryOpIC::patch(Code* code) {
1791 set_target(code); 1826 set_target(code);
1792 } 1827 }
1793 1828
1794 1829
1795 const char* BinaryOpIC::GetName(TypeInfo type_info) { 1830 const char* BinaryOpIC::GetName(TypeInfo type_info) {
1796 switch (type_info) { 1831 switch (type_info) {
1832 case UNINIT_OR_SMI: return "UninitOrSmi";
1797 case DEFAULT: return "Default"; 1833 case DEFAULT: return "Default";
1798 case GENERIC: return "Generic"; 1834 case GENERIC: return "Generic";
1799 case HEAP_NUMBERS: return "HeapNumbers"; 1835 case HEAP_NUMBERS: return "HeapNumbers";
1800 case STRINGS: return "Strings"; 1836 case STRINGS: return "Strings";
1801 default: return "Invalid"; 1837 default: return "Invalid";
1802 } 1838 }
1803 } 1839 }
1804 1840
1805 1841
1806 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { 1842 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
1807 switch (type_info) { 1843 switch (type_info) {
1808 // DEFAULT is mapped to UNINITIALIZED so that calls to DEFAULT stubs 1844 case UNINIT_OR_SMI:
1809 // are not cleared at GC. 1845 return UNINITIALIZED;
1810 case DEFAULT: return UNINITIALIZED; 1846 case DEFAULT:
1811 1847 case HEAP_NUMBERS:
1812 // Could have mapped GENERIC to MONOMORPHIC just as well but MEGAMORPHIC is 1848 case STRINGS:
1813 // conceptually closer. 1849 return MONOMORPHIC;
1814 case GENERIC: return MEGAMORPHIC; 1850 case GENERIC:
1815 1851 return MEGAMORPHIC;
1816 default: return MONOMORPHIC;
1817 } 1852 }
1853 UNREACHABLE();
1854 return UNINITIALIZED;
1818 } 1855 }
1819 1856
1820 1857
1821 BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left, 1858 BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left,
1822 Object* right) { 1859 Object* right) {
1823 if (left->IsSmi() && right->IsSmi()) { 1860 if (left->IsSmi() && right->IsSmi()) {
1824 return GENERIC; 1861 // If we have two smi inputs we can reach here because
1862 // of an overflow. Enter default state.
1863 return DEFAULT;
1825 } 1864 }
1826 1865
1827 if (left->IsNumber() && right->IsNumber()) { 1866 if (left->IsNumber() && right->IsNumber()) {
1828 return HEAP_NUMBERS; 1867 return HEAP_NUMBERS;
1829 } 1868 }
1830 1869
1831 if (left->IsString() || right->IsString()) { 1870 if (left->IsString() || right->IsString()) {
1832 // Patching for fast string ADD makes sense even if only one of the 1871 // Patching for fast string ADD makes sense even if only one of the
1833 // arguments is a string. 1872 // arguments is a string.
1834 return STRINGS; 1873 return STRINGS;
1835 } 1874 }
1836 1875
1837 return GENERIC; 1876 return GENERIC;
1838 } 1877 }
1839 1878
1840 1879
1841 // defined in codegen-<arch>.cc 1880 // defined in code-stubs-<arch>.cc
1842 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); 1881 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
1843 1882
1844 1883
1845 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { 1884 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) {
1846 RUNTIME_GET_ISOLATE; 1885 RUNTIME_GET_ISOLATE;
1847 ASSERT(args.length() == 5); 1886 ASSERT(args.length() == 5);
1848 1887
1888 HandleScope scope;
1849 Handle<Object> left = args.at<Object>(0); 1889 Handle<Object> left = args.at<Object>(0);
1850 Handle<Object> right = args.at<Object>(1); 1890 Handle<Object> right = args.at<Object>(1);
1851 int key = Smi::cast(args[2])->value(); 1891 int key = Smi::cast(args[2])->value();
1852 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); 1892 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
1853 #ifdef DEBUG 1893 BinaryOpIC::TypeInfo previous_type =
1854 BinaryOpIC::TypeInfo prev_type_info =
1855 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); 1894 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
1856 #endif // DEBUG 1895
1857 { HandleScope scope; 1896 BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right);
1858 BinaryOpIC::TypeInfo type_info = BinaryOpIC::GetTypeInfo(*left, *right); 1897 Handle<Code> code = GetBinaryOpStub(key, type);
1859 Handle<Code> code = GetBinaryOpStub(key, type_info); 1898 if (!code.is_null()) {
1860 if (!code.is_null()) { 1899 BinaryOpIC ic(isolate);
1861 BinaryOpIC ic(isolate); 1900 ic.patch(*code);
1862 ic.patch(*code); 1901 if (FLAG_trace_ic) {
1863 #ifdef DEBUG 1902 PrintF("[BinaryOpIC (%s->%s)#%s]\n",
1864 if (FLAG_trace_ic) { 1903 BinaryOpIC::GetName(previous_type),
1865 PrintF("[BinaryOpIC (%s->%s)#%s]\n", 1904 BinaryOpIC::GetName(type),
1866 BinaryOpIC::GetName(prev_type_info), 1905 Token::Name(op));
1867 BinaryOpIC::GetName(type_info),
1868 Token::Name(op));
1869 }
1870 #endif // DEBUG
1871 } 1906 }
1872 } 1907 }
1873 1908
1874 HandleScope scope;
1875 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( 1909 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
1876 isolate->thread_local_top()->context_->builtins()); 1910 isolate->thread_local_top()->context_->builtins());
1877
1878 Object* builtin = NULL; // Initialization calms down the compiler. 1911 Object* builtin = NULL; // Initialization calms down the compiler.
1879
1880 switch (op) { 1912 switch (op) {
1881 case Token::ADD: 1913 case Token::ADD:
1882 builtin = builtins->javascript_builtin(Builtins::ADD); 1914 builtin = builtins->javascript_builtin(Builtins::ADD);
1915 break;
1916 case Token::SUB:
1917 builtin = builtins->javascript_builtin(Builtins::SUB);
1918 break;
1919 case Token::MUL:
1920 builtin = builtins->javascript_builtin(Builtins::MUL);
1921 break;
1922 case Token::DIV:
1923 builtin = builtins->javascript_builtin(Builtins::DIV);
1924 break;
1925 case Token::MOD:
1926 builtin = builtins->javascript_builtin(Builtins::MOD);
1927 break;
1928 case Token::BIT_AND:
1929 builtin = builtins->javascript_builtin(Builtins::BIT_AND);
1930 break;
1931 case Token::BIT_OR:
1932 builtin = builtins->javascript_builtin(Builtins::BIT_OR);
1933 break;
1934 case Token::BIT_XOR:
1935 builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
1936 break;
1937 case Token::SHR:
1938 builtin = builtins->javascript_builtin(Builtins::SHR);
1939 break;
1940 case Token::SAR:
1941 builtin = builtins->javascript_builtin(Builtins::SAR);
1942 break;
1943 case Token::SHL:
1944 builtin = builtins->javascript_builtin(Builtins::SHL);
1945 break;
1946 default:
1947 UNREACHABLE();
1948 }
1949
1950 Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
1951
1952 bool caught_exception;
1953 Object** builtin_args[] = { right.location() };
1954 Handle<Object> result = Execution::Call(builtin_function,
1955 left,
1956 ARRAY_SIZE(builtin_args),
1957 builtin_args,
1958 &caught_exception);
1959 if (caught_exception) {
1960 return Failure::Exception();
1961 }
1962 return *result;
1963 }
1964
1965
1966 void TRBinaryOpIC::patch(Code* code) {
1967 set_target(code);
1968 }
1969
1970
1971 const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
1972 switch (type_info) {
1973 case UNINITIALIZED: return "Uninitialized";
1974 case SMI: return "SMI";
1975 case INT32: return "Int32s";
1976 case HEAP_NUMBER: return "HeapNumbers";
1977 case STRING: return "Strings";
1978 case GENERIC: return "Generic";
1979 default: return "Invalid";
1980 }
1981 }
1982
1983
1984 TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) {
1985 switch (type_info) {
1986 case UNINITIALIZED:
1987 return ::v8::internal::UNINITIALIZED;
1988 case SMI:
1989 case INT32:
1990 case HEAP_NUMBER:
1991 case STRING:
1992 return MONOMORPHIC;
1993 case GENERIC:
1994 return MEGAMORPHIC;
1995 }
1996 UNREACHABLE();
1997 return ::v8::internal::UNINITIALIZED;
1998 }
1999
2000
2001 TRBinaryOpIC::TypeInfo TRBinaryOpIC::JoinTypes(TRBinaryOpIC::TypeInfo x,
2002 TRBinaryOpIC::TypeInfo y) {
2003 if (x == UNINITIALIZED) return y;
2004 if (y == UNINITIALIZED) return x;
2005 if (x == STRING && y == STRING) return STRING;
2006 if (x == STRING || y == STRING) return GENERIC;
2007 if (x >= y) return x;
2008 return y;
2009 }
2010
2011 TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left,
2012 Handle<Object> right) {
2013 ::v8::internal::TypeInfo left_type =
2014 ::v8::internal::TypeInfo::TypeFromValue(left);
2015 ::v8::internal::TypeInfo right_type =
2016 ::v8::internal::TypeInfo::TypeFromValue(right);
2017
2018 if (left_type.IsSmi() && right_type.IsSmi()) {
2019 return SMI;
2020 }
2021
2022 if (left_type.IsInteger32() && right_type.IsInteger32()) {
2023 return INT32;
2024 }
2025
2026 if (left_type.IsNumber() && right_type.IsNumber()) {
2027 return HEAP_NUMBER;
2028 }
2029
2030 if (left_type.IsString() || right_type.IsString()) {
2031 // Patching for fast string ADD makes sense even if only one of the
2032 // arguments is a string.
2033 return STRING;
2034 }
2035
2036 return GENERIC;
2037 }
2038
2039
2040 // defined in code-stubs-<arch>.cc
2041 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
2042 Handle<Code> GetTypeRecordingBinaryOpStub(int key,
2043 TRBinaryOpIC::TypeInfo type_info,
2044 TRBinaryOpIC::TypeInfo result_type);
2045
2046
2047 MaybeObject* TypeRecordingBinaryOp_Patch(RUNTIME_CALLING_CONVENTION) {
2048 RUNTIME_GET_ISOLATE;
2049 ASSERT(args.length() == 5);
2050
2051 HandleScope scope(isolate);
2052 Handle<Object> left = args.at<Object>(0);
2053 Handle<Object> right = args.at<Object>(1);
2054 int key = Smi::cast(args[2])->value();
2055 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
2056 TRBinaryOpIC::TypeInfo previous_type =
2057 static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
2058
2059 TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right);
2060 type = TRBinaryOpIC::JoinTypes(type, previous_type);
2061 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED;
2062 if (type == TRBinaryOpIC::STRING && op != Token::ADD) {
2063 type = TRBinaryOpIC::GENERIC;
2064 }
2065 if (type == TRBinaryOpIC::SMI &&
2066 previous_type == TRBinaryOpIC::SMI) {
2067 if (op == Token::DIV || op == Token::MUL) {
2068 // Arithmetic on two Smi inputs has yielded a heap number.
2069 // That is the only way to get here from the Smi stub.
2070 result_type = TRBinaryOpIC::HEAP_NUMBER;
2071 } else {
2072 // Other operations on SMIs that overflow yield int32s.
2073 result_type = TRBinaryOpIC::INT32;
2074 }
2075 }
2076 if (type == TRBinaryOpIC::INT32 &&
2077 previous_type == TRBinaryOpIC::INT32) {
2078 // We must be here because an operation on two INT32 types overflowed.
2079 result_type = TRBinaryOpIC::HEAP_NUMBER;
2080 }
2081
2082 Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type);
2083 if (!code.is_null()) {
2084 TRBinaryOpIC ic(isolate);
2085 ic.patch(*code);
2086 if (FLAG_trace_ic) {
2087 PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n",
2088 TRBinaryOpIC::GetName(previous_type),
2089 TRBinaryOpIC::GetName(type),
2090 TRBinaryOpIC::GetName(result_type),
2091 Token::Name(op));
2092 }
2093 }
2094
2095 Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
2096 isolate->thread_local_top()->context_->builtins());
2097 Object* builtin = NULL; // Initialization calms down the compiler.
2098 switch (op) {
2099 case Token::ADD:
2100 builtin = builtins->javascript_builtin(Builtins::ADD);
1883 break; 2101 break;
1884 case Token::SUB: 2102 case Token::SUB:
1885 builtin = builtins->javascript_builtin(Builtins::SUB); 2103 builtin = builtins->javascript_builtin(Builtins::SUB);
1886 break; 2104 break;
1887 case Token::MUL: 2105 case Token::MUL:
1888 builtin = builtins->javascript_builtin(Builtins::MUL); 2106 builtin = builtins->javascript_builtin(Builtins::MUL);
1889 break; 2107 break;
1890 case Token::DIV: 2108 case Token::DIV:
1891 builtin = builtins->javascript_builtin(Builtins::DIV); 2109 builtin = builtins->javascript_builtin(Builtins::DIV);
1892 break; 2110 break;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1924 ARRAY_SIZE(builtin_args), 2142 ARRAY_SIZE(builtin_args),
1925 builtin_args, 2143 builtin_args,
1926 &caught_exception); 2144 &caught_exception);
1927 if (caught_exception) { 2145 if (caught_exception) {
1928 return Failure::Exception(); 2146 return Failure::Exception();
1929 } 2147 }
1930 return *result; 2148 return *result;
1931 } 2149 }
1932 2150
1933 2151
2152 Handle<Code> CompareIC::GetUninitialized(Token::Value op) {
2153 ICCompareStub stub(op, UNINITIALIZED);
2154 return stub.GetCode();
2155 }
2156
2157
2158 CompareIC::State CompareIC::ComputeState(Code* target) {
2159 int key = target->major_key();
2160 if (key == CodeStub::Compare) return GENERIC;
2161 ASSERT(key == CodeStub::CompareIC);
2162 return static_cast<State>(target->compare_state());
2163 }
2164
2165
2166 const char* CompareIC::GetStateName(State state) {
2167 switch (state) {
2168 case UNINITIALIZED: return "UNINITIALIZED";
2169 case SMIS: return "SMIS";
2170 case HEAP_NUMBERS: return "HEAP_NUMBERS";
2171 case OBJECTS: return "OBJECTS";
2172 case GENERIC: return "GENERIC";
2173 default:
2174 UNREACHABLE();
2175 return NULL;
2176 }
2177 }
2178
2179
2180 CompareIC::State CompareIC::TargetState(Handle<Object> x, Handle<Object> y) {
2181 State state = GetState();
2182 if (state != UNINITIALIZED) return GENERIC;
2183 if (x->IsSmi() && y->IsSmi()) return SMIS;
2184 if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
2185 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC;
2186 if (x->IsJSObject() && y->IsJSObject()) return OBJECTS;
2187 return GENERIC;
2188 }
2189
2190
2191 // Used from ic_<arch>.cc.
2192 Code* CompareIC_Miss(RUNTIME_CALLING_CONVENTION) {
2193 RUNTIME_GET_ISOLATE;
2194 NoHandleAllocation na;
2195 ASSERT(args.length() == 3);
2196 CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value()));
2197 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2198 return ic.target();
2199 }
2200
2201
1934 static const Address IC_utilities[] = { 2202 static const Address IC_utilities[] = {
1935 #define ADDR(name) FUNCTION_ADDR(name), 2203 #define ADDR(name) FUNCTION_ADDR(name),
1936 IC_UTIL_LIST(ADDR) 2204 IC_UTIL_LIST(ADDR)
1937 NULL 2205 NULL
1938 #undef ADDR 2206 #undef ADDR
1939 }; 2207 };
1940 2208
1941 2209
1942 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2210 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1943 return IC_utilities[id]; 2211 return IC_utilities[id];
1944 } 2212 }
1945 2213
1946 2214
1947 } } // namespace v8::internal 2215 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698