OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 CSA_ASSERT(this, IsDictionaryMap(LoadMap(object))); | 1091 CSA_ASSERT(this, IsDictionaryMap(LoadMap(object))); |
1092 Node* properties = LoadProperties(object); | 1092 Node* properties = LoadProperties(object); |
1093 // Ensure the property does not exist in a dictionary-mode object. | 1093 // Ensure the property does not exist in a dictionary-mode object. |
1094 Variable var_name_index(this, MachineType::PointerRepresentation()); | 1094 Variable var_name_index(this, MachineType::PointerRepresentation()); |
1095 Label done(this); | 1095 Label done(this); |
1096 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 1096 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
1097 &done); | 1097 &done); |
1098 Bind(&done); | 1098 Bind(&done); |
1099 } | 1099 } |
1100 | 1100 |
| 1101 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, |
| 1102 Node* instance_type, Node* index, |
| 1103 Label* slow) { |
| 1104 Comment("integer index"); |
| 1105 Label if_element_hole(this), if_oob(this); |
| 1106 // Receivers requiring non-standard element accesses (interceptors, access |
| 1107 // checks, strings and string wrappers, proxies) are handled in the runtime. |
| 1108 GotoIf(Int32LessThanOrEqual(instance_type, |
| 1109 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
| 1110 slow); |
| 1111 Node* elements = LoadElements(receiver); |
| 1112 Node* elements_kind = LoadMapElementsKind(receiver_map); |
| 1113 Node* is_jsarray_condition = |
| 1114 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
| 1115 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 1116 Label rebox_double(this, &var_double_value); |
| 1117 |
| 1118 // Unimplemented elements kinds fall back to a runtime call. |
| 1119 Label* unimplemented_elements_kind = slow; |
| 1120 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); |
| 1121 EmitElementLoad(receiver, elements, elements_kind, index, |
| 1122 is_jsarray_condition, &if_element_hole, &rebox_double, |
| 1123 &var_double_value, unimplemented_elements_kind, &if_oob, |
| 1124 slow); |
| 1125 |
| 1126 Bind(&rebox_double); |
| 1127 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
| 1128 |
| 1129 Bind(&if_oob); |
| 1130 { |
| 1131 Comment("out of bounds"); |
| 1132 // Negative keys can't take the fast OOB path. |
| 1133 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); |
| 1134 // Positive OOB indices are effectively the same as hole loads. |
| 1135 Goto(&if_element_hole); |
| 1136 } |
| 1137 |
| 1138 Bind(&if_element_hole); |
| 1139 { |
| 1140 Comment("found the hole"); |
| 1141 Label return_undefined(this); |
| 1142 BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, slow); |
| 1143 |
| 1144 Bind(&return_undefined); |
| 1145 Return(UndefinedConstant()); |
| 1146 } |
| 1147 } |
| 1148 |
| 1149 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, |
| 1150 Node* instance_type, Node* key, |
| 1151 const LoadICParameters* p, |
| 1152 Label* slow) { |
| 1153 Comment("key is unique name"); |
| 1154 Label if_found_on_receiver(this), if_property_dictionary(this), |
| 1155 lookup_prototype_chain(this); |
| 1156 Variable var_details(this, MachineRepresentation::kWord32); |
| 1157 Variable var_value(this, MachineRepresentation::kTagged); |
| 1158 |
| 1159 // Receivers requiring non-standard accesses (interceptors, access |
| 1160 // checks, string wrappers, proxies) are handled in the runtime. |
| 1161 // We special-case strings here, to support loading <Symbol.split> etc. |
| 1162 Variable var_receiver(this, MachineRepresentation::kTagged); |
| 1163 Variable var_receiver_map(this, MachineRepresentation::kTagged); |
| 1164 Variable var_instance_type(this, MachineRepresentation::kWord32); |
| 1165 var_receiver.Bind(receiver); |
| 1166 var_receiver_map.Bind(receiver_map); |
| 1167 var_instance_type.Bind(instance_type); |
| 1168 Label normal_receiver(this); |
| 1169 GotoIf(Int32GreaterThan(instance_type, |
| 1170 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
| 1171 &normal_receiver); |
| 1172 GotoIf(Int32GreaterThanOrEqual(instance_type, |
| 1173 Int32Constant(FIRST_NONSTRING_TYPE)), |
| 1174 slow); |
| 1175 CSA_ASSERT(this, WordEqual(LoadMapConstructorFunctionIndex(receiver_map), |
| 1176 IntPtrConstant(Context::STRING_FUNCTION_INDEX))); |
| 1177 Node* native_context = LoadNativeContext(p->context); |
| 1178 Node* constructor_function = |
| 1179 LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX); |
| 1180 Node* initial_map = LoadObjectField(constructor_function, |
| 1181 JSFunction::kPrototypeOrInitialMapOffset); |
| 1182 var_receiver.Bind(LoadMapPrototype(initial_map)); |
| 1183 var_receiver_map.Bind(LoadMap(var_receiver.value())); |
| 1184 var_instance_type.Bind(LoadMapInstanceType(var_receiver_map.value())); |
| 1185 Goto(&normal_receiver); |
| 1186 |
| 1187 Bind(&normal_receiver); |
| 1188 receiver = var_receiver.value(); |
| 1189 receiver_map = var_receiver_map.value(); |
| 1190 instance_type = var_instance_type.value(); |
| 1191 // Check if the receiver has fast or slow properties. |
| 1192 Node* properties = LoadProperties(receiver); |
| 1193 Node* properties_map = LoadMap(properties); |
| 1194 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), |
| 1195 &if_property_dictionary); |
| 1196 |
| 1197 // Try looking up the property on the receiver; if unsuccessful, look |
| 1198 // for a handler in the stub cache. |
| 1199 Comment("DescriptorArray lookup"); |
| 1200 |
| 1201 // Skip linear search if there are too many descriptors. |
| 1202 // TODO(jkummerow): Consider implementing binary search. |
| 1203 // See also TryLookupProperty() which has the same limitation. |
| 1204 const int32_t kMaxLinear = 210; |
| 1205 Label stub_cache(this); |
| 1206 Node* bitfield3 = LoadMapBitField3(var_receiver_map.value()); |
| 1207 Node* nof = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); |
| 1208 GotoIf(UintPtrLessThan(IntPtrConstant(kMaxLinear), nof), &stub_cache); |
| 1209 Node* descriptors = LoadMapDescriptors(var_receiver_map.value()); |
| 1210 Variable var_name_index(this, MachineType::PointerRepresentation()); |
| 1211 Label if_descriptor_found(this); |
| 1212 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, |
| 1213 &var_name_index, &stub_cache); |
| 1214 |
| 1215 Bind(&if_descriptor_found); |
| 1216 { |
| 1217 LoadPropertyFromFastObject(receiver, var_receiver_map.value(), descriptors, |
| 1218 var_name_index.value(), &var_details, |
| 1219 &var_value); |
| 1220 Goto(&if_found_on_receiver); |
| 1221 } |
| 1222 |
| 1223 Bind(&stub_cache); |
| 1224 { |
| 1225 Comment("stub cache probe for fast property load"); |
| 1226 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1227 Label found_handler(this, &var_handler), stub_cache_miss(this); |
| 1228 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, |
| 1229 &found_handler, &var_handler, &stub_cache_miss); |
| 1230 Bind(&found_handler); |
| 1231 { HandleLoadICHandlerCase(p, var_handler.value(), slow); } |
| 1232 |
| 1233 Bind(&stub_cache_miss); |
| 1234 { |
| 1235 // TODO(jkummerow): Check if the property exists on the prototype |
| 1236 // chain. If it doesn't, then there's no point in missing. |
| 1237 Comment("KeyedLoadGeneric_miss"); |
| 1238 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
| 1239 p->name, p->slot, p->vector); |
| 1240 } |
| 1241 } |
| 1242 |
| 1243 Bind(&if_property_dictionary); |
| 1244 { |
| 1245 Comment("dictionary property load"); |
| 1246 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out |
| 1247 // seeing global objects here (which would need special handling). |
| 1248 |
| 1249 Variable var_name_index(this, MachineType::PointerRepresentation()); |
| 1250 Label dictionary_found(this, &var_name_index); |
| 1251 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found, |
| 1252 &var_name_index, |
| 1253 &lookup_prototype_chain); |
| 1254 Bind(&dictionary_found); |
| 1255 { |
| 1256 LoadPropertyFromNameDictionary(properties, var_name_index.value(), |
| 1257 &var_details, &var_value); |
| 1258 Goto(&if_found_on_receiver); |
| 1259 } |
| 1260 } |
| 1261 |
| 1262 Bind(&if_found_on_receiver); |
| 1263 { |
| 1264 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(), |
| 1265 p->context, var_receiver.value(), slow); |
| 1266 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); |
| 1267 Return(value); |
| 1268 } |
| 1269 |
| 1270 Bind(&lookup_prototype_chain); |
| 1271 { |
| 1272 Variable var_holder_map(this, MachineRepresentation::kTagged); |
| 1273 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); |
| 1274 Label return_undefined(this); |
| 1275 Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; |
| 1276 Label loop(this, arraysize(merged_variables), merged_variables); |
| 1277 |
| 1278 var_holder_map.Bind(var_receiver_map.value()); |
| 1279 var_holder_instance_type.Bind(var_instance_type.value()); |
| 1280 // Private symbols must not be looked up on the prototype chain. |
| 1281 GotoIf(IsPrivateSymbol(key), &return_undefined); |
| 1282 Goto(&loop); |
| 1283 Bind(&loop); |
| 1284 { |
| 1285 // Bailout if it can be an integer indexed exotic case. |
| 1286 GotoIf(Word32Equal(var_holder_instance_type.value(), |
| 1287 Int32Constant(JS_TYPED_ARRAY_TYPE)), |
| 1288 slow); |
| 1289 Node* proto = LoadMapPrototype(var_holder_map.value()); |
| 1290 GotoIf(WordEqual(proto, NullConstant()), &return_undefined); |
| 1291 Node* proto_map = LoadMap(proto); |
| 1292 Node* proto_instance_type = LoadMapInstanceType(proto_map); |
| 1293 var_holder_map.Bind(proto_map); |
| 1294 var_holder_instance_type.Bind(proto_instance_type); |
| 1295 Label next_proto(this), return_value(this, &var_value), goto_slow(this); |
| 1296 TryGetOwnProperty(p->context, var_receiver.value(), proto, proto_map, |
| 1297 proto_instance_type, key, &return_value, &var_value, |
| 1298 &next_proto, &goto_slow); |
| 1299 |
| 1300 // This trampoline and the next are required to appease Turbofan's |
| 1301 // variable merging. |
| 1302 Bind(&next_proto); |
| 1303 Goto(&loop); |
| 1304 |
| 1305 Bind(&goto_slow); |
| 1306 Goto(slow); |
| 1307 |
| 1308 Bind(&return_value); |
| 1309 Return(var_value.value()); |
| 1310 } |
| 1311 |
| 1312 Bind(&return_undefined); |
| 1313 Return(UndefinedConstant()); |
| 1314 } |
| 1315 } |
| 1316 |
1101 //////////////////// Stub cache access helpers. | 1317 //////////////////// Stub cache access helpers. |
1102 | 1318 |
1103 enum AccessorAssembler::StubCacheTable : int { | 1319 enum AccessorAssembler::StubCacheTable : int { |
1104 kPrimary = static_cast<int>(StubCache::kPrimary), | 1320 kPrimary = static_cast<int>(StubCache::kPrimary), |
1105 kSecondary = static_cast<int>(StubCache::kSecondary) | 1321 kSecondary = static_cast<int>(StubCache::kSecondary) |
1106 }; | 1322 }; |
1107 | 1323 |
1108 Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) { | 1324 Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) { |
1109 // See v8::internal::StubCache::PrimaryOffset(). | 1325 // See v8::internal::StubCache::PrimaryOffset(). |
1110 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); | 1326 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 Comment("KeyedLoadIC_miss"); | 1608 Comment("KeyedLoadIC_miss"); |
1393 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1609 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
1394 p->name, p->slot, p->vector); | 1610 p->name, p->slot, p->vector); |
1395 } | 1611 } |
1396 } | 1612 } |
1397 | 1613 |
1398 void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { | 1614 void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
1399 Variable var_index(this, MachineType::PointerRepresentation()); | 1615 Variable var_index(this, MachineType::PointerRepresentation()); |
1400 Variable var_unique(this, MachineRepresentation::kTagged); | 1616 Variable var_unique(this, MachineRepresentation::kTagged); |
1401 var_unique.Bind(p->name); // Dummy initialization. | 1617 var_unique.Bind(p->name); // Dummy initialization. |
1402 Variable var_details(this, MachineRepresentation::kWord32); | 1618 Label if_index(this), if_unique_name(this), slow(this); |
1403 Variable var_value(this, MachineRepresentation::kTagged); | |
1404 Label if_index(this), if_unique_name(this), if_element_hole(this), | |
1405 if_oob(this), slow(this), stub_cache_miss(this), | |
1406 if_property_dictionary(this), if_found_on_receiver(this), | |
1407 lookup_prototype_chain(this); | |
1408 | 1619 |
1409 Node* receiver = p->receiver; | 1620 Node* receiver = p->receiver; |
1410 GotoIf(TaggedIsSmi(receiver), &slow); | 1621 GotoIf(TaggedIsSmi(receiver), &slow); |
1411 Node* receiver_map = LoadMap(receiver); | 1622 Node* receiver_map = LoadMap(receiver); |
1412 Node* instance_type = LoadMapInstanceType(receiver_map); | 1623 Node* instance_type = LoadMapInstanceType(receiver_map); |
1413 // Receivers requiring non-standard element accesses (interceptors, access | |
1414 // checks, strings and string wrappers, proxies) are handled in the runtime. | |
1415 GotoIf(Int32LessThanOrEqual(instance_type, | |
1416 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | |
1417 &slow); | |
1418 | 1624 |
1419 TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, | 1625 TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, |
1420 &slow); | 1626 &slow); |
1421 | 1627 |
1422 Bind(&if_index); | 1628 Bind(&if_index); |
1423 { | 1629 { |
1424 Comment("integer index"); | 1630 GenericElementLoad(receiver, receiver_map, instance_type, var_index.value(), |
1425 Node* index = var_index.value(); | 1631 &slow); |
1426 Node* elements = LoadElements(receiver); | |
1427 Node* elements_kind = LoadMapElementsKind(receiver_map); | |
1428 Node* is_jsarray_condition = | |
1429 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | |
1430 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
1431 Label rebox_double(this, &var_double_value); | |
1432 | |
1433 // Unimplemented elements kinds fall back to a runtime call. | |
1434 Label* unimplemented_elements_kind = &slow; | |
1435 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); | |
1436 EmitElementLoad(receiver, elements, elements_kind, index, | |
1437 is_jsarray_condition, &if_element_hole, &rebox_double, | |
1438 &var_double_value, unimplemented_elements_kind, &if_oob, | |
1439 &slow); | |
1440 | |
1441 Bind(&rebox_double); | |
1442 Return(AllocateHeapNumberWithValue(var_double_value.value())); | |
1443 } | 1632 } |
1444 | 1633 |
1445 Bind(&if_oob); | |
1446 { | |
1447 Comment("out of bounds"); | |
1448 Node* index = var_index.value(); | |
1449 // Negative keys can't take the fast OOB path. | |
1450 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), &slow); | |
1451 // Positive OOB indices are effectively the same as hole loads. | |
1452 Goto(&if_element_hole); | |
1453 } | |
1454 | |
1455 Bind(&if_element_hole); | |
1456 { | |
1457 Comment("found the hole"); | |
1458 Label return_undefined(this); | |
1459 BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, &slow); | |
1460 | |
1461 Bind(&return_undefined); | |
1462 Return(UndefinedConstant()); | |
1463 } | |
1464 | |
1465 Node* properties = nullptr; | |
1466 Bind(&if_unique_name); | 1634 Bind(&if_unique_name); |
1467 { | 1635 { |
1468 Comment("key is unique name"); | 1636 GenericPropertyLoad(receiver, receiver_map, instance_type, |
1469 Node* key = var_unique.value(); | 1637 var_unique.value(), p, &slow); |
1470 // Check if the receiver has fast or slow properties. | |
1471 properties = LoadProperties(receiver); | |
1472 Node* properties_map = LoadMap(properties); | |
1473 GotoIf(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), | |
1474 &if_property_dictionary); | |
1475 | |
1476 // Try looking up the property on the receiver; if unsuccessful, look | |
1477 // for a handler in the stub cache. | |
1478 Comment("DescriptorArray lookup"); | |
1479 | |
1480 // Skip linear search if there are too many descriptors. | |
1481 // TODO(jkummerow): Consider implementing binary search. | |
1482 // See also TryLookupProperty() which has the same limitation. | |
1483 const int32_t kMaxLinear = 210; | |
1484 Label stub_cache(this); | |
1485 Node* bitfield3 = LoadMapBitField3(receiver_map); | |
1486 Node* nof = | |
1487 DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3); | |
1488 GotoIf(UintPtrLessThan(IntPtrConstant(kMaxLinear), nof), &stub_cache); | |
1489 Node* descriptors = LoadMapDescriptors(receiver_map); | |
1490 Variable var_name_index(this, MachineType::PointerRepresentation()); | |
1491 Label if_descriptor_found(this); | |
1492 DescriptorLookupLinear(key, descriptors, nof, &if_descriptor_found, | |
1493 &var_name_index, &stub_cache); | |
1494 | |
1495 Bind(&if_descriptor_found); | |
1496 { | |
1497 LoadPropertyFromFastObject(receiver, receiver_map, descriptors, | |
1498 var_name_index.value(), &var_details, | |
1499 &var_value); | |
1500 Goto(&if_found_on_receiver); | |
1501 } | |
1502 | |
1503 Bind(&stub_cache); | |
1504 { | |
1505 Comment("stub cache probe for fast property load"); | |
1506 Variable var_handler(this, MachineRepresentation::kTagged); | |
1507 Label found_handler(this, &var_handler), stub_cache_miss(this); | |
1508 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, | |
1509 &found_handler, &var_handler, &stub_cache_miss); | |
1510 Bind(&found_handler); | |
1511 { HandleLoadICHandlerCase(p, var_handler.value(), &slow); } | |
1512 | |
1513 Bind(&stub_cache_miss); | |
1514 { | |
1515 Comment("KeyedLoadGeneric_miss"); | |
1516 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | |
1517 p->name, p->slot, p->vector); | |
1518 } | |
1519 } | |
1520 } | |
1521 | |
1522 Bind(&if_property_dictionary); | |
1523 { | |
1524 Comment("dictionary property load"); | |
1525 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out | |
1526 // seeing global objects here (which would need special handling). | |
1527 | |
1528 Node* key = var_unique.value(); | |
1529 Variable var_name_index(this, MachineType::PointerRepresentation()); | |
1530 Label dictionary_found(this, &var_name_index); | |
1531 NameDictionaryLookup<NameDictionary>(properties, key, &dictionary_found, | |
1532 &var_name_index, | |
1533 &lookup_prototype_chain); | |
1534 Bind(&dictionary_found); | |
1535 { | |
1536 LoadPropertyFromNameDictionary(properties, var_name_index.value(), | |
1537 &var_details, &var_value); | |
1538 Goto(&if_found_on_receiver); | |
1539 } | |
1540 } | |
1541 | |
1542 Bind(&if_found_on_receiver); | |
1543 { | |
1544 Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(), | |
1545 p->context, receiver, &slow); | |
1546 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1); | |
1547 Return(value); | |
1548 } | |
1549 | |
1550 Bind(&lookup_prototype_chain); | |
1551 { | |
1552 Variable var_holder_map(this, MachineRepresentation::kTagged); | |
1553 Variable var_holder_instance_type(this, MachineRepresentation::kWord32); | |
1554 Label return_undefined(this); | |
1555 Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type}; | |
1556 Label loop(this, arraysize(merged_variables), merged_variables); | |
1557 | |
1558 var_holder_map.Bind(receiver_map); | |
1559 var_holder_instance_type.Bind(instance_type); | |
1560 // Private symbols must not be looked up on the prototype chain. | |
1561 GotoIf(IsPrivateSymbol(var_unique.value()), &return_undefined); | |
1562 Goto(&loop); | |
1563 Bind(&loop); | |
1564 { | |
1565 // Bailout if it can be an integer indexed exotic case. | |
1566 GotoIf(Word32Equal(var_holder_instance_type.value(), | |
1567 Int32Constant(JS_TYPED_ARRAY_TYPE)), | |
1568 &slow); | |
1569 Node* proto = LoadMapPrototype(var_holder_map.value()); | |
1570 GotoIf(WordEqual(proto, NullConstant()), &return_undefined); | |
1571 Node* proto_map = LoadMap(proto); | |
1572 Node* proto_instance_type = LoadMapInstanceType(proto_map); | |
1573 var_holder_map.Bind(proto_map); | |
1574 var_holder_instance_type.Bind(proto_instance_type); | |
1575 Label next_proto(this), return_value(this, &var_value), goto_slow(this); | |
1576 TryGetOwnProperty(p->context, receiver, proto, proto_map, | |
1577 proto_instance_type, var_unique.value(), &return_value, | |
1578 &var_value, &next_proto, &goto_slow); | |
1579 | |
1580 // This trampoline and the next are required to appease Turbofan's | |
1581 // variable merging. | |
1582 Bind(&next_proto); | |
1583 Goto(&loop); | |
1584 | |
1585 Bind(&goto_slow); | |
1586 Goto(&slow); | |
1587 | |
1588 Bind(&return_value); | |
1589 Return(var_value.value()); | |
1590 } | |
1591 | |
1592 Bind(&return_undefined); | |
1593 Return(UndefinedConstant()); | |
1594 } | 1638 } |
1595 | 1639 |
1596 Bind(&slow); | 1640 Bind(&slow); |
1597 { | 1641 { |
1598 Comment("KeyedLoadGeneric_slow"); | 1642 Comment("KeyedLoadGeneric_slow"); |
1599 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 1643 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
1600 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 1644 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
1601 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 1645 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
1602 p->name); | 1646 p->name); |
1603 } | 1647 } |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1931 Node* slot = Parameter(Descriptor::kSlot); | 1975 Node* slot = Parameter(Descriptor::kSlot); |
1932 Node* context = Parameter(Descriptor::kContext); | 1976 Node* context = Parameter(Descriptor::kContext); |
1933 Node* vector = LoadTypeFeedbackVectorForStub(); | 1977 Node* vector = LoadTypeFeedbackVectorForStub(); |
1934 | 1978 |
1935 StoreICParameters p(context, receiver, name, value, slot, vector); | 1979 StoreICParameters p(context, receiver, name, value, slot, vector); |
1936 KeyedStoreIC(&p, language_mode); | 1980 KeyedStoreIC(&p, language_mode); |
1937 } | 1981 } |
1938 | 1982 |
1939 } // namespace internal | 1983 } // namespace internal |
1940 } // namespace v8 | 1984 } // namespace v8 |
OLD | NEW |