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

Side by Side Diff: src/ic/ic.cc

Issue 2405213002: V8 support for cached accessors. (Closed)
Patch Set: Toon's feedback. Created 4 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
« no previous file with comments | « src/ic/ic.h ('k') | src/lookup.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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ic/ic.h" 5 #include "src/ic/ic.h"
6 6
7 #include <iostream> 7 #include <iostream>
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/api-arguments-inl.h" 10 #include "src/api-arguments-inl.h"
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 break; 1168 break;
1169 } 1169 }
1170 } else { 1170 } else {
1171 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit); 1171 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1172 } 1172 }
1173 } 1173 }
1174 1174
1175 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, 1175 Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
1176 Handle<Object> value) { 1176 Handle<Object> value) {
1177 // Try to find a globally shared handler stub. 1177 // Try to find a globally shared handler stub.
1178 Handle<Object> handler = GetMapIndependentHandler(lookup); 1178 Handle<Object> shared_handler = GetMapIndependentHandler(lookup);
1179 if (!handler.is_null()) { 1179 if (!shared_handler.is_null()) {
1180 DCHECK(IC::IsHandler(*handler)); 1180 DCHECK(IC::IsHandler(*shared_handler));
1181 return handler; 1181 return shared_handler;
1182 } 1182 }
1183 1183
1184 // Otherwise check the map's handler cache for a map-specific handler, and 1184 // Otherwise check the map's handler cache for a map-specific handler, and
1185 // compile one if the cache comes up empty. 1185 // compile one if the cache comes up empty.
1186 bool receiver_is_holder = 1186 bool receiver_is_holder =
1187 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); 1187 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
1188 CacheHolderFlag flag; 1188 CacheHolderFlag flag;
1189 Handle<Map> stub_holder_map; 1189 Handle<Map> stub_holder_map;
1190 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC || 1190 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC ||
1191 kind() == Code::KEYED_LOAD_IC) { 1191 kind() == Code::KEYED_LOAD_IC) {
1192 stub_holder_map = IC::GetHandlerCacheHolder( 1192 stub_holder_map = IC::GetHandlerCacheHolder(
1193 receiver_map(), receiver_is_holder, isolate(), &flag); 1193 receiver_map(), receiver_is_holder, isolate(), &flag);
1194 } else { 1194 } else {
1195 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); 1195 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
1196 // Store handlers cannot be cached on prototypes. 1196 // Store handlers cannot be cached on prototypes.
1197 flag = kCacheOnReceiver; 1197 flag = kCacheOnReceiver;
1198 stub_holder_map = receiver_map(); 1198 stub_holder_map = receiver_map();
1199 } 1199 }
1200 1200
1201 Handle<Code> code = PropertyHandlerCompiler::Find( 1201 Handle<Object> handler = PropertyHandlerCompiler::Find(
1202 lookup->name(), stub_holder_map, kind(), flag); 1202 lookup->name(), stub_holder_map, kind(), flag);
1203 // Use the cached value if it exists, and if it is different from the 1203 // Use the cached value if it exists, and if it is different from the
1204 // handler that just missed. 1204 // handler that just missed.
1205 if (!code.is_null()) { 1205 if (!handler.is_null()) {
1206 Handle<Object> handler; 1206 Handle<Object> current_handler;
1207 if (maybe_handler_.ToHandle(&handler)) { 1207 if (maybe_handler_.ToHandle(&current_handler)) {
1208 if (!handler.is_identical_to(code)) { 1208 if (!current_handler.is_identical_to(handler)) {
1209 TraceHandlerCacheHitStats(lookup); 1209 TraceHandlerCacheHitStats(lookup);
1210 return code; 1210 return handler;
1211 } 1211 }
1212 } else { 1212 } else {
1213 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs. 1213 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
1214 // In MEGAMORPHIC case, check if the handler in the megamorphic stub 1214 // In MEGAMORPHIC case, check if the handler in the megamorphic stub
1215 // cache (which just missed) is different from the cached handler. 1215 // cache (which just missed) is different from the cached handler.
1216 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) { 1216 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
1217 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map(); 1217 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
1218 Object* megamorphic_cached_handler = 1218 Object* megamorphic_cached_handler =
1219 stub_cache()->Get(*lookup->name(), map); 1219 stub_cache()->Get(*lookup->name(), map);
1220 if (megamorphic_cached_handler != *code) { 1220 if (megamorphic_cached_handler != *handler) {
1221 TraceHandlerCacheHitStats(lookup); 1221 TraceHandlerCacheHitStats(lookup);
1222 return code; 1222 return handler;
1223 } 1223 }
1224 } else { 1224 } else {
1225 TraceHandlerCacheHitStats(lookup); 1225 TraceHandlerCacheHitStats(lookup);
1226 return code; 1226 return handler;
1227 } 1227 }
1228 } 1228 }
1229 } 1229 }
1230 1230
1231 code = CompileHandler(lookup, value, flag); 1231 handler = CompileHandler(lookup, value, flag);
1232 DCHECK(code->is_handler()); 1232 DCHECK(IC::IsHandler(*handler));
1233 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag); 1233 if (handler->IsCode()) {
1234 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); 1234 Handle<Code> code = Handle<Code>::cast(handler);
1235 1235 DCHECK_EQ(Code::ExtractCacheHolderFromFlags(code->flags()), flag);
1236 return code; 1236 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
1237 }
1238 return handler;
1237 } 1239 }
1238 1240
1239 Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) { 1241 Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
1240 Handle<Object> receiver = lookup->GetReceiver(); 1242 Handle<Object> receiver = lookup->GetReceiver();
1241 if (receiver->IsString() && 1243 if (receiver->IsString() &&
1242 Name::Equals(isolate()->factory()->length_string(), lookup->name())) { 1244 Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
1243 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset); 1245 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
1244 return SimpleFieldLoad(index); 1246 return SimpleFieldLoad(index);
1245 } 1247 }
1246 1248
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 case LookupIterator::ACCESS_CHECK: 1389 case LookupIterator::ACCESS_CHECK:
1388 case LookupIterator::JSPROXY: 1390 case LookupIterator::JSPROXY:
1389 case LookupIterator::NOT_FOUND: 1391 case LookupIterator::NOT_FOUND:
1390 case LookupIterator::TRANSITION: 1392 case LookupIterator::TRANSITION:
1391 UNREACHABLE(); 1393 UNREACHABLE();
1392 } 1394 }
1393 1395
1394 return Handle<Code>::null(); 1396 return Handle<Code>::null();
1395 } 1397 }
1396 1398
1397 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, 1399 Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
1398 Handle<Object> unused, 1400 Handle<Object> unused,
1399 CacheHolderFlag cache_holder) { 1401 CacheHolderFlag cache_holder) {
1400 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); 1402 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1401 #ifdef DEBUG 1403 #ifdef DEBUG
1402 // Only used by DCHECKs below. 1404 // Only used by DCHECKs below.
1403 Handle<Object> receiver = lookup->GetReceiver(); 1405 Handle<Object> receiver = lookup->GetReceiver();
1404 bool receiver_is_holder = receiver.is_identical_to(holder); 1406 bool receiver_is_holder = receiver.is_identical_to(holder);
1405 #endif 1407 #endif
1406 // Non-map-specific handler stubs have already been selected. 1408 // Non-map-specific handler stubs have already been selected.
1407 DCHECK(!receiver->IsString() || 1409 DCHECK(!receiver->IsString() ||
1408 !Name::Equals(isolate()->factory()->length_string(), lookup->name())); 1410 !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
1409 DCHECK(!receiver->IsStringWrapper() || 1411 DCHECK(!receiver->IsStringWrapper() ||
(...skipping 24 matching lines...) Expand all
1434 case LookupIterator::ACCESSOR: { 1436 case LookupIterator::ACCESSOR: {
1435 #ifdef DEBUG 1437 #ifdef DEBUG
1436 int object_offset; 1438 int object_offset;
1437 DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(), 1439 DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
1438 &object_offset)); 1440 &object_offset));
1439 #endif 1441 #endif
1440 1442
1441 DCHECK(IsCompatibleReceiver(lookup, map)); 1443 DCHECK(IsCompatibleReceiver(lookup, map));
1442 Handle<Object> accessors = lookup->GetAccessors(); 1444 Handle<Object> accessors = lookup->GetAccessors();
1443 if (accessors->IsAccessorPair()) { 1445 if (accessors->IsAccessorPair()) {
1446 if (lookup->TryLookupCachedProperty()) {
1447 DCHECK_EQ(LookupIterator::DATA, lookup->state());
1448 return ComputeHandler(lookup);
1449 }
1444 DCHECK(holder->HasFastProperties()); 1450 DCHECK(holder->HasFastProperties());
1445 DCHECK(!GetSharedFunctionInfo()->HasDebugInfo()); 1451 DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
1446 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), 1452 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
1447 isolate()); 1453 isolate());
1448 CallOptimization call_optimization(getter); 1454 CallOptimization call_optimization(getter);
1449 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); 1455 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1450 if (call_optimization.is_simple_api_call()) { 1456 if (call_optimization.is_simple_api_call()) {
1451 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback); 1457 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
1452 int index = lookup->GetAccessorIndex(); 1458 int index = lookup->GetAccessorIndex();
1453 Handle<Code> code = compiler.CompileLoadCallback( 1459 Handle<Code> code = compiler.CompileLoadCallback(
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
1956 1962
1957 case LookupIterator::INTEGER_INDEXED_EXOTIC: 1963 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1958 case LookupIterator::ACCESS_CHECK: 1964 case LookupIterator::ACCESS_CHECK:
1959 case LookupIterator::JSPROXY: 1965 case LookupIterator::JSPROXY:
1960 case LookupIterator::NOT_FOUND: 1966 case LookupIterator::NOT_FOUND:
1961 UNREACHABLE(); 1967 UNREACHABLE();
1962 } 1968 }
1963 return Handle<Code>::null(); 1969 return Handle<Code>::null();
1964 } 1970 }
1965 1971
1966 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, 1972 Handle<Object> StoreIC::CompileHandler(LookupIterator* lookup,
1967 Handle<Object> value, 1973 Handle<Object> value,
1968 CacheHolderFlag cache_holder) { 1974 CacheHolderFlag cache_holder) {
1969 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); 1975 DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1970 1976
1971 // This is currently guaranteed by checks in StoreIC::Store. 1977 // This is currently guaranteed by checks in StoreIC::Store.
1972 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); 1978 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1973 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); 1979 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1974 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); 1980 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1975 1981
1976 switch (lookup->state()) { 1982 switch (lookup->state()) {
1977 case LookupIterator::TRANSITION: { 1983 case LookupIterator::TRANSITION: {
1978 auto store_target = lookup->GetStoreTarget(); 1984 auto store_target = lookup->GetStoreTarget();
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after
3134 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); 3140 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3135 it.Next(); 3141 it.Next();
3136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, 3142 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3137 Object::GetProperty(&it)); 3143 Object::GetProperty(&it));
3138 } 3144 }
3139 3145
3140 return *result; 3146 return *result;
3141 } 3147 }
3142 } // namespace internal 3148 } // namespace internal
3143 } // namespace v8 3149 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/lookup.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698