| 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 |