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

Side by Side Diff: src/ic.cc

Issue 32643004: Add a soft-deopt in keyed element access when current IC is pre-monomorphic and no type feedback wa… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/type-info.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 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/type-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698