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

Side by Side Diff: src/ic.cc

Issue 6850015: Remove support for inlined property loads and stores. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/x64/full-codegen-x64.cc » ('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 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 if (state == UNINITIALIZED) return; 297 if (state == UNINITIALIZED) return;
298 Code* code = 298 Code* code =
299 Isolate::Current()->stub_cache()->FindCallInitialize( 299 Isolate::Current()->stub_cache()->FindCallInitialize(
300 target->arguments_count(), 300 target->arguments_count(),
301 target->ic_in_loop(), 301 target->ic_in_loop(),
302 target->kind()); 302 target->kind());
303 SetTargetAtAddress(address, code); 303 SetTargetAtAddress(address, code);
304 } 304 }
305 305
306 306
307 void KeyedLoadIC::ClearInlinedVersion(Address address) {
308 // Insert null as the map to check for to make sure the map check fails
309 // sending control flow to the IC instead of the inlined version.
310 PatchInlinedLoad(address, HEAP->null_value());
311 }
312
313
314 void KeyedLoadIC::Clear(Address address, Code* target) { 307 void KeyedLoadIC::Clear(Address address, Code* target) {
315 if (target->ic_state() == UNINITIALIZED) return; 308 if (target->ic_state() == UNINITIALIZED) return;
316 // Make sure to also clear the map used in inline fast cases. If we 309 // Make sure to also clear the map used in inline fast cases. If we
317 // do not clear these maps, cached code can keep objects alive 310 // do not clear these maps, cached code can keep objects alive
318 // through the embedded maps. 311 // through the embedded maps.
319 ClearInlinedVersion(address);
320 SetTargetAtAddress(address, initialize_stub()); 312 SetTargetAtAddress(address, initialize_stub());
321 } 313 }
322 314
323 315
324 void LoadIC::ClearInlinedVersion(Address address) {
325 // Reset the map check of the inlined inobject property load (if
326 // present) to guarantee failure by holding an invalid map (the null
327 // value). The offset can be patched to anything.
328 Heap* heap = HEAP;
329 PatchInlinedLoad(address, heap->null_value(), 0);
330 PatchInlinedContextualLoad(address,
331 heap->null_value(),
332 heap->null_value(),
333 true);
334 }
335
336
337 void LoadIC::Clear(Address address, Code* target) { 316 void LoadIC::Clear(Address address, Code* target) {
338 if (target->ic_state() == UNINITIALIZED) return; 317 if (target->ic_state() == UNINITIALIZED) return;
339 ClearInlinedVersion(address);
340 SetTargetAtAddress(address, initialize_stub()); 318 SetTargetAtAddress(address, initialize_stub());
341 } 319 }
342 320
343 321
344 void StoreIC::ClearInlinedVersion(Address address) {
345 // Reset the map check of the inlined inobject property store (if
346 // present) to guarantee failure by holding an invalid map (the null
347 // value). The offset can be patched to anything.
348 PatchInlinedStore(address, HEAP->null_value(), 0);
349 }
350
351
352 void StoreIC::Clear(Address address, Code* target) { 322 void StoreIC::Clear(Address address, Code* target) {
353 if (target->ic_state() == UNINITIALIZED) return; 323 if (target->ic_state() == UNINITIALIZED) return;
354 ClearInlinedVersion(address);
355 SetTargetAtAddress(address, 324 SetTargetAtAddress(address,
356 (target->extra_ic_state() == kStrictMode) 325 (target->extra_ic_state() == kStrictMode)
357 ? initialize_stub_strict() 326 ? initialize_stub_strict()
358 : initialize_stub()); 327 : initialize_stub());
359 } 328 }
360 329
361 330
362 void KeyedStoreIC::ClearInlinedVersion(Address address) {
363 // Insert null as the elements map to check for. This will make
364 // sure that the elements fast-case map check fails so that control
365 // flows to the IC instead of the inlined version.
366 PatchInlinedStore(address, HEAP->null_value());
367 }
368
369
370 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
371 // Restore the fast-case elements map check so that the inlined
372 // version can be used again.
373 PatchInlinedStore(address, HEAP->fixed_array_map());
374 }
375
376
377 void KeyedStoreIC::Clear(Address address, Code* target) { 331 void KeyedStoreIC::Clear(Address address, Code* target) {
378 if (target->ic_state() == UNINITIALIZED) return; 332 if (target->ic_state() == UNINITIALIZED) return;
379 SetTargetAtAddress(address, 333 SetTargetAtAddress(address,
380 (target->extra_ic_state() == kStrictMode) 334 (target->extra_ic_state() == kStrictMode)
381 ? initialize_stub_strict() 335 ? initialize_stub_strict()
382 : initialize_stub()); 336 : initialize_stub());
383 } 337 }
384 338
385 339
386 static bool HasInterceptorGetter(JSObject* object) { 340 static bool HasInterceptorGetter(JSObject* object) {
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 // objects is read-only and therefore always returns the length of 820 // objects is read-only and therefore always returns the length of
867 // the underlying string value. See ECMA-262 15.5.5.1. 821 // the underlying string value. See ECMA-262 15.5.5.1.
868 if ((object->IsString() || object->IsStringWrapper()) && 822 if ((object->IsString() || object->IsStringWrapper()) &&
869 name->Equals(isolate()->heap()->length_symbol())) { 823 name->Equals(isolate()->heap()->length_symbol())) {
870 HandleScope scope(isolate()); 824 HandleScope scope(isolate());
871 #ifdef DEBUG 825 #ifdef DEBUG
872 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); 826 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
873 #endif 827 #endif
874 if (state == PREMONOMORPHIC) { 828 if (state == PREMONOMORPHIC) {
875 if (object->IsString()) { 829 if (object->IsString()) {
876 Map* map = HeapObject::cast(*object)->map();
877 const int offset = String::kLengthOffset;
878 PatchInlinedLoad(address(), map, offset);
879 set_target(isolate()->builtins()->builtin( 830 set_target(isolate()->builtins()->builtin(
880 Builtins::kLoadIC_StringLength)); 831 Builtins::kLoadIC_StringLength));
881 } else { 832 } else {
882 set_target(isolate()->builtins()->builtin( 833 set_target(isolate()->builtins()->builtin(
883 Builtins::kLoadIC_StringWrapperLength)); 834 Builtins::kLoadIC_StringWrapperLength));
884 } 835 }
885 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { 836 } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
886 set_target(isolate()->builtins()->builtin( 837 set_target(isolate()->builtins()->builtin(
887 Builtins::kLoadIC_StringWrapperLength)); 838 Builtins::kLoadIC_StringWrapperLength));
888 } else { 839 } else {
889 set_target(non_monomorphic_stub); 840 set_target(non_monomorphic_stub);
890 } 841 }
891 // Get the string if we have a string wrapper object. 842 // Get the string if we have a string wrapper object.
892 if (object->IsJSValue()) { 843 if (object->IsJSValue()) {
893 object = Handle<Object>(Handle<JSValue>::cast(object)->value(), 844 object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
894 isolate()); 845 isolate());
895 } 846 }
896 return Smi::FromInt(String::cast(*object)->length()); 847 return Smi::FromInt(String::cast(*object)->length());
897 } 848 }
898 849
899 // Use specialized code for getting the length of arrays. 850 // Use specialized code for getting the length of arrays.
900 if (object->IsJSArray() && 851 if (object->IsJSArray() &&
901 name->Equals(isolate()->heap()->length_symbol())) { 852 name->Equals(isolate()->heap()->length_symbol())) {
902 #ifdef DEBUG 853 #ifdef DEBUG
903 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); 854 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
904 #endif 855 #endif
905 if (state == PREMONOMORPHIC) { 856 if (state == PREMONOMORPHIC) {
906 Map* map = HeapObject::cast(*object)->map();
907 const int offset = JSArray::kLengthOffset;
908 PatchInlinedLoad(address(), map, offset);
909 set_target(isolate()->builtins()->builtin( 857 set_target(isolate()->builtins()->builtin(
910 Builtins::kLoadIC_ArrayLength)); 858 Builtins::kLoadIC_ArrayLength));
911 } else { 859 } else {
912 set_target(non_monomorphic_stub); 860 set_target(non_monomorphic_stub);
913 } 861 }
914 return JSArray::cast(*object)->length(); 862 return JSArray::cast(*object)->length();
915 } 863 }
916 864
917 // Use specialized code for getting prototype of functions. 865 // Use specialized code for getting prototype of functions.
918 if (object->IsJSFunction() && 866 if (object->IsJSFunction() &&
(...skipping 22 matching lines...) Expand all
941 LookupForRead(*object, *name, &lookup); 889 LookupForRead(*object, *name, &lookup);
942 890
943 // If we did not find a property, check if we need to throw an exception. 891 // If we did not find a property, check if we need to throw an exception.
944 if (!lookup.IsProperty()) { 892 if (!lookup.IsProperty()) {
945 if (FLAG_strict || IsContextual(object)) { 893 if (FLAG_strict || IsContextual(object)) {
946 return ReferenceError("not_defined", name); 894 return ReferenceError("not_defined", name);
947 } 895 }
948 LOG(isolate(), SuspectReadEvent(*name, *object)); 896 LOG(isolate(), SuspectReadEvent(*name, *object));
949 } 897 }
950 898
951 bool can_be_inlined_precheck =
952 FLAG_use_ic &&
953 lookup.IsProperty() &&
954 lookup.IsCacheable() &&
955 lookup.holder() == *object &&
956 !object->IsAccessCheckNeeded();
957
958 bool can_be_inlined =
959 can_be_inlined_precheck &&
960 state == PREMONOMORPHIC &&
961 lookup.type() == FIELD;
962
963 bool can_be_inlined_contextual =
964 can_be_inlined_precheck &&
965 state == UNINITIALIZED &&
966 lookup.holder()->IsGlobalObject() &&
967 lookup.type() == NORMAL;
968
969 if (can_be_inlined) {
970 Map* map = lookup.holder()->map();
971 // Property's index in the properties array. If negative we have
972 // an inobject property.
973 int index = lookup.GetFieldIndex() - map->inobject_properties();
974 if (index < 0) {
975 // Index is an offset from the end of the object.
976 int offset = map->instance_size() + (index * kPointerSize);
977 if (PatchInlinedLoad(address(), map, offset)) {
978 set_target(megamorphic_stub());
979 TRACE_IC_NAMED("[LoadIC : inline patch %s]\n", name);
980 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
981 } else {
982 TRACE_IC_NAMED("[LoadIC : no inline patch %s (patching failed)]\n",
983 name);
984 }
985 } else {
986 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inobject)]\n", name);
987 }
988 } else if (can_be_inlined_contextual) {
989 Map* map = lookup.holder()->map();
990 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
991 lookup.holder()->property_dictionary()->ValueAt(
992 lookup.GetDictionaryEntry()));
993 if (PatchInlinedContextualLoad(address(),
994 map,
995 cell,
996 lookup.IsDontDelete())) {
997 set_target(megamorphic_stub());
998 TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
999 ASSERT(cell->value() != isolate()->heap()->the_hole_value());
1000 return cell->value();
1001 }
1002 } else {
1003 if (FLAG_use_ic && state == PREMONOMORPHIC) {
1004 TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name);
1005 }
1006 }
1007
1008 // Update inline cache and stub cache. 899 // Update inline cache and stub cache.
1009 if (FLAG_use_ic) { 900 if (FLAG_use_ic) {
1010 UpdateCaches(&lookup, state, object, name); 901 UpdateCaches(&lookup, state, object, name);
1011 } 902 }
1012 903
1013 PropertyAttributes attr; 904 PropertyAttributes attr;
1014 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 905 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
1015 // Get the property. 906 // Get the property.
1016 Object* result; 907 Object* result;
1017 { MaybeObject* maybe_result = 908 { MaybeObject* maybe_result =
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 stub = probe->IsFailure() ? 1178 stub = probe->IsFailure() ?
1288 NULL : Code::cast(probe->ToObjectUnchecked()); 1179 NULL : Code::cast(probe->ToObjectUnchecked());
1289 } 1180 }
1290 } 1181 }
1291 } 1182 }
1292 if (stub != NULL) set_target(stub); 1183 if (stub != NULL) set_target(stub);
1293 1184
1294 #ifdef DEBUG 1185 #ifdef DEBUG
1295 TraceIC("KeyedLoadIC", key, state, target()); 1186 TraceIC("KeyedLoadIC", key, state, target());
1296 #endif // DEBUG 1187 #endif // DEBUG
1297
1298 // For JSObjects with fast elements that are not value wrappers
1299 // and that do not have indexed interceptors, we initialize the
1300 // inlined fast case (if present) by patching the inlined map
1301 // check.
1302 if (object->IsJSObject() &&
1303 !object->IsJSValue() &&
1304 !JSObject::cast(*object)->HasIndexedInterceptor() &&
1305 JSObject::cast(*object)->HasFastElements()) {
1306 Map* map = JSObject::cast(*object)->map();
1307 PatchInlinedLoad(address(), map);
1308 }
1309 } 1188 }
1310 1189
1311 // Get the property. 1190 // Get the property.
1312 return Runtime::GetObjectProperty(isolate(), object, key); 1191 return Runtime::GetObjectProperty(isolate(), object, key);
1313 } 1192 }
1314 1193
1315 1194
1316 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1195 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1317 Handle<Object> object, Handle<String> name) { 1196 Handle<Object> object, Handle<String> name) {
1318 // Bail out if we didn't find a result. 1197 // Bail out if we didn't find a result.
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1464 : Builtins::kStoreIC_ArrayLength; 1343 : Builtins::kStoreIC_ArrayLength;
1465 set_target(isolate()->builtins()->builtin(target)); 1344 set_target(isolate()->builtins()->builtin(target));
1466 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1345 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1467 } 1346 }
1468 1347
1469 // Lookup the property locally in the receiver. 1348 // Lookup the property locally in the receiver.
1470 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 1349 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1471 LookupResult lookup; 1350 LookupResult lookup;
1472 1351
1473 if (LookupForWrite(*receiver, *name, &lookup)) { 1352 if (LookupForWrite(*receiver, *name, &lookup)) {
1474 bool can_be_inlined = 1353 // Generate a stub for this store.
1475 state == UNINITIALIZED &&
1476 lookup.IsProperty() &&
1477 lookup.holder() == *receiver &&
1478 lookup.type() == FIELD &&
1479 !receiver->IsAccessCheckNeeded();
1480
1481 if (can_be_inlined) {
1482 Map* map = lookup.holder()->map();
1483 // Property's index in the properties array. If negative we have
1484 // an inobject property.
1485 int index = lookup.GetFieldIndex() - map->inobject_properties();
1486 if (index < 0) {
1487 // Index is an offset from the end of the object.
1488 int offset = map->instance_size() + (index * kPointerSize);
1489 if (PatchInlinedStore(address(), map, offset)) {
1490 set_target((strict_mode == kStrictMode)
1491 ? megamorphic_stub_strict()
1492 : megamorphic_stub());
1493 #ifdef DEBUG
1494 if (FLAG_trace_ic) {
1495 PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
1496 }
1497 #endif
1498 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1499 #ifdef DEBUG
1500
1501 } else {
1502 if (FLAG_trace_ic) {
1503 PrintF("[StoreIC : no inline patch %s (patching failed)]\n",
1504 *name->ToCString());
1505 }
1506 }
1507 } else {
1508 if (FLAG_trace_ic) {
1509 PrintF("[StoreIC : no inline patch %s (not inobject)]\n",
1510 *name->ToCString());
1511 }
1512 }
1513 } else {
1514 if (state == PREMONOMORPHIC) {
1515 if (FLAG_trace_ic) {
1516 PrintF("[StoreIC : no inline patch %s (not inlinable)]\n",
1517 *name->ToCString());
1518 #endif
1519 }
1520 }
1521 }
1522
1523 // If no inlined store ic was patched, generate a stub for this
1524 // store.
1525 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); 1354 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1526 } else { 1355 } else {
1527 // Strict mode doesn't allow setting non-existent global property 1356 // Strict mode doesn't allow setting non-existent global property
1528 // or an assignment to a read only property. 1357 // or an assignment to a read only property.
1529 if (strict_mode == kStrictMode) { 1358 if (strict_mode == kStrictMode) {
1530 if (lookup.IsFound() && lookup.IsReadOnly()) { 1359 if (lookup.IsFound() && lookup.IsReadOnly()) {
1531 return TypeError("strict_read_only_property", object, name); 1360 return TypeError("strict_read_only_property", object, name);
1532 } else if (IsContextual(object)) { 1361 } else if (IsContextual(object)) {
1533 return ReferenceError("not_defined", name); 1362 return ReferenceError("not_defined", name);
1534 } 1363 }
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
2238 #undef ADDR 2067 #undef ADDR
2239 }; 2068 };
2240 2069
2241 2070
2242 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2071 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2243 return IC_utilities[id]; 2072 return IC_utilities[id];
2244 } 2073 }
2245 2074
2246 2075
2247 } } // namespace v8::internal 2076 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698