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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 } \ | 110 } \ |
111 } while (false) | 111 } while (false) |
112 | 112 |
113 #else | 113 #else |
114 #define TRACE_GENERIC_IC(isolate, type, reason) | 114 #define TRACE_GENERIC_IC(isolate, type, reason) |
115 #endif // DEBUG | 115 #endif // DEBUG |
116 | 116 |
117 #define TRACE_IC(type, name) \ | 117 #define TRACE_IC(type, name) \ |
118 ASSERT((TraceIC(type, name), true)) | 118 ASSERT((TraceIC(type, name), true)) |
119 | 119 |
120 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 120 IC::IC(FrameDepth depth, Isolate* isolate) |
| 121 : isolate_(isolate), |
| 122 target_set_(false) { |
121 // To improve the performance of the (much used) IC code, we unfold a few | 123 // To improve the performance of the (much used) IC code, we unfold a few |
122 // levels of the stack frame iteration code. This yields a ~35% speedup when | 124 // levels of the stack frame iteration code. This yields a ~35% speedup when |
123 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 125 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
124 const Address entry = | 126 const Address entry = |
125 Isolate::c_entry_fp(isolate->thread_local_top()); | 127 Isolate::c_entry_fp(isolate->thread_local_top()); |
126 Address* pc_address = | 128 Address* pc_address = |
127 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 129 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
128 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 130 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
129 // If there's another JavaScript frame on the stack or a | 131 // If there's another JavaScript frame on the stack or a |
130 // StubFailureTrampoline, we need to look one frame further down the stack to | 132 // StubFailureTrampoline, we need to look one frame further down the stack to |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1356 } | 1358 } |
1357 | 1359 |
1358 | 1360 |
1359 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, | 1361 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, |
1360 Handle<Object> key, | 1362 Handle<Object> key, |
1361 ICMissMode miss_mode) { | 1363 ICMissMode miss_mode) { |
1362 if (MigrateDeprecated(object)) { | 1364 if (MigrateDeprecated(object)) { |
1363 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1365 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
1364 } | 1366 } |
1365 | 1367 |
| 1368 MaybeObject* maybe_object = NULL; |
| 1369 Handle<Code> stub = generic_stub(); |
| 1370 |
1366 // Check for values that can be converted into an internalized string directly | 1371 // Check for values that can be converted into an internalized string directly |
1367 // or is representable as a smi. | 1372 // or is representable as a smi. |
1368 key = TryConvertKey(key, isolate()); | 1373 key = TryConvertKey(key, isolate()); |
1369 | 1374 |
1370 if (key->IsInternalizedString()) { | 1375 if (key->IsInternalizedString()) { |
1371 return LoadIC::Load(object, Handle<String>::cast(key)); | 1376 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); |
| 1377 if (maybe_object->IsFailure()) return maybe_object; |
| 1378 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1379 ASSERT(!object->IsJSGlobalProxy()); |
| 1380 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1381 if (object->IsString() && key->IsNumber()) { |
| 1382 if (state() == UNINITIALIZED) stub = string_stub(); |
| 1383 } else if (object->IsJSObject()) { |
| 1384 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1385 if (receiver->elements()->map() == |
| 1386 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1387 stub = non_strict_arguments_stub(); |
| 1388 } else if (receiver->HasIndexedInterceptor()) { |
| 1389 stub = indexed_interceptor_stub(); |
| 1390 } else if (!key->ToSmi()->IsFailure() && |
| 1391 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 1392 stub = LoadElementStub(receiver); |
| 1393 } |
| 1394 } |
| 1395 } |
1372 } | 1396 } |
1373 | 1397 |
1374 if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1398 if (!is_target_set()) { |
1375 ASSERT(!object->IsJSGlobalProxy()); | 1399 if (*stub == *generic_stub()) { |
1376 Handle<Code> stub = generic_stub(); | 1400 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
1377 if (miss_mode == MISS_FORCE_GENERIC) { | |
1378 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | |
1379 } else if (object->IsString() && key->IsNumber()) { | |
1380 if (state() == UNINITIALIZED) stub = string_stub(); | |
1381 } else if (object->IsJSObject()) { | |
1382 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
1383 if (receiver->elements()->map() == | |
1384 isolate()->heap()->non_strict_arguments_elements_map()) { | |
1385 stub = non_strict_arguments_stub(); | |
1386 } else if (receiver->HasIndexedInterceptor()) { | |
1387 stub = indexed_interceptor_stub(); | |
1388 } else if (!key->ToSmi()->IsFailure() && | |
1389 (!target().is_identical_to(non_strict_arguments_stub()))) { | |
1390 stub = LoadElementStub(receiver); | |
1391 } | |
1392 } | 1401 } |
1393 | |
1394 ASSERT(!stub.is_null()); | 1402 ASSERT(!stub.is_null()); |
1395 set_target(*stub); | 1403 set_target(*stub); |
1396 TRACE_IC("LoadIC", key); | 1404 TRACE_IC("LoadIC", key); |
1397 } | 1405 } |
1398 | 1406 |
1399 | 1407 if (maybe_object != NULL) return maybe_object; |
1400 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1408 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
1401 } | 1409 } |
1402 | 1410 |
1403 | 1411 |
1404 static bool LookupForWrite(Handle<JSObject> receiver, | 1412 static bool LookupForWrite(Handle<JSObject> receiver, |
1405 Handle<String> name, | 1413 Handle<String> name, |
1406 Handle<Object> value, | 1414 Handle<Object> value, |
1407 LookupResult* lookup, | 1415 LookupResult* lookup, |
1408 IC* ic) { | 1416 IC* ic) { |
1409 Handle<JSObject> holder = receiver; | 1417 Handle<JSObject> holder = receiver; |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1929 ICMissMode miss_mode) { | 1937 ICMissMode miss_mode) { |
1930 if (MigrateDeprecated(object)) { | 1938 if (MigrateDeprecated(object)) { |
1931 return Runtime::SetObjectPropertyOrFail( | 1939 return Runtime::SetObjectPropertyOrFail( |
1932 isolate(), object , key, value, NONE, strict_mode()); | 1940 isolate(), object , key, value, NONE, strict_mode()); |
1933 } | 1941 } |
1934 | 1942 |
1935 // Check for values that can be converted into an internalized string directly | 1943 // Check for values that can be converted into an internalized string directly |
1936 // or is representable as a smi. | 1944 // or is representable as a smi. |
1937 key = TryConvertKey(key, isolate()); | 1945 key = TryConvertKey(key, isolate()); |
1938 | 1946 |
| 1947 MaybeObject* maybe_object = NULL; |
| 1948 Handle<Code> stub = generic_stub(); |
| 1949 |
1939 if (key->IsInternalizedString()) { | 1950 if (key->IsInternalizedString()) { |
1940 return StoreIC::Store(object, | 1951 maybe_object = StoreIC::Store(object, |
1941 Handle<String>::cast(key), | 1952 Handle<String>::cast(key), |
1942 value, | 1953 value, |
1943 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1954 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
| 1955 if (maybe_object->IsFailure()) return maybe_object; |
| 1956 } else { |
| 1957 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
| 1958 !(FLAG_harmony_observation && object->IsJSObject() && |
| 1959 JSObject::cast(*object)->map()->is_observed()); |
| 1960 if (use_ic && !object->IsSmi()) { |
| 1961 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 1962 // expect to be able to trap element sets to objects with those maps in |
| 1963 // the runtime to enable optimization of element hole access. |
| 1964 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 1965 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
| 1966 } |
| 1967 |
| 1968 if (use_ic) { |
| 1969 ASSERT(!object->IsJSGlobalProxy()); |
| 1970 |
| 1971 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1972 if (object->IsJSObject()) { |
| 1973 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1974 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
| 1975 if (receiver->elements()->map() == |
| 1976 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1977 stub = non_strict_arguments_stub(); |
| 1978 } else if (key_is_smi_like && |
| 1979 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 1980 KeyedAccessStoreMode store_mode = |
| 1981 GetStoreMode(receiver, key, value); |
| 1982 stub = StoreElementStub(receiver, store_mode); |
| 1983 } |
| 1984 } |
| 1985 } |
| 1986 } |
1944 } | 1987 } |
1945 | 1988 |
1946 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1989 if (!is_target_set()) { |
1947 !(FLAG_harmony_observation && object->IsJSObject() && | 1990 if (*stub == *generic_stub()) { |
1948 JSObject::cast(*object)->map()->is_observed()); | 1991 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
1949 if (use_ic && !object->IsSmi()) { | |
1950 // Don't use ICs for maps of the objects in Array's prototype chain. We | |
1951 // expect to be able to trap element sets to objects with those maps in the | |
1952 // runtime to enable optimization of element hole access. | |
1953 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | |
1954 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | |
1955 } | |
1956 | |
1957 if (use_ic) { | |
1958 ASSERT(!object->IsJSGlobalProxy()); | |
1959 | |
1960 Handle<Code> stub = generic_stub(); | |
1961 if (miss_mode != MISS_FORCE_GENERIC) { | |
1962 if (object->IsJSObject()) { | |
1963 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
1964 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | |
1965 if (receiver->elements()->map() == | |
1966 isolate()->heap()->non_strict_arguments_elements_map()) { | |
1967 stub = non_strict_arguments_stub(); | |
1968 } else if (key_is_smi_like && | |
1969 (!target().is_identical_to(non_strict_arguments_stub()))) { | |
1970 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | |
1971 stub = StoreElementStub(receiver, store_mode); | |
1972 } else { | |
1973 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); | |
1974 } | |
1975 } else { | |
1976 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); | |
1977 } | |
1978 } else { | |
1979 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); | |
1980 } | 1992 } |
1981 ASSERT(!stub.is_null()); | 1993 ASSERT(!stub.is_null()); |
1982 set_target(*stub); | 1994 set_target(*stub); |
1983 TRACE_IC("StoreIC", key); | 1995 TRACE_IC("StoreIC", key); |
1984 } | 1996 } |
1985 | 1997 |
| 1998 if (maybe_object) return maybe_object; |
1986 return Runtime::SetObjectPropertyOrFail( | 1999 return Runtime::SetObjectPropertyOrFail( |
1987 isolate(), object , key, value, NONE, strict_mode()); | 2000 isolate(), object , key, value, NONE, strict_mode()); |
1988 } | 2001 } |
1989 | 2002 |
1990 | 2003 |
1991 #undef TRACE_IC | 2004 #undef TRACE_IC |
1992 | 2005 |
1993 | 2006 |
1994 // ---------------------------------------------------------------------------- | 2007 // ---------------------------------------------------------------------------- |
1995 // Static IC stub generators. | 2008 // Static IC stub generators. |
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2713 #undef ADDR | 2726 #undef ADDR |
2714 }; | 2727 }; |
2715 | 2728 |
2716 | 2729 |
2717 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2730 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2718 return IC_utilities[id]; | 2731 return IC_utilities[id]; |
2719 } | 2732 } |
2720 | 2733 |
2721 | 2734 |
2722 } } // namespace v8::internal | 2735 } } // namespace v8::internal |
OLD | NEW |