| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 | 1046 |
| 1047 | 1047 |
| 1048 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1048 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
| 1049 Handle<Map> map) { | 1049 Handle<Map> map) { |
| 1050 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1050 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
| 1051 AddInstruction(check); | 1051 AddInstruction(check); |
| 1052 return check; | 1052 return check; |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 | 1055 |
| 1056 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | |
| 1057 HValue* external_elements, | |
| 1058 HValue* checked_key, | |
| 1059 HValue* val, | |
| 1060 HValue* dependency, | |
| 1061 ElementsKind elements_kind, | |
| 1062 bool is_store) { | |
| 1063 Zone* zone = this->zone(); | |
| 1064 if (is_store) { | |
| 1065 ASSERT(val != NULL); | |
| 1066 switch (elements_kind) { | |
| 1067 case EXTERNAL_PIXEL_ELEMENTS: { | |
| 1068 val = Add<HClampToUint8>(val); | |
| 1069 break; | |
| 1070 } | |
| 1071 case EXTERNAL_BYTE_ELEMENTS: | |
| 1072 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 1073 case EXTERNAL_SHORT_ELEMENTS: | |
| 1074 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 1075 case EXTERNAL_INT_ELEMENTS: | |
| 1076 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
| 1077 break; | |
| 1078 } | |
| 1079 case EXTERNAL_FLOAT_ELEMENTS: | |
| 1080 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 1081 break; | |
| 1082 case FAST_SMI_ELEMENTS: | |
| 1083 case FAST_ELEMENTS: | |
| 1084 case FAST_DOUBLE_ELEMENTS: | |
| 1085 case FAST_HOLEY_SMI_ELEMENTS: | |
| 1086 case FAST_HOLEY_ELEMENTS: | |
| 1087 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 1088 case DICTIONARY_ELEMENTS: | |
| 1089 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 1090 UNREACHABLE(); | |
| 1091 break; | |
| 1092 } | |
| 1093 return new(zone) HStoreKeyed(external_elements, checked_key, | |
| 1094 val, elements_kind); | |
| 1095 } else { | |
| 1096 ASSERT(val == NULL); | |
| 1097 HLoadKeyed* load = | |
| 1098 new(zone) HLoadKeyed( | |
| 1099 external_elements, checked_key, dependency, elements_kind); | |
| 1100 if (FLAG_opt_safe_uint32_operations && | |
| 1101 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
| 1102 graph()->RecordUint32Instruction(load); | |
| 1103 } | |
| 1104 return load; | |
| 1105 } | |
| 1106 } | |
| 1107 | |
| 1108 | |
| 1109 HInstruction* HGraphBuilder::BuildFastElementAccess( | |
| 1110 HValue* elements, | |
| 1111 HValue* checked_key, | |
| 1112 HValue* val, | |
| 1113 HValue* load_dependency, | |
| 1114 ElementsKind elements_kind, | |
| 1115 bool is_store, | |
| 1116 LoadKeyedHoleMode load_mode, | |
| 1117 KeyedAccessStoreMode store_mode) { | |
| 1118 Zone* zone = this->zone(); | |
| 1119 if (is_store) { | |
| 1120 ASSERT(val != NULL); | |
| 1121 switch (elements_kind) { | |
| 1122 case FAST_SMI_ELEMENTS: | |
| 1123 case FAST_HOLEY_SMI_ELEMENTS: | |
| 1124 case FAST_ELEMENTS: | |
| 1125 case FAST_HOLEY_ELEMENTS: | |
| 1126 case FAST_DOUBLE_ELEMENTS: | |
| 1127 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 1128 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | |
| 1129 default: | |
| 1130 UNREACHABLE(); | |
| 1131 return NULL; | |
| 1132 } | |
| 1133 } | |
| 1134 // It's an element load (!is_store). | |
| 1135 return new(zone) HLoadKeyed(elements, | |
| 1136 checked_key, | |
| 1137 load_dependency, | |
| 1138 elements_kind, | |
| 1139 load_mode); | |
| 1140 } | |
| 1141 | |
| 1142 | |
| 1143 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1056 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
| 1144 HValue* elements, | 1057 HValue* elements, |
| 1145 ElementsKind kind, | 1058 ElementsKind kind, |
| 1146 HValue* length, | 1059 HValue* length, |
| 1147 HValue* key, | 1060 HValue* key, |
| 1148 bool is_js_array) { | 1061 bool is_js_array) { |
| 1149 Zone* zone = this->zone(); | 1062 Zone* zone = this->zone(); |
| 1150 IfBuilder length_checker(this); | 1063 IfBuilder length_checker(this); |
| 1151 | 1064 |
| 1152 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; | 1065 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 cow_checker.Else(); | 1131 cow_checker.Else(); |
| 1219 | 1132 |
| 1220 environment()->Push(elements); | 1133 environment()->Push(elements); |
| 1221 | 1134 |
| 1222 cow_checker.End(); | 1135 cow_checker.End(); |
| 1223 | 1136 |
| 1224 return environment()->Pop(); | 1137 return environment()->Pop(); |
| 1225 } | 1138 } |
| 1226 | 1139 |
| 1227 | 1140 |
| 1141 void HGraphBuilder::BuildTransitionElementsKind(HValue* object, |
| 1142 HValue* map, |
| 1143 ElementsKind from_kind, |
| 1144 ElementsKind to_kind, |
| 1145 bool is_jsarray) { |
| 1146 ASSERT(!IsFastHoleyElementsKind(from_kind) || |
| 1147 IsFastHoleyElementsKind(to_kind)); |
| 1148 |
| 1149 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 1150 Add<HTrapAllocationMemento>(object); |
| 1151 } |
| 1152 |
| 1153 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 1154 HInstruction* elements = AddLoadElements(object); |
| 1155 |
| 1156 HInstruction* empty_fixed_array = Add<HConstant>( |
| 1157 isolate()->factory()->empty_fixed_array(), Representation::Tagged()); |
| 1158 |
| 1159 IfBuilder if_builder(this); |
| 1160 |
| 1161 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
| 1162 |
| 1163 if_builder.Then(); |
| 1164 |
| 1165 HInstruction* elements_length = AddLoadFixedArrayLength(elements); |
| 1166 |
| 1167 HInstruction* array_length = is_jsarray |
| 1168 ? AddLoad(object, HObjectAccess::ForArrayLength(), |
| 1169 NULL, Representation::Smi()) |
| 1170 : elements_length; |
| 1171 array_length->set_type(HType::Smi()); |
| 1172 |
| 1173 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
| 1174 array_length, elements_length); |
| 1175 |
| 1176 if_builder.End(); |
| 1177 } |
| 1178 |
| 1179 AddStore(object, HObjectAccess::ForMap(), map); |
| 1180 } |
| 1181 |
| 1182 |
| 1228 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1183 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 1229 HValue* object, | 1184 HValue* object, |
| 1230 HValue* key, | 1185 HValue* key, |
| 1231 HValue* val, | 1186 HValue* val, |
| 1232 HCheckMaps* mapcheck, | 1187 HCheckMaps* mapcheck, |
| 1233 bool is_js_array, | 1188 bool is_js_array, |
| 1234 ElementsKind elements_kind, | 1189 ElementsKind elements_kind, |
| 1235 bool is_store, | 1190 bool is_store, |
| 1236 LoadKeyedHoleMode load_mode, | 1191 LoadKeyedHoleMode load_mode, |
| 1237 KeyedAccessStoreMode store_mode) { | 1192 KeyedAccessStoreMode store_mode) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 NoObservableSideEffectsScope no_effects(this); | 1228 NoObservableSideEffectsScope no_effects(this); |
| 1274 HLoadExternalArrayPointer* external_elements = | 1229 HLoadExternalArrayPointer* external_elements = |
| 1275 Add<HLoadExternalArrayPointer>(elements); | 1230 Add<HLoadExternalArrayPointer>(elements); |
| 1276 IfBuilder length_checker(this); | 1231 IfBuilder length_checker(this); |
| 1277 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1232 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 1278 length_checker.Then(); | 1233 length_checker.Then(); |
| 1279 IfBuilder negative_checker(this); | 1234 IfBuilder negative_checker(this); |
| 1280 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1235 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 1281 key, graph()->GetConstant0(), Token::GTE); | 1236 key, graph()->GetConstant0(), Token::GTE); |
| 1282 negative_checker.Then(); | 1237 negative_checker.Then(); |
| 1283 HInstruction* result = BuildExternalArrayElementAccess( | 1238 HInstruction* result = AddExternalArrayElementAccess( |
| 1284 external_elements, key, val, bounds_check, | 1239 external_elements, key, val, bounds_check, elements_kind, is_store); |
| 1285 elements_kind, is_store); | |
| 1286 AddInstruction(result); | |
| 1287 negative_checker.ElseDeopt(); | 1240 negative_checker.ElseDeopt(); |
| 1288 length_checker.End(); | 1241 length_checker.End(); |
| 1289 return result; | 1242 return result; |
| 1290 } else { | 1243 } else { |
| 1291 ASSERT(store_mode == STANDARD_STORE); | 1244 ASSERT(store_mode == STANDARD_STORE); |
| 1292 checked_key = Add<HBoundsCheck>(key, length); | 1245 checked_key = Add<HBoundsCheck>(key, length); |
| 1293 HLoadExternalArrayPointer* external_elements = | 1246 HLoadExternalArrayPointer* external_elements = |
| 1294 Add<HLoadExternalArrayPointer>(elements); | 1247 Add<HLoadExternalArrayPointer>(elements); |
| 1295 return AddInstruction(BuildExternalArrayElementAccess( | 1248 return AddExternalArrayElementAccess( |
| 1296 external_elements, checked_key, val, mapcheck, | 1249 external_elements, checked_key, val, |
| 1297 elements_kind, is_store)); | 1250 mapcheck, elements_kind, is_store); |
| 1298 } | 1251 } |
| 1299 } | 1252 } |
| 1300 ASSERT(fast_smi_only_elements || | 1253 ASSERT(fast_smi_only_elements || |
| 1301 fast_elements || | 1254 fast_elements || |
| 1302 IsFastDoubleElementsKind(elements_kind)); | 1255 IsFastDoubleElementsKind(elements_kind)); |
| 1303 | 1256 |
| 1304 // In case val is stored into a fast smi array, assure that the value is a smi | 1257 // In case val is stored into a fast smi array, assure that the value is a smi |
| 1305 // before manipulating the backing store. Otherwise the actual store may | 1258 // before manipulating the backing store. Otherwise the actual store may |
| 1306 // deopt, leaving the backing store in an invalid state. | 1259 // deopt, leaving the backing store in an invalid state. |
| 1307 if (is_store && IsFastSmiElementsKind(elements_kind) && | 1260 if (is_store && IsFastSmiElementsKind(elements_kind) && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1324 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1277 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
| 1325 length); | 1278 length); |
| 1326 } else { | 1279 } else { |
| 1327 HCheckMaps* check_cow_map = HCheckMaps::New( | 1280 HCheckMaps* check_cow_map = HCheckMaps::New( |
| 1328 elements, isolate()->factory()->fixed_array_map(), zone); | 1281 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1329 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1282 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1330 AddInstruction(check_cow_map); | 1283 AddInstruction(check_cow_map); |
| 1331 } | 1284 } |
| 1332 } | 1285 } |
| 1333 } | 1286 } |
| 1334 return AddInstruction( | 1287 return AddFastElementAccess(elements, checked_key, val, mapcheck, |
| 1335 BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1288 elements_kind, is_store, load_mode, store_mode); |
| 1336 elements_kind, is_store, load_mode, store_mode)); | |
| 1337 } | 1289 } |
| 1338 | 1290 |
| 1339 | 1291 |
| 1340 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1292 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
| 1341 ElementsKind kind, | 1293 ElementsKind kind, |
| 1342 HValue* capacity) { | 1294 HValue* capacity) { |
| 1343 Zone* zone = this->zone(); | 1295 Zone* zone = this->zone(); |
| 1344 | 1296 |
| 1345 int elements_size = IsFastDoubleElementsKind(kind) | 1297 int elements_size = IsFastDoubleElementsKind(kind) |
| 1346 ? kDoubleSize : kPointerSize; | 1298 ? kDoubleSize : kPointerSize; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 AddStore(array, HObjectAccess::ForMap(), array_map); | 1358 AddStore(array, HObjectAccess::ForMap(), array_map); |
| 1407 | 1359 |
| 1408 HConstant* empty_fixed_array = | 1360 HConstant* empty_fixed_array = |
| 1409 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 1361 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 1410 | 1362 |
| 1411 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1363 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 1412 AddStore(array, access, empty_fixed_array); | 1364 AddStore(array, access, empty_fixed_array); |
| 1413 AddStore(array, HObjectAccess::ForArrayLength(), length_field); | 1365 AddStore(array, HObjectAccess::ForArrayLength(), length_field); |
| 1414 | 1366 |
| 1415 if (mode == TRACK_ALLOCATION_SITE) { | 1367 if (mode == TRACK_ALLOCATION_SITE) { |
| 1416 BuildCreateAllocationSiteInfo(array, | 1368 BuildCreateAllocationMemento(array, |
| 1417 JSArray::kSize, | 1369 JSArray::kSize, |
| 1418 allocation_site_payload); | 1370 allocation_site_payload); |
| 1419 } | 1371 } |
| 1420 | 1372 |
| 1421 int elements_location = JSArray::kSize; | 1373 int elements_location = JSArray::kSize; |
| 1422 if (mode == TRACK_ALLOCATION_SITE) { | 1374 if (mode == TRACK_ALLOCATION_SITE) { |
| 1423 elements_location += AllocationSiteInfo::kSize; | 1375 elements_location += AllocationMemento::kSize; |
| 1424 } | 1376 } |
| 1425 | 1377 |
| 1426 HInnerAllocatedObject* elements = | 1378 HInnerAllocatedObject* elements = |
| 1427 Add<HInnerAllocatedObject>(array, elements_location); | 1379 Add<HInnerAllocatedObject>(array, elements_location); |
| 1428 AddStore(array, HObjectAccess::ForElementsPointer(), elements); | 1380 AddStore(array, HObjectAccess::ForElementsPointer(), elements); |
| 1429 return elements; | 1381 return elements; |
| 1430 } | 1382 } |
| 1431 | 1383 |
| 1432 | 1384 |
| 1385 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( |
| 1386 HValue* external_elements, |
| 1387 HValue* checked_key, |
| 1388 HValue* val, |
| 1389 HValue* dependency, |
| 1390 ElementsKind elements_kind, |
| 1391 bool is_store) { |
| 1392 if (is_store) { |
| 1393 ASSERT(val != NULL); |
| 1394 switch (elements_kind) { |
| 1395 case EXTERNAL_PIXEL_ELEMENTS: { |
| 1396 val = Add<HClampToUint8>(val); |
| 1397 break; |
| 1398 } |
| 1399 case EXTERNAL_BYTE_ELEMENTS: |
| 1400 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 1401 case EXTERNAL_SHORT_ELEMENTS: |
| 1402 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 1403 case EXTERNAL_INT_ELEMENTS: |
| 1404 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 1405 break; |
| 1406 } |
| 1407 case EXTERNAL_FLOAT_ELEMENTS: |
| 1408 case EXTERNAL_DOUBLE_ELEMENTS: |
| 1409 break; |
| 1410 case FAST_SMI_ELEMENTS: |
| 1411 case FAST_ELEMENTS: |
| 1412 case FAST_DOUBLE_ELEMENTS: |
| 1413 case FAST_HOLEY_SMI_ELEMENTS: |
| 1414 case FAST_HOLEY_ELEMENTS: |
| 1415 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1416 case DICTIONARY_ELEMENTS: |
| 1417 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 1418 UNREACHABLE(); |
| 1419 break; |
| 1420 } |
| 1421 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); |
| 1422 } else { |
| 1423 ASSERT(val == NULL); |
| 1424 HLoadKeyed* load = Add<HLoadKeyed>(external_elements, checked_key, |
| 1425 dependency, elements_kind); |
| 1426 if (FLAG_opt_safe_uint32_operations && |
| 1427 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 1428 graph()->RecordUint32Instruction(load); |
| 1429 } |
| 1430 return load; |
| 1431 } |
| 1432 } |
| 1433 |
| 1434 |
| 1435 HInstruction* HGraphBuilder::AddFastElementAccess( |
| 1436 HValue* elements, |
| 1437 HValue* checked_key, |
| 1438 HValue* val, |
| 1439 HValue* load_dependency, |
| 1440 ElementsKind elements_kind, |
| 1441 bool is_store, |
| 1442 LoadKeyedHoleMode load_mode, |
| 1443 KeyedAccessStoreMode store_mode) { |
| 1444 if (is_store) { |
| 1445 ASSERT(val != NULL); |
| 1446 switch (elements_kind) { |
| 1447 case FAST_SMI_ELEMENTS: |
| 1448 case FAST_HOLEY_SMI_ELEMENTS: |
| 1449 case FAST_ELEMENTS: |
| 1450 case FAST_HOLEY_ELEMENTS: |
| 1451 case FAST_DOUBLE_ELEMENTS: |
| 1452 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1453 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind); |
| 1454 default: |
| 1455 UNREACHABLE(); |
| 1456 return NULL; |
| 1457 } |
| 1458 } |
| 1459 // It's an element load (!is_store). |
| 1460 return Add<HLoadKeyed>( |
| 1461 elements, checked_key, load_dependency, elements_kind, load_mode); |
| 1462 } |
| 1463 |
| 1464 |
| 1433 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1465 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
| 1434 HValue* typecheck) { | 1466 HValue* typecheck) { |
| 1435 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1467 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); |
| 1436 } | 1468 } |
| 1437 | 1469 |
| 1438 | 1470 |
| 1439 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1471 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 1440 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), | 1472 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(), |
| 1441 NULL, Representation::Smi()); | 1473 NULL, Representation::Smi()); |
| 1442 instr->set_type(HType::Smi()); | 1474 instr->set_type(HType::Smi()); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1607 HValue* boilerplate, | 1639 HValue* boilerplate, |
| 1608 HValue* allocation_site, | 1640 HValue* allocation_site, |
| 1609 AllocationSiteMode mode, | 1641 AllocationSiteMode mode, |
| 1610 ElementsKind kind, | 1642 ElementsKind kind, |
| 1611 int length) { | 1643 int length) { |
| 1612 NoObservableSideEffectsScope no_effects(this); | 1644 NoObservableSideEffectsScope no_effects(this); |
| 1613 | 1645 |
| 1614 // All sizes here are multiples of kPointerSize. | 1646 // All sizes here are multiples of kPointerSize. |
| 1615 int size = JSArray::kSize; | 1647 int size = JSArray::kSize; |
| 1616 if (mode == TRACK_ALLOCATION_SITE) { | 1648 if (mode == TRACK_ALLOCATION_SITE) { |
| 1617 size += AllocationSiteInfo::kSize; | 1649 size += AllocationMemento::kSize; |
| 1618 } | 1650 } |
| 1619 int elems_offset = size; | 1651 int elems_offset = size; |
| 1620 if (length > 0) { | 1652 if (length > 0) { |
| 1621 size += IsFastDoubleElementsKind(kind) | 1653 size += IsFastDoubleElementsKind(kind) |
| 1622 ? FixedDoubleArray::SizeFor(length) | 1654 ? FixedDoubleArray::SizeFor(length) |
| 1623 : FixedArray::SizeFor(length); | 1655 : FixedArray::SizeFor(length); |
| 1624 } | 1656 } |
| 1625 | 1657 |
| 1626 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); | 1658 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); |
| 1627 // Allocate both the JS array and the elements array in one big | 1659 // Allocate both the JS array and the elements array in one big |
| 1628 // allocation. This avoids multiple limit checks. | 1660 // allocation. This avoids multiple limit checks. |
| 1629 HValue* size_in_bytes = Add<HConstant>(size); | 1661 HValue* size_in_bytes = Add<HConstant>(size); |
| 1630 HInstruction* object = Add<HAllocate>(context, | 1662 HInstruction* object = Add<HAllocate>(context, |
| 1631 size_in_bytes, | 1663 size_in_bytes, |
| 1632 HType::JSObject(), | 1664 HType::JSObject(), |
| 1633 allocate_flags); | 1665 allocate_flags); |
| 1634 | 1666 |
| 1635 // Copy the JS array part. | 1667 // Copy the JS array part. |
| 1636 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1668 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 1637 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1669 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 1638 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 1670 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 1639 AddStore(object, access, AddLoad(boilerplate, access)); | 1671 AddStore(object, access, AddLoad(boilerplate, access)); |
| 1640 } | 1672 } |
| 1641 } | 1673 } |
| 1642 | 1674 |
| 1643 // Create an allocation site info if requested. | 1675 // Create an allocation site info if requested. |
| 1644 if (mode == TRACK_ALLOCATION_SITE) { | 1676 if (mode == TRACK_ALLOCATION_SITE) { |
| 1645 BuildCreateAllocationSiteInfo(object, JSArray::kSize, allocation_site); | 1677 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
| 1646 } | 1678 } |
| 1647 | 1679 |
| 1648 if (length > 0) { | 1680 if (length > 0) { |
| 1649 // Get hold of the elements array of the boilerplate and setup the | 1681 // Get hold of the elements array of the boilerplate and setup the |
| 1650 // elements pointer in the resulting object. | 1682 // elements pointer in the resulting object. |
| 1651 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1683 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 1652 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1684 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
| 1653 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); | 1685 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); |
| 1654 | 1686 |
| 1655 // Copy the elements array header. | 1687 // Copy the elements array header. |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1740 BuildCheckMap(value, type->Classes().Current()); | 1772 BuildCheckMap(value, type->Classes().Current()); |
| 1741 } else { | 1773 } else { |
| 1742 if_nil.Deopt(); | 1774 if_nil.Deopt(); |
| 1743 } | 1775 } |
| 1744 } | 1776 } |
| 1745 | 1777 |
| 1746 if_nil.CaptureContinuation(continuation); | 1778 if_nil.CaptureContinuation(continuation); |
| 1747 } | 1779 } |
| 1748 | 1780 |
| 1749 | 1781 |
| 1750 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, | 1782 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
| 1751 int previous_object_size, | 1783 int previous_object_size, |
| 1752 HValue* alloc_site) { | 1784 HValue* alloc_site) { |
| 1753 ASSERT(alloc_site != NULL); | 1785 ASSERT(alloc_site != NULL); |
| 1754 HInnerAllocatedObject* alloc_site_info = Add<HInnerAllocatedObject>( | 1786 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( |
| 1755 previous_object, previous_object_size); | 1787 previous_object, previous_object_size); |
| 1756 Handle<Map> alloc_site_info_map( | 1788 Handle<Map> alloc_memento_map( |
| 1757 isolate()->heap()->allocation_site_info_map()); | 1789 isolate()->heap()->allocation_memento_map()); |
| 1758 AddStoreMapConstant(alloc_site_info, alloc_site_info_map); | 1790 AddStoreMapConstant(alloc_memento, alloc_memento_map); |
| 1759 HObjectAccess access = HObjectAccess::ForAllocationSiteInfoSite(); | 1791 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
| 1760 AddStore(alloc_site_info, access, alloc_site); | 1792 AddStore(alloc_memento, access, alloc_site); |
| 1761 return alloc_site_info; | 1793 return alloc_memento; |
| 1762 } | 1794 } |
| 1763 | 1795 |
| 1764 | 1796 |
| 1765 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { | 1797 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { |
| 1766 // Get the global context, then the native context | 1798 // Get the global context, then the native context |
| 1767 HInstruction* global_object = Add<HGlobalObject>(context); | 1799 HInstruction* global_object = Add<HGlobalObject>(context); |
| 1768 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1800 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 1769 GlobalObject::kNativeContextOffset); | 1801 GlobalObject::kNativeContextOffset); |
| 1770 return AddLoad(global_object, access); | 1802 return AddLoad(global_object, access); |
| 1771 } | 1803 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1842 } | 1874 } |
| 1843 | 1875 |
| 1844 | 1876 |
| 1845 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1877 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1846 HValue* length_node) { | 1878 HValue* length_node) { |
| 1847 HValue* context = builder()->environment()->LookupContext(); | 1879 HValue* context = builder()->environment()->LookupContext(); |
| 1848 ASSERT(length_node != NULL); | 1880 ASSERT(length_node != NULL); |
| 1849 | 1881 |
| 1850 int base_size = JSArray::kSize; | 1882 int base_size = JSArray::kSize; |
| 1851 if (mode_ == TRACK_ALLOCATION_SITE) { | 1883 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1852 base_size += AllocationSiteInfo::kSize; | 1884 base_size += AllocationMemento::kSize; |
| 1853 } | 1885 } |
| 1854 | 1886 |
| 1855 if (IsFastDoubleElementsKind(kind_)) { | 1887 if (IsFastDoubleElementsKind(kind_)) { |
| 1856 base_size += FixedDoubleArray::kHeaderSize; | 1888 base_size += FixedDoubleArray::kHeaderSize; |
| 1857 } else { | 1889 } else { |
| 1858 base_size += FixedArray::kHeaderSize; | 1890 base_size += FixedArray::kHeaderSize; |
| 1859 } | 1891 } |
| 1860 | 1892 |
| 1861 HInstruction* elements_size_value = | 1893 HInstruction* elements_size_value = |
| 1862 builder()->Add<HConstant>(elements_size()); | 1894 builder()->Add<HConstant>(elements_size()); |
| 1863 HInstruction* mul = HMul::New(zone(), context, length_node, | 1895 HInstruction* mul = HMul::New(zone(), context, length_node, |
| 1864 elements_size_value); | 1896 elements_size_value); |
| 1865 mul->ClearFlag(HValue::kCanOverflow); | 1897 mul->ClearFlag(HValue::kCanOverflow); |
| 1866 builder()->AddInstruction(mul); | 1898 builder()->AddInstruction(mul); |
| 1867 | 1899 |
| 1868 HInstruction* base = builder()->Add<HConstant>(base_size); | 1900 HInstruction* base = builder()->Add<HConstant>(base_size); |
| 1869 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1901 HInstruction* total_size = HAdd::New(zone(), context, base, mul); |
| 1870 total_size->ClearFlag(HValue::kCanOverflow); | 1902 total_size->ClearFlag(HValue::kCanOverflow); |
| 1871 builder()->AddInstruction(total_size); | 1903 builder()->AddInstruction(total_size); |
| 1872 return total_size; | 1904 return total_size; |
| 1873 } | 1905 } |
| 1874 | 1906 |
| 1875 | 1907 |
| 1876 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 1908 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
| 1877 int base_size = JSArray::kSize; | 1909 int base_size = JSArray::kSize; |
| 1878 if (mode_ == TRACK_ALLOCATION_SITE) { | 1910 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1879 base_size += AllocationSiteInfo::kSize; | 1911 base_size += AllocationMemento::kSize; |
| 1880 } | 1912 } |
| 1881 | 1913 |
| 1882 base_size += IsFastDoubleElementsKind(kind_) | 1914 base_size += IsFastDoubleElementsKind(kind_) |
| 1883 ? FixedDoubleArray::SizeFor(initial_capacity()) | 1915 ? FixedDoubleArray::SizeFor(initial_capacity()) |
| 1884 : FixedArray::SizeFor(initial_capacity()); | 1916 : FixedArray::SizeFor(initial_capacity()); |
| 1885 | 1917 |
| 1886 return builder()->Add<HConstant>(base_size); | 1918 return builder()->Add<HConstant>(base_size); |
| 1887 } | 1919 } |
| 1888 | 1920 |
| 1889 | 1921 |
| (...skipping 2491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4381 // Check whether to use fast or slow deep-copying for boilerplate. | 4413 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4382 int data_size = 0; | 4414 int data_size = 0; |
| 4383 int pointer_size = 0; | 4415 int pointer_size = 0; |
| 4384 int max_properties = kMaxFastLiteralProperties; | 4416 int max_properties = kMaxFastLiteralProperties; |
| 4385 if (IsFastLiteral(original_boilerplate_object, | 4417 if (IsFastLiteral(original_boilerplate_object, |
| 4386 kMaxFastLiteralDepth, | 4418 kMaxFastLiteralDepth, |
| 4387 &max_properties, | 4419 &max_properties, |
| 4388 &data_size, | 4420 &data_size, |
| 4389 &pointer_size)) { | 4421 &pointer_size)) { |
| 4390 if (mode == TRACK_ALLOCATION_SITE) { | 4422 if (mode == TRACK_ALLOCATION_SITE) { |
| 4391 pointer_size += AllocationSiteInfo::kSize; | 4423 pointer_size += AllocationMemento::kSize; |
| 4392 } | 4424 } |
| 4393 | 4425 |
| 4394 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4426 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
| 4395 literal = BuildFastLiteral(context, | 4427 literal = BuildFastLiteral(context, |
| 4396 boilerplate_object, | 4428 boilerplate_object, |
| 4397 original_boilerplate_object, | 4429 original_boilerplate_object, |
| 4398 site, | 4430 site, |
| 4399 data_size, | 4431 data_size, |
| 4400 pointer_size, | 4432 pointer_size, |
| 4401 mode); | 4433 mode); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4782 if (count != types->length()) return false; | 4814 if (count != types->length()) return false; |
| 4783 | 4815 |
| 4784 // Everything matched; can use monomorphic store. | 4816 // Everything matched; can use monomorphic store. |
| 4785 BuildCheckHeapObject(object); | 4817 BuildCheckHeapObject(object); |
| 4786 AddInstruction(HCheckMaps::New(object, types, zone())); | 4818 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 4787 HInstruction* store; | 4819 HInstruction* store; |
| 4788 CHECK_ALIVE_OR_RETURN( | 4820 CHECK_ALIVE_OR_RETURN( |
| 4789 store = BuildStoreNamedField( | 4821 store = BuildStoreNamedField( |
| 4790 object, name, store_value, types->at(count - 1), &lookup), | 4822 object, name, store_value, types->at(count - 1), &lookup), |
| 4791 true); | 4823 true); |
| 4792 if (result_value != NULL) Push(result_value); | 4824 if (!ast_context()->IsEffect()) Push(result_value); |
| 4793 Push(store_value); | |
| 4794 store->set_position(position); | 4825 store->set_position(position); |
| 4795 AddInstruction(store); | 4826 AddInstruction(store); |
| 4796 AddSimulate(assignment_id); | 4827 AddSimulate(assignment_id); |
| 4797 if (result_value != NULL) Drop(1); | 4828 if (!ast_context()->IsEffect()) Drop(1); |
| 4798 ast_context()->ReturnValue(Pop()); | 4829 ast_context()->ReturnValue(result_value); |
| 4799 return true; | 4830 return true; |
| 4800 } | 4831 } |
| 4801 | 4832 |
| 4802 | 4833 |
| 4803 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4834 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 4804 BailoutId id, | |
| 4805 int position, | 4835 int position, |
| 4806 BailoutId assignment_id, | 4836 BailoutId assignment_id, |
| 4807 HValue* object, | 4837 HValue* object, |
| 4808 HValue* store_value, | 4838 HValue* store_value, |
| 4809 HValue* result_value, | 4839 HValue* result_value, |
| 4810 SmallMapList* types, | 4840 SmallMapList* types, |
| 4811 Handle<String> name) { | 4841 Handle<String> name) { |
| 4812 if (TryStorePolymorphicAsMonomorphic( | 4842 if (TryStorePolymorphicAsMonomorphic( |
| 4813 position, assignment_id, object, | 4843 position, assignment_id, object, |
| 4814 store_value, result_value, types, name)) { | 4844 store_value, result_value, types, name)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4835 new(zone()) HCompareMap(object, map, if_true, if_false); | 4865 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 4836 current_block()->Finish(compare); | 4866 current_block()->Finish(compare); |
| 4837 | 4867 |
| 4838 set_current_block(if_true); | 4868 set_current_block(if_true); |
| 4839 HInstruction* instr; | 4869 HInstruction* instr; |
| 4840 CHECK_ALIVE(instr = BuildStoreNamedField( | 4870 CHECK_ALIVE(instr = BuildStoreNamedField( |
| 4841 object, name, store_value, map, &lookup)); | 4871 object, name, store_value, map, &lookup)); |
| 4842 instr->set_position(position); | 4872 instr->set_position(position); |
| 4843 // Goto will add the HSimulate for the store. | 4873 // Goto will add the HSimulate for the store. |
| 4844 AddInstruction(instr); | 4874 AddInstruction(instr); |
| 4845 if (!ast_context()->IsEffect()) { | 4875 if (!ast_context()->IsEffect()) Push(result_value); |
| 4846 if (result_value != NULL) Push(result_value); | |
| 4847 Push(store_value); | |
| 4848 } | |
| 4849 current_block()->Goto(join); | 4876 current_block()->Goto(join); |
| 4850 | 4877 |
| 4851 set_current_block(if_false); | 4878 set_current_block(if_false); |
| 4852 } | 4879 } |
| 4853 } | 4880 } |
| 4854 | 4881 |
| 4855 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4882 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 4856 // know about and do not want to handle ones we've never seen. Otherwise | 4883 // know about and do not want to handle ones we've never seen. Otherwise |
| 4857 // use a generic IC. | 4884 // use a generic IC. |
| 4858 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4885 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 4859 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 4886 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 4860 } else { | 4887 } else { |
| 4861 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4888 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
| 4862 instr->set_position(position); | 4889 instr->set_position(position); |
| 4863 AddInstruction(instr); | 4890 AddInstruction(instr); |
| 4864 | 4891 |
| 4865 if (join != NULL) { | 4892 if (join != NULL) { |
| 4866 if (!ast_context()->IsEffect()) { | 4893 if (!ast_context()->IsEffect()) { |
| 4867 if (result_value != NULL) Push(result_value); | 4894 Push(result_value); |
| 4868 Push(store_value); | |
| 4869 } | 4895 } |
| 4870 current_block()->Goto(join); | 4896 current_block()->Goto(join); |
| 4871 } else { | 4897 } else { |
| 4872 // The HSimulate for the store should not see the stored value in | 4898 // The HSimulate for the store should not see the stored value in |
| 4873 // effect contexts (it is not materialized at expr->id() in the | 4899 // effect contexts (it is not materialized at expr->id() in the |
| 4874 // unoptimized code). | 4900 // unoptimized code). |
| 4875 if (instr->HasObservableSideEffects()) { | 4901 if (instr->HasObservableSideEffects()) { |
| 4876 if (ast_context()->IsEffect()) { | 4902 if (ast_context()->IsEffect()) { |
| 4877 AddSimulate(id, REMOVABLE_SIMULATE); | 4903 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
| 4878 } else { | 4904 } else { |
| 4879 if (result_value != NULL) Push(result_value); | 4905 Push(result_value); |
| 4880 Push(store_value); | 4906 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
| 4881 AddSimulate(id, REMOVABLE_SIMULATE); | 4907 Drop(1); |
| 4882 Drop(result_value != NULL ? 2 : 1); | |
| 4883 } | 4908 } |
| 4884 } | 4909 } |
| 4885 return ast_context()->ReturnValue( | 4910 return ast_context()->ReturnValue(result_value); |
| 4886 result_value != NULL ? result_value : store_value); | |
| 4887 } | 4911 } |
| 4888 } | 4912 } |
| 4889 | 4913 |
| 4890 ASSERT(join != NULL); | 4914 ASSERT(join != NULL); |
| 4891 join->SetJoinId(id); | 4915 join->SetJoinId(assignment_id); |
| 4892 set_current_block(join); | 4916 set_current_block(join); |
| 4893 if (!ast_context()->IsEffect()) { | 4917 if (!ast_context()->IsEffect()) { |
| 4894 if (result_value != NULL) Drop(1); | |
| 4895 ast_context()->ReturnValue(Pop()); | 4918 ast_context()->ReturnValue(Pop()); |
| 4896 } | 4919 } |
| 4897 } | 4920 } |
| 4898 | 4921 |
| 4899 | 4922 |
| 4900 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4923 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 4901 Property* prop = expr->target()->AsProperty(); | 4924 Property* prop = expr->target()->AsProperty(); |
| 4902 ASSERT(prop != NULL); | 4925 ASSERT(prop != NULL); |
| 4903 CHECK_ALIVE(VisitForValue(prop->obj())); | 4926 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4904 | 4927 |
| 4905 if (prop->key()->IsPropertyName()) { | 4928 if (prop->key()->IsPropertyName()) { |
| 4906 // Named store. | 4929 // Named store. |
| 4907 CHECK_ALIVE(VisitForValue(expr->value())); | 4930 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4908 HValue* value = environment()->ExpressionStackAt(0); | 4931 HValue* value = environment()->ExpressionStackAt(0); |
| 4909 HValue* object = environment()->ExpressionStackAt(1); | 4932 HValue* object = environment()->ExpressionStackAt(1); |
| 4910 | 4933 |
| 4911 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4934 if (expr->IsUninitialized()) AddSoftDeoptimize(); |
| 4912 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4935 return BuildStoreNamed(expr, expr->id(), expr->position(), |
| 4913 expr->AssignmentId(), prop, object, value); | 4936 expr->AssignmentId(), prop, object, value, value); |
| 4914 } else { | 4937 } else { |
| 4915 // Keyed store. | 4938 // Keyed store. |
| 4916 CHECK_ALIVE(VisitForValue(prop->key())); | 4939 CHECK_ALIVE(VisitForValue(prop->key())); |
| 4917 CHECK_ALIVE(VisitForValue(expr->value())); | 4940 CHECK_ALIVE(VisitForValue(expr->value())); |
| 4918 HValue* value = environment()->ExpressionStackAt(0); | 4941 HValue* value = environment()->ExpressionStackAt(0); |
| 4919 HValue* key = environment()->ExpressionStackAt(1); | 4942 HValue* key = environment()->ExpressionStackAt(1); |
| 4920 HValue* object = environment()->ExpressionStackAt(2); | 4943 HValue* object = environment()->ExpressionStackAt(2); |
| 4921 bool has_side_effects = false; | 4944 bool has_side_effects = false; |
| 4922 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4945 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 4923 expr->position(), | 4946 expr->position(), |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4996 map = types->first(); | 5019 map = types->first(); |
| 4997 if (map->is_dictionary_map()) monomorphic = false; | 5020 if (map->is_dictionary_map()) monomorphic = false; |
| 4998 } | 5021 } |
| 4999 if (monomorphic) { | 5022 if (monomorphic) { |
| 5000 Handle<JSFunction> setter; | 5023 Handle<JSFunction> setter; |
| 5001 Handle<JSObject> holder; | 5024 Handle<JSObject> holder; |
| 5002 if (LookupSetter(map, name, &setter, &holder)) { | 5025 if (LookupSetter(map, name, &setter, &holder)) { |
| 5003 AddCheckConstantFunction(holder, object, map); | 5026 AddCheckConstantFunction(holder, object, map); |
| 5004 // Don't try to inline if the result_value is different from the | 5027 // Don't try to inline if the result_value is different from the |
| 5005 // store_value. That case isn't handled yet by the inlining. | 5028 // store_value. That case isn't handled yet by the inlining. |
| 5006 if (result_value == NULL && | 5029 if (result_value == store_value && |
| 5007 FLAG_inline_accessors && | 5030 FLAG_inline_accessors && |
| 5008 TryInlineSetter(setter, id, assignment_id, store_value)) { | 5031 TryInlineSetter(setter, id, assignment_id, store_value)) { |
| 5009 return; | 5032 return; |
| 5010 } | 5033 } |
| 5011 Drop(2); | 5034 Drop(2); |
| 5012 Add<HPushArgument>(object); | 5035 Add<HPushArgument>(object); |
| 5013 Add<HPushArgument>(store_value); | 5036 Add<HPushArgument>(store_value); |
| 5014 instr = new(zone()) HCallConstantFunction(setter, 2); | 5037 instr = new(zone()) HCallConstantFunction(setter, 2); |
| 5015 } else { | 5038 } else { |
| 5016 Drop(2); | 5039 Drop(2); |
| 5017 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5040 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 5018 name, | 5041 name, |
| 5019 store_value, | 5042 store_value, |
| 5020 map)); | 5043 map)); |
| 5021 } | 5044 } |
| 5022 } else if (types != NULL && types->length() > 1) { | 5045 } else if (types != NULL && types->length() > 1) { |
| 5023 Drop(2); | 5046 Drop(2); |
| 5024 return HandlePolymorphicStoreNamedField( | 5047 return HandlePolymorphicStoreNamedField( |
| 5025 id, position, assignment_id, object, | 5048 position, id, object, |
| 5026 store_value, result_value, types, name); | 5049 store_value, result_value, types, name); |
| 5027 } else { | 5050 } else { |
| 5028 Drop(2); | 5051 Drop(2); |
| 5029 instr = BuildStoreNamedGeneric(object, name, store_value); | 5052 instr = BuildStoreNamedGeneric(object, name, store_value); |
| 5030 } | 5053 } |
| 5031 | 5054 |
| 5032 if (result_value != NULL) Push(result_value); | 5055 if (!ast_context()->IsEffect()) Push(result_value); |
| 5033 Push(store_value); | |
| 5034 instr->set_position(position); | 5056 instr->set_position(position); |
| 5035 AddInstruction(instr); | 5057 AddInstruction(instr); |
| 5036 if (instr->HasObservableSideEffects()) { | 5058 if (instr->HasObservableSideEffects()) { |
| 5037 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 5059 AddSimulate(id, REMOVABLE_SIMULATE); |
| 5038 } | 5060 } |
| 5039 if (result_value != NULL) Drop(1); | 5061 if (!ast_context()->IsEffect()) Drop(1); |
| 5040 return ast_context()->ReturnValue(Pop()); | 5062 return ast_context()->ReturnValue(result_value); |
| 5041 } | 5063 } |
| 5042 | 5064 |
| 5043 | 5065 |
| 5044 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5066 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5045 Expression* target = expr->target(); | 5067 Expression* target = expr->target(); |
| 5046 VariableProxy* proxy = target->AsVariableProxy(); | 5068 VariableProxy* proxy = target->AsVariableProxy(); |
| 5047 Property* prop = target->AsProperty(); | 5069 Property* prop = target->AsProperty(); |
| 5048 ASSERT(proxy == NULL || prop == NULL); | 5070 ASSERT(proxy == NULL || prop == NULL); |
| 5049 | 5071 |
| 5050 // We have a second position recorded in the FullCodeGenerator to have | 5072 // We have a second position recorded in the FullCodeGenerator to have |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5160 HValue* right = Pop(); | 5182 HValue* right = Pop(); |
| 5161 HValue* left = Pop(); | 5183 HValue* left = Pop(); |
| 5162 | 5184 |
| 5163 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5185 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5164 PushAndAdd(instr); | 5186 PushAndAdd(instr); |
| 5165 if (instr->HasObservableSideEffects()) { | 5187 if (instr->HasObservableSideEffects()) { |
| 5166 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5188 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
| 5167 } | 5189 } |
| 5168 | 5190 |
| 5169 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5191 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 5170 expr->AssignmentId(), prop, object, instr); | 5192 expr->AssignmentId(), prop, object, instr, instr); |
| 5171 } else { | 5193 } else { |
| 5172 // Keyed property. | 5194 // Keyed property. |
| 5173 CHECK_ALIVE(VisitForValue(prop->obj())); | 5195 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 5174 CHECK_ALIVE(VisitForValue(prop->key())); | 5196 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5175 HValue* obj = environment()->ExpressionStackAt(1); | 5197 HValue* obj = environment()->ExpressionStackAt(1); |
| 5176 HValue* key = environment()->ExpressionStackAt(0); | 5198 HValue* key = environment()->ExpressionStackAt(0); |
| 5177 | 5199 |
| 5178 bool has_side_effects = false; | 5200 bool has_side_effects = false; |
| 5179 HValue* load = HandleKeyedElementAccess( | 5201 HValue* load = HandleKeyedElementAccess( |
| 5180 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5202 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5572 HValue* val, | 5594 HValue* val, |
| 5573 Expression* prop, | 5595 Expression* prop, |
| 5574 BailoutId ast_id, | 5596 BailoutId ast_id, |
| 5575 int position, | 5597 int position, |
| 5576 bool is_store, | 5598 bool is_store, |
| 5577 KeyedAccessStoreMode store_mode, | 5599 KeyedAccessStoreMode store_mode, |
| 5578 bool* has_side_effects) { | 5600 bool* has_side_effects) { |
| 5579 *has_side_effects = false; | 5601 *has_side_effects = false; |
| 5580 BuildCheckHeapObject(object); | 5602 BuildCheckHeapObject(object); |
| 5581 SmallMapList* maps = prop->GetReceiverTypes(); | 5603 SmallMapList* maps = prop->GetReceiverTypes(); |
| 5582 bool todo_external_array = false; | |
| 5583 | 5604 |
| 5584 if (!is_store) { | 5605 if (!is_store) { |
| 5585 HInstruction* consolidated_load = | 5606 HInstruction* consolidated_load = |
| 5586 TryBuildConsolidatedElementLoad(object, key, val, maps); | 5607 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 5587 if (consolidated_load != NULL) { | 5608 if (consolidated_load != NULL) { |
| 5588 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 5609 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
| 5589 if (position != RelocInfo::kNoPosition) { | 5610 if (position != RelocInfo::kNoPosition) { |
| 5590 consolidated_load->set_position(position); | 5611 consolidated_load->set_position(position); |
| 5591 } | 5612 } |
| 5592 return consolidated_load; | 5613 return consolidated_load; |
| 5593 } | 5614 } |
| 5594 } | 5615 } |
| 5595 | 5616 |
| 5596 static const int kNumElementTypes = kElementsKindCount; | |
| 5597 bool type_todo[kNumElementTypes]; | |
| 5598 for (int i = 0; i < kNumElementTypes; ++i) { | |
| 5599 type_todo[i] = false; | |
| 5600 } | |
| 5601 | |
| 5602 // Elements_kind transition support. | 5617 // Elements_kind transition support. |
| 5603 MapHandleList transition_target(maps->length()); | 5618 MapHandleList transition_target(maps->length()); |
| 5604 // Collect possible transition targets. | 5619 // Collect possible transition targets. |
| 5605 MapHandleList possible_transitioned_maps(maps->length()); | 5620 MapHandleList possible_transitioned_maps(maps->length()); |
| 5606 for (int i = 0; i < maps->length(); ++i) { | 5621 for (int i = 0; i < maps->length(); ++i) { |
| 5607 Handle<Map> map = maps->at(i); | 5622 Handle<Map> map = maps->at(i); |
| 5608 ElementsKind elements_kind = map->elements_kind(); | 5623 ElementsKind elements_kind = map->elements_kind(); |
| 5609 if (IsFastElementsKind(elements_kind) && | 5624 if (IsFastElementsKind(elements_kind) && |
| 5610 elements_kind != GetInitialFastElementsKind()) { | 5625 elements_kind != GetInitialFastElementsKind()) { |
| 5611 possible_transitioned_maps.Add(map); | 5626 possible_transitioned_maps.Add(map); |
| 5612 } | 5627 } |
| 5613 } | 5628 } |
| 5614 // Get transition target for each map (NULL == no transition). | 5629 // Get transition target for each map (NULL == no transition). |
| 5615 for (int i = 0; i < maps->length(); ++i) { | 5630 for (int i = 0; i < maps->length(); ++i) { |
| 5616 Handle<Map> map = maps->at(i); | 5631 Handle<Map> map = maps->at(i); |
| 5617 Handle<Map> transitioned_map = | 5632 Handle<Map> transitioned_map = |
| 5618 map->FindTransitionedMap(&possible_transitioned_maps); | 5633 map->FindTransitionedMap(&possible_transitioned_maps); |
| 5619 transition_target.Add(transitioned_map); | 5634 transition_target.Add(transitioned_map); |
| 5620 } | 5635 } |
| 5621 | 5636 |
| 5622 int num_untransitionable_maps = 0; | 5637 MapHandleList untransitionable_maps(maps->length()); |
| 5623 Handle<Map> untransitionable_map; | |
| 5624 HTransitionElementsKind* transition = NULL; | 5638 HTransitionElementsKind* transition = NULL; |
| 5625 for (int i = 0; i < maps->length(); ++i) { | 5639 for (int i = 0; i < maps->length(); ++i) { |
| 5626 Handle<Map> map = maps->at(i); | 5640 Handle<Map> map = maps->at(i); |
| 5627 ASSERT(map->IsMap()); | 5641 ASSERT(map->IsMap()); |
| 5628 if (!transition_target.at(i).is_null()) { | 5642 if (!transition_target.at(i).is_null()) { |
| 5629 ASSERT(Map::IsValidElementsTransition( | 5643 ASSERT(Map::IsValidElementsTransition( |
| 5630 map->elements_kind(), | 5644 map->elements_kind(), |
| 5631 transition_target.at(i)->elements_kind())); | 5645 transition_target.at(i)->elements_kind())); |
| 5632 HValue* context = environment()->LookupContext(); | 5646 HValue* context = environment()->LookupContext(); |
| 5633 transition = Add<HTransitionElementsKind>(context, object, map, | 5647 transition = Add<HTransitionElementsKind>(context, object, map, |
| 5634 transition_target.at(i)); | 5648 transition_target.at(i)); |
| 5635 } else { | 5649 } else { |
| 5636 type_todo[map->elements_kind()] = true; | 5650 untransitionable_maps.Add(map); |
| 5637 if (IsExternalArrayElementsKind(map->elements_kind())) { | |
| 5638 todo_external_array = true; | |
| 5639 } | |
| 5640 num_untransitionable_maps++; | |
| 5641 untransitionable_map = map; | |
| 5642 } | 5651 } |
| 5643 } | 5652 } |
| 5644 | 5653 |
| 5645 // If only one map is left after transitioning, handle this case | 5654 // If only one map is left after transitioning, handle this case |
| 5646 // monomorphically. | 5655 // monomorphically. |
| 5647 ASSERT(num_untransitionable_maps >= 1); | 5656 ASSERT(untransitionable_maps.length() >= 1); |
| 5648 if (num_untransitionable_maps == 1) { | 5657 if (untransitionable_maps.length() == 1) { |
| 5658 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
| 5649 HInstruction* instr = NULL; | 5659 HInstruction* instr = NULL; |
| 5650 if (untransitionable_map->has_slow_elements_kind()) { | 5660 if (untransitionable_map->has_slow_elements_kind()) { |
| 5651 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 5661 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
| 5652 : BuildLoadKeyedGeneric(object, key)); | 5662 : BuildLoadKeyedGeneric(object, key)); |
| 5653 } else { | 5663 } else { |
| 5654 instr = BuildMonomorphicElementAccess( | 5664 instr = BuildMonomorphicElementAccess( |
| 5655 object, key, val, transition, untransitionable_map, is_store, | 5665 object, key, val, transition, untransitionable_map, is_store, |
| 5656 store_mode); | 5666 store_mode); |
| 5657 } | 5667 } |
| 5658 *has_side_effects |= instr->HasObservableSideEffects(); | 5668 *has_side_effects |= instr->HasObservableSideEffects(); |
| 5659 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5669 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5660 return is_store ? NULL : instr; | 5670 return is_store ? NULL : instr; |
| 5661 } | 5671 } |
| 5662 | 5672 |
| 5663 HInstruction* checkspec = | 5673 HInstruction* checkspec = |
| 5664 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 5674 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
| 5665 HBasicBlock* join = graph()->CreateBasicBlock(); | 5675 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 5666 | 5676 |
| 5667 HInstruction* elements_kind_instr = Add<HElementsKind>(object); | |
| 5668 HInstruction* elements = AddLoadElements(object, checkspec); | 5677 HInstruction* elements = AddLoadElements(object, checkspec); |
| 5669 HLoadExternalArrayPointer* external_elements = NULL; | |
| 5670 HInstruction* checked_key = NULL; | |
| 5671 | 5678 |
| 5672 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds | 5679 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 5673 // are handled before external arrays. | 5680 Handle<Map> map = untransitionable_maps[i]; |
| 5674 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5681 ElementsKind elements_kind = map->elements_kind(); |
| 5675 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5682 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 5676 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5683 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 5677 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); | 5684 HCompareMap* mapcompare = |
| 5685 new(zone()) HCompareMap(object, map, this_map, other_map); |
| 5686 current_block()->Finish(mapcompare); |
| 5678 | 5687 |
| 5679 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; | 5688 set_current_block(this_map); |
| 5680 elements_kind <= LAST_ELEMENTS_KIND; | 5689 HInstruction* checked_key = NULL; |
| 5681 elements_kind = ElementsKind(elements_kind + 1)) { | 5690 HInstruction* access = NULL; |
| 5682 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some | 5691 if (IsFastElementsKind(elements_kind)) { |
| 5683 // code that's executed for all external array cases. | 5692 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
| 5684 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 5693 AddInstruction(HCheckMaps::New( |
| 5685 LAST_ELEMENTS_KIND); | 5694 elements, isolate()->factory()->fixed_array_map(), |
| 5686 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 5695 zone(), mapcompare)); |
| 5687 && todo_external_array) { | 5696 } |
| 5697 if (map->IsJSArray()) { |
| 5698 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), |
| 5699 mapcompare, Representation::Smi()); |
| 5700 length->set_type(HType::Smi()); |
| 5701 checked_key = Add<HBoundsCheck>(key, length); |
| 5702 } else { |
| 5703 HInstruction* length = AddLoadFixedArrayLength(elements); |
| 5704 checked_key = Add<HBoundsCheck>(key, length); |
| 5705 } |
| 5706 access = AddFastElementAccess( |
| 5707 elements, checked_key, val, mapcompare, |
| 5708 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 5709 } else if (IsDictionaryElementsKind(elements_kind)) { |
| 5710 if (is_store) { |
| 5711 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
| 5712 } else { |
| 5713 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 5714 } |
| 5715 } else { |
| 5716 ASSERT(IsExternalArrayElementsKind(elements_kind)); |
| 5688 HInstruction* length = AddLoadFixedArrayLength(elements); | 5717 HInstruction* length = AddLoadFixedArrayLength(elements); |
| 5689 checked_key = Add<HBoundsCheck>(key, length); | 5718 checked_key = Add<HBoundsCheck>(key, length); |
| 5690 external_elements = Add<HLoadExternalArrayPointer>(elements); | 5719 HLoadExternalArrayPointer* external_elements = |
| 5720 Add<HLoadExternalArrayPointer>(elements); |
| 5721 access = AddExternalArrayElementAccess( |
| 5722 external_elements, checked_key, val, |
| 5723 mapcompare, elements_kind, is_store); |
| 5691 } | 5724 } |
| 5692 if (type_todo[elements_kind]) { | 5725 *has_side_effects |= access->HasObservableSideEffects(); |
| 5693 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 5726 // The caller will use has_side_effects and add a correct Simulate. |
| 5694 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 5727 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 5695 HCompareConstantEqAndBranch* elements_kind_branch = | 5728 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 5696 new(zone()) HCompareConstantEqAndBranch( | 5729 if (!is_store) { |
| 5697 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 5730 Push(access); |
| 5698 elements_kind_branch->SetSuccessorAt(0, if_true); | |
| 5699 elements_kind_branch->SetSuccessorAt(1, if_false); | |
| 5700 current_block()->Finish(elements_kind_branch); | |
| 5701 | |
| 5702 set_current_block(if_true); | |
| 5703 HInstruction* access; | |
| 5704 if (IsFastElementsKind(elements_kind)) { | |
| 5705 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | |
| 5706 AddInstruction(HCheckMaps::New( | |
| 5707 elements, isolate()->factory()->fixed_array_map(), | |
| 5708 zone(), elements_kind_branch)); | |
| 5709 } | |
| 5710 // TODO(jkummerow): The need for these two blocks could be avoided | |
| 5711 // in one of two ways: | |
| 5712 // (1) Introduce ElementsKinds for JSArrays that are distinct from | |
| 5713 // those for fast objects. | |
| 5714 // (2) Put the common instructions into a third "join" block. This | |
| 5715 // requires additional AST IDs that we can deopt to from inside | |
| 5716 // that join block. They must be added to the Property class (when | |
| 5717 // it's a keyed property) and registered in the full codegen. | |
| 5718 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | |
| 5719 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | |
| 5720 HHasInstanceTypeAndBranch* typecheck = | |
| 5721 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | |
| 5722 typecheck->SetSuccessorAt(0, if_jsarray); | |
| 5723 typecheck->SetSuccessorAt(1, if_fastobject); | |
| 5724 current_block()->Finish(typecheck); | |
| 5725 | |
| 5726 set_current_block(if_jsarray); | |
| 5727 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | |
| 5728 typecheck, Representation::Smi()); | |
| 5729 length->set_type(HType::Smi()); | |
| 5730 | |
| 5731 checked_key = Add<HBoundsCheck>(key, length); | |
| 5732 access = AddInstruction(BuildFastElementAccess( | |
| 5733 elements, checked_key, val, elements_kind_branch, | |
| 5734 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | |
| 5735 if (!is_store) { | |
| 5736 Push(access); | |
| 5737 } | |
| 5738 | |
| 5739 *has_side_effects |= access->HasObservableSideEffects(); | |
| 5740 // The caller will use has_side_effects and add correct Simulate. | |
| 5741 access->SetFlag(HValue::kHasNoObservableSideEffects); | |
| 5742 if (position != -1) { | |
| 5743 access->set_position(position); | |
| 5744 } | |
| 5745 if_jsarray->GotoNoSimulate(join); | |
| 5746 | |
| 5747 set_current_block(if_fastobject); | |
| 5748 length = AddLoadFixedArrayLength(elements); | |
| 5749 checked_key = Add<HBoundsCheck>(key, length); | |
| 5750 access = AddInstruction(BuildFastElementAccess( | |
| 5751 elements, checked_key, val, elements_kind_branch, | |
| 5752 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | |
| 5753 } else if (elements_kind == DICTIONARY_ELEMENTS) { | |
| 5754 if (is_store) { | |
| 5755 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | |
| 5756 } else { | |
| 5757 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | |
| 5758 } | |
| 5759 } else { // External array elements. | |
| 5760 access = AddInstruction(BuildExternalArrayElementAccess( | |
| 5761 external_elements, checked_key, val, | |
| 5762 elements_kind_branch, elements_kind, is_store)); | |
| 5763 } | |
| 5764 *has_side_effects |= access->HasObservableSideEffects(); | |
| 5765 // The caller will use has_side_effects and add correct Simulate. | |
| 5766 access->SetFlag(HValue::kHasNoObservableSideEffects); | |
| 5767 if (position != RelocInfo::kNoPosition) access->set_position(position); | |
| 5768 if (!is_store) { | |
| 5769 Push(access); | |
| 5770 } | |
| 5771 current_block()->GotoNoSimulate(join); | |
| 5772 set_current_block(if_false); | |
| 5773 } | 5731 } |
| 5732 current_block()->GotoNoSimulate(join); |
| 5733 set_current_block(other_map); |
| 5774 } | 5734 } |
| 5775 | 5735 |
| 5776 // Deopt if none of the cases matched. | 5736 // Deopt if none of the cases matched. |
| 5777 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 5737 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 5778 set_current_block(join); | 5738 set_current_block(join); |
| 5779 return is_store ? NULL : Pop(); | 5739 return is_store ? NULL : Pop(); |
| 5780 } | 5740 } |
| 5781 | 5741 |
| 5782 | 5742 |
| 5783 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5743 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6335 CompilationInfo* outer_info = current_info(); | 6295 CompilationInfo* outer_info = current_info(); |
| 6336 if (target->context() != outer_info->closure()->context() || | 6296 if (target->context() != outer_info->closure()->context() || |
| 6337 outer_info->scope()->contains_with() || | 6297 outer_info->scope()->contains_with() || |
| 6338 outer_info->scope()->num_heap_slots() > 0) { | 6298 outer_info->scope()->num_heap_slots() > 0) { |
| 6339 TraceInline(target, caller, "target requires context change"); | 6299 TraceInline(target, caller, "target requires context change"); |
| 6340 return false; | 6300 return false; |
| 6341 } | 6301 } |
| 6342 #endif | 6302 #endif |
| 6343 | 6303 |
| 6344 | 6304 |
| 6345 // Don't inline deeper than kMaxInliningLevels calls. | 6305 // Don't inline deeper than the maximum number of inlining levels. |
| 6346 HEnvironment* env = environment(); | 6306 HEnvironment* env = environment(); |
| 6347 int current_level = 1; | 6307 int current_level = 1; |
| 6348 while (env->outer() != NULL) { | 6308 while (env->outer() != NULL) { |
| 6349 if (current_level == Compiler::kMaxInliningLevels) { | 6309 if (current_level == FLAG_max_inlining_levels) { |
| 6350 TraceInline(target, caller, "inline depth limit reached"); | 6310 TraceInline(target, caller, "inline depth limit reached"); |
| 6351 return false; | 6311 return false; |
| 6352 } | 6312 } |
| 6353 if (env->outer()->frame_type() == JS_FUNCTION) { | 6313 if (env->outer()->frame_type() == JS_FUNCTION) { |
| 6354 current_level++; | 6314 current_level++; |
| 6355 } | 6315 } |
| 6356 env = env->outer(); | 6316 env = env->outer(); |
| 6357 } | 6317 } |
| 6358 | 6318 |
| 6359 // Don't inline recursive functions. | 6319 // Don't inline recursive functions. |
| (...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7393 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 7353 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 7394 ASSERT(!HasStackOverflow()); | 7354 ASSERT(!HasStackOverflow()); |
| 7395 ASSERT(current_block() != NULL); | 7355 ASSERT(current_block() != NULL); |
| 7396 ASSERT(current_block()->HasPredecessor()); | 7356 ASSERT(current_block()->HasPredecessor()); |
| 7397 if (expr->is_jsruntime()) { | 7357 if (expr->is_jsruntime()) { |
| 7398 return Bailout("call to a JavaScript runtime function"); | 7358 return Bailout("call to a JavaScript runtime function"); |
| 7399 } | 7359 } |
| 7400 | 7360 |
| 7401 const Runtime::Function* function = expr->function(); | 7361 const Runtime::Function* function = expr->function(); |
| 7402 ASSERT(function != NULL); | 7362 ASSERT(function != NULL); |
| 7403 | |
| 7404 if (static_cast<int>(function->function_id) | |
| 7405 == static_cast<int>(Runtime::kNeverOptimize) | |
| 7406 && expr->arguments()->length() == 0) { | |
| 7407 // %NeverOptimize() without arguments marks the caller as never optimize. | |
| 7408 return Bailout("function marked itself as never optimize"); | |
| 7409 } | |
| 7410 | |
| 7411 if (function->intrinsic_type == Runtime::INLINE) { | 7363 if (function->intrinsic_type == Runtime::INLINE) { |
| 7412 ASSERT(expr->name()->length() > 0); | 7364 ASSERT(expr->name()->length() > 0); |
| 7413 ASSERT(expr->name()->Get(0) == '_'); | 7365 ASSERT(expr->name()->Get(0) == '_'); |
| 7414 // Call to an inline function. | 7366 // Call to an inline function. |
| 7415 int lookup_index = static_cast<int>(function->function_id) - | 7367 int lookup_index = static_cast<int>(function->function_id) - |
| 7416 static_cast<int>(Runtime::kFirstInlineFunction); | 7368 static_cast<int>(Runtime::kFirstInlineFunction); |
| 7417 ASSERT(lookup_index >= 0); | 7369 ASSERT(lookup_index >= 0); |
| 7418 ASSERT(static_cast<size_t>(lookup_index) < | 7370 ASSERT(static_cast<size_t>(lookup_index) < |
| 7419 ARRAY_SIZE(kInlineFunctionGenerators)); | 7371 ARRAY_SIZE(kInlineFunctionGenerators)); |
| 7420 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 7372 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7715 } else if (types != NULL && types->length() > 1) { | 7667 } else if (types != NULL && types->length() > 1) { |
| 7716 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7668 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
| 7717 } | 7669 } |
| 7718 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7670 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
| 7719 PushAndAdd(load); | 7671 PushAndAdd(load); |
| 7720 if (load->HasObservableSideEffects()) { | 7672 if (load->HasObservableSideEffects()) { |
| 7721 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7673 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 7722 } | 7674 } |
| 7723 | 7675 |
| 7724 after = BuildIncrement(returns_original_input, expr); | 7676 after = BuildIncrement(returns_original_input, expr); |
| 7725 | 7677 HValue* result = returns_original_input ? Pop() : after; |
| 7726 HValue* result = returns_original_input ? Pop() : NULL; | |
| 7727 | 7678 |
| 7728 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7679 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 7729 expr->AssignmentId(), prop, object, after, result); | 7680 expr->AssignmentId(), prop, object, after, result); |
| 7730 } else { | 7681 } else { |
| 7731 // Keyed property. | 7682 // Keyed property. |
| 7732 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7683 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7733 | 7684 |
| 7734 CHECK_ALIVE(VisitForValue(prop->obj())); | 7685 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7735 CHECK_ALIVE(VisitForValue(prop->key())); | 7686 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7736 HValue* obj = environment()->ExpressionStackAt(1); | 7687 HValue* obj = environment()->ExpressionStackAt(1); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8085 CHECK_ALIVE(VisitForValue(expr->right())); | 8036 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8086 HValue* right = Pop(); | 8037 HValue* right = Pop(); |
| 8087 HValue* left = Pop(); | 8038 HValue* left = Pop(); |
| 8088 HInstruction* instr = BuildBinaryOperation(expr, left, right); | 8039 HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| 8089 instr->set_position(expr->position()); | 8040 instr->set_position(expr->position()); |
| 8090 return ast_context()->ReturnInstruction(instr, expr->id()); | 8041 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 8091 } | 8042 } |
| 8092 | 8043 |
| 8093 | 8044 |
| 8094 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 8045 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 8095 HTypeof* typeof_expr, | 8046 Expression* sub_expr, |
| 8096 Handle<String> check) { | 8047 Handle<String> check) { |
| 8097 // Note: The HTypeof itself is removed during canonicalization, if possible. | 8048 CHECK_ALIVE(VisitForTypeOf(sub_expr)); |
| 8098 HValue* value = typeof_expr->value(); | 8049 HValue* value = Pop(); |
| 8099 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 8050 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 8100 instr->set_position(expr->position()); | 8051 instr->set_position(expr->position()); |
| 8101 return ast_context()->ReturnControl(instr, expr->id()); | 8052 return ast_context()->ReturnControl(instr, expr->id()); |
| 8102 } | 8053 } |
| 8103 | 8054 |
| 8104 | 8055 |
| 8105 static bool MatchLiteralCompareNil(HValue* left, | |
| 8106 Token::Value op, | |
| 8107 HValue* right, | |
| 8108 Handle<Object> nil, | |
| 8109 HValue** expr) { | |
| 8110 if (left->IsConstant() && | |
| 8111 HConstant::cast(left)->handle().is_identical_to(nil) && | |
| 8112 Token::IsEqualityOp(op)) { | |
| 8113 *expr = right; | |
| 8114 return true; | |
| 8115 } | |
| 8116 return false; | |
| 8117 } | |
| 8118 | |
| 8119 | |
| 8120 static bool MatchLiteralCompareTypeof(HValue* left, | |
| 8121 Token::Value op, | |
| 8122 HValue* right, | |
| 8123 HTypeof** typeof_expr, | |
| 8124 Handle<String>* check) { | |
| 8125 if (left->IsTypeof() && | |
| 8126 Token::IsEqualityOp(op) && | |
| 8127 right->IsConstant() && | |
| 8128 HConstant::cast(right)->handle()->IsString()) { | |
| 8129 *typeof_expr = HTypeof::cast(left); | |
| 8130 *check = Handle<String>::cast(HConstant::cast(right)->handle()); | |
| 8131 return true; | |
| 8132 } | |
| 8133 return false; | |
| 8134 } | |
| 8135 | |
| 8136 | |
| 8137 static bool IsLiteralCompareTypeof(HValue* left, | |
| 8138 Token::Value op, | |
| 8139 HValue* right, | |
| 8140 HTypeof** typeof_expr, | |
| 8141 Handle<String>* check) { | |
| 8142 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || | |
| 8143 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); | |
| 8144 } | |
| 8145 | |
| 8146 | |
| 8147 static bool IsLiteralCompareNil(HValue* left, | |
| 8148 Token::Value op, | |
| 8149 HValue* right, | |
| 8150 Handle<Object> nil, | |
| 8151 HValue** expr) { | |
| 8152 return MatchLiteralCompareNil(left, op, right, nil, expr) || | |
| 8153 MatchLiteralCompareNil(right, op, left, nil, expr); | |
| 8154 } | |
| 8155 | |
| 8156 | |
| 8157 static bool IsLiteralCompareBool(HValue* left, | 8056 static bool IsLiteralCompareBool(HValue* left, |
| 8158 Token::Value op, | 8057 Token::Value op, |
| 8159 HValue* right) { | 8058 HValue* right) { |
| 8160 return op == Token::EQ_STRICT && | 8059 return op == Token::EQ_STRICT && |
| 8161 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 8060 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
| 8162 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 8061 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
| 8163 } | 8062 } |
| 8164 | 8063 |
| 8165 | 8064 |
| 8166 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 8065 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 8167 ASSERT(!HasStackOverflow()); | 8066 ASSERT(!HasStackOverflow()); |
| 8168 ASSERT(current_block() != NULL); | 8067 ASSERT(current_block() != NULL); |
| 8169 ASSERT(current_block()->HasPredecessor()); | 8068 ASSERT(current_block()->HasPredecessor()); |
| 8069 |
| 8070 // Check for a few fast cases. The AST visiting behavior must be in sync |
| 8071 // with the full codegen: We don't push both left and right values onto |
| 8072 // the expression stack when one side is a special-case literal. |
| 8073 Expression* sub_expr = NULL; |
| 8074 Handle<String> check; |
| 8075 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
| 8076 return HandleLiteralCompareTypeof(expr, sub_expr, check); |
| 8077 } |
| 8078 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { |
| 8079 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); |
| 8080 } |
| 8081 if (expr->IsLiteralCompareNull(&sub_expr)) { |
| 8082 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); |
| 8083 } |
| 8084 |
| 8170 if (IsClassOfTest(expr)) { | 8085 if (IsClassOfTest(expr)) { |
| 8171 CallRuntime* call = expr->left()->AsCallRuntime(); | 8086 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 8172 ASSERT(call->arguments()->length() == 1); | 8087 ASSERT(call->arguments()->length() == 1); |
| 8173 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8088 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8174 HValue* value = Pop(); | 8089 HValue* value = Pop(); |
| 8175 Literal* literal = expr->right()->AsLiteral(); | 8090 Literal* literal = expr->right()->AsLiteral(); |
| 8176 Handle<String> rhs = Handle<String>::cast(literal->value()); | 8091 Handle<String> rhs = Handle<String>::cast(literal->value()); |
| 8177 HClassOfTestAndBranch* instr = | 8092 HClassOfTestAndBranch* instr = |
| 8178 new(zone()) HClassOfTestAndBranch(value, rhs); | 8093 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 8179 instr->set_position(expr->position()); | 8094 instr->set_position(expr->position()); |
| 8180 return ast_context()->ReturnControl(instr, expr->id()); | 8095 return ast_context()->ReturnControl(instr, expr->id()); |
| 8181 } | 8096 } |
| 8182 | 8097 |
| 8183 Handle<Type> left_type = expr->left()->bounds().lower; | 8098 Handle<Type> left_type = expr->left()->bounds().lower; |
| 8184 Handle<Type> right_type = expr->right()->bounds().lower; | 8099 Handle<Type> right_type = expr->right()->bounds().lower; |
| 8185 Handle<Type> combined_type = expr->combined_type(); | 8100 Handle<Type> combined_type = expr->combined_type(); |
| 8186 Representation combined_rep = Representation::FromType(combined_type); | 8101 Representation combined_rep = Representation::FromType(combined_type); |
| 8187 Representation left_rep = Representation::FromType(left_type); | 8102 Representation left_rep = Representation::FromType(left_type); |
| 8188 Representation right_rep = Representation::FromType(right_type); | 8103 Representation right_rep = Representation::FromType(right_type); |
| 8189 | 8104 |
| 8190 CHECK_ALIVE(VisitForValue(expr->left())); | 8105 CHECK_ALIVE(VisitForValue(expr->left())); |
| 8191 CHECK_ALIVE(VisitForValue(expr->right())); | 8106 CHECK_ALIVE(VisitForValue(expr->right())); |
| 8192 | 8107 |
| 8193 HValue* context = environment()->LookupContext(); | 8108 HValue* context = environment()->LookupContext(); |
| 8194 HValue* right = Pop(); | 8109 HValue* right = Pop(); |
| 8195 HValue* left = Pop(); | 8110 HValue* left = Pop(); |
| 8196 Token::Value op = expr->op(); | 8111 Token::Value op = expr->op(); |
| 8197 | 8112 |
| 8198 HTypeof* typeof_expr = NULL; | |
| 8199 Handle<String> check; | |
| 8200 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { | |
| 8201 return HandleLiteralCompareTypeof(expr, typeof_expr, check); | |
| 8202 } | |
| 8203 HValue* sub_expr = NULL; | |
| 8204 Factory* f = isolate()->factory(); | |
| 8205 if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) { | |
| 8206 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); | |
| 8207 } | |
| 8208 if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { | |
| 8209 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); | |
| 8210 } | |
| 8211 if (IsLiteralCompareBool(left, op, right)) { | 8113 if (IsLiteralCompareBool(left, op, right)) { |
| 8212 HCompareObjectEqAndBranch* result = | 8114 HCompareObjectEqAndBranch* result = |
| 8213 new(zone()) HCompareObjectEqAndBranch(left, right); | 8115 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 8214 result->set_position(expr->position()); | 8116 result->set_position(expr->position()); |
| 8215 return ast_context()->ReturnControl(result, expr->id()); | 8117 return ast_context()->ReturnControl(result, expr->id()); |
| 8216 } | 8118 } |
| 8217 | 8119 |
| 8218 if (op == Token::INSTANCEOF) { | 8120 if (op == Token::INSTANCEOF) { |
| 8219 // Check to see if the rhs of the instanceof is a global function not | 8121 // Check to see if the rhs of the instanceof is a global function not |
| 8220 // residing in new space. If it is we assume that the function will stay the | 8122 // residing in new space. If it is we assume that the function will stay the |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8327 new(zone()) HCompareNumericAndBranch(left, right, op); | 8229 new(zone()) HCompareNumericAndBranch(left, right, op); |
| 8328 result->set_observed_input_representation(left_rep, right_rep); | 8230 result->set_observed_input_representation(left_rep, right_rep); |
| 8329 result->set_position(expr->position()); | 8231 result->set_position(expr->position()); |
| 8330 return ast_context()->ReturnControl(result, expr->id()); | 8232 return ast_context()->ReturnControl(result, expr->id()); |
| 8331 } | 8233 } |
| 8332 } | 8234 } |
| 8333 } | 8235 } |
| 8334 | 8236 |
| 8335 | 8237 |
| 8336 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8238 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8337 HValue* value, | 8239 Expression* sub_expr, |
| 8338 NilValue nil) { | 8240 NilValue nil) { |
| 8339 ASSERT(!HasStackOverflow()); | 8241 ASSERT(!HasStackOverflow()); |
| 8340 ASSERT(current_block() != NULL); | 8242 ASSERT(current_block() != NULL); |
| 8341 ASSERT(current_block()->HasPredecessor()); | 8243 ASSERT(current_block()->HasPredecessor()); |
| 8342 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 8244 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 8245 CHECK_ALIVE(VisitForValue(sub_expr)); |
| 8246 HValue* value = Pop(); |
| 8343 HIfContinuation continuation; | 8247 HIfContinuation continuation; |
| 8344 if (expr->op() == Token::EQ_STRICT) { | 8248 if (expr->op() == Token::EQ_STRICT) { |
| 8345 IfBuilder if_nil(this); | 8249 IfBuilder if_nil(this); |
| 8346 if_nil.If<HCompareObjectEqAndBranch>( | 8250 if_nil.If<HCompareObjectEqAndBranch>( |
| 8347 value, (nil == kNullValue) ? graph()->GetConstantNull() | 8251 value, (nil == kNullValue) ? graph()->GetConstantNull() |
| 8348 : graph()->GetConstantUndefined()); | 8252 : graph()->GetConstantUndefined()); |
| 8349 if_nil.Then(); | 8253 if_nil.Then(); |
| 8350 if_nil.Else(); | 8254 if_nil.Else(); |
| 8351 if_nil.CaptureContinuation(&continuation); | 8255 if_nil.CaptureContinuation(&continuation); |
| 8352 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8256 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 8376 Handle<JSObject> original_boilerplate_object, | 8280 Handle<JSObject> original_boilerplate_object, |
| 8377 Handle<Object> allocation_site, | 8281 Handle<Object> allocation_site, |
| 8378 int data_size, | 8282 int data_size, |
| 8379 int pointer_size, | 8283 int pointer_size, |
| 8380 AllocationSiteMode mode) { | 8284 AllocationSiteMode mode) { |
| 8381 NoObservableSideEffectsScope no_effects(this); | 8285 NoObservableSideEffectsScope no_effects(this); |
| 8382 | 8286 |
| 8383 HInstruction* target = NULL; | 8287 HInstruction* target = NULL; |
| 8384 HInstruction* data_target = NULL; | 8288 HInstruction* data_target = NULL; |
| 8385 | 8289 |
| 8386 HAllocate::Flags flags = HAllocate::DefaultFlags(); | 8290 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 8387 | 8291 |
| 8388 if (isolate()->heap()->ShouldGloballyPretenure()) { | 8292 if (isolate()->heap()->ShouldGloballyPretenure()) { |
| 8389 if (data_size != 0) { | 8293 if (data_size != 0) { |
| 8390 HAllocate::Flags data_flags = | 8294 HAllocate::Flags data_flags = |
| 8391 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | | 8295 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags(kind) | |
| 8392 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 8296 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
| 8393 HValue* size_in_bytes = Add<HConstant>(data_size); | 8297 HValue* size_in_bytes = Add<HConstant>(data_size); |
| 8394 data_target = Add<HAllocate>(context, size_in_bytes, | 8298 data_target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), |
| 8395 HType::JSObject(), data_flags); | 8299 data_flags); |
| 8396 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | 8300 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); |
| 8397 AddStoreMapConstant(data_target, free_space_map); | 8301 AddStoreMapConstant(data_target, free_space_map); |
| 8398 HObjectAccess access = | 8302 HObjectAccess access = |
| 8399 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | 8303 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
| 8400 AddStore(data_target, access, size_in_bytes); | 8304 AddStore(data_target, access, size_in_bytes); |
| 8401 } | 8305 } |
| 8402 if (pointer_size != 0) { | 8306 if (pointer_size != 0) { |
| 8403 flags = static_cast<HAllocate::Flags>( | 8307 HAllocate::Flags pointer_flags = |
| 8404 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 8308 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | |
| 8309 HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 8405 HValue* size_in_bytes = Add<HConstant>(pointer_size); | 8310 HValue* size_in_bytes = Add<HConstant>(pointer_size); |
| 8406 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); | 8311 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), |
| 8312 pointer_flags); |
| 8407 } | 8313 } |
| 8408 } else { | 8314 } else { |
| 8315 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); |
| 8409 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); | 8316 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); |
| 8410 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); | 8317 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); |
| 8411 } | 8318 } |
| 8412 | 8319 |
| 8413 int offset = 0; | 8320 int offset = 0; |
| 8414 int data_offset = 0; | 8321 int data_offset = 0; |
| 8415 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, | 8322 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, |
| 8416 allocation_site, target, &offset, data_target, | 8323 allocation_site, target, &offset, data_target, |
| 8417 &data_offset, mode); | 8324 &data_offset, mode); |
| 8418 return target; | 8325 return target; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8482 if (boilerplate_object->map()->NumberOfFields() != 0) { | 8389 if (boilerplate_object->map()->NumberOfFields() != 0) { |
| 8483 HValue* object_properties = | 8390 HValue* object_properties = |
| 8484 Add<HInnerAllocatedObject>(target, object_offset); | 8391 Add<HInnerAllocatedObject>(target, object_offset); |
| 8485 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | 8392 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, |
| 8486 object_properties, target, offset, data_target, data_offset); | 8393 object_properties, target, offset, data_target, data_offset); |
| 8487 } | 8394 } |
| 8488 | 8395 |
| 8489 // Create allocation site info. | 8396 // Create allocation site info. |
| 8490 if (mode == TRACK_ALLOCATION_SITE && | 8397 if (mode == TRACK_ALLOCATION_SITE && |
| 8491 boilerplate_object->map()->CanTrackAllocationSite()) { | 8398 boilerplate_object->map()->CanTrackAllocationSite()) { |
| 8492 elements_offset += AllocationSiteInfo::kSize; | 8399 elements_offset += AllocationMemento::kSize; |
| 8493 *offset += AllocationSiteInfo::kSize; | 8400 *offset += AllocationMemento::kSize; |
| 8494 BuildCreateAllocationSiteInfo(target, JSArray::kSize, allocation_site); | 8401 BuildCreateAllocationMemento(target, JSArray::kSize, allocation_site); |
| 8495 } | 8402 } |
| 8496 } | 8403 } |
| 8497 | 8404 |
| 8498 | 8405 |
| 8499 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 8406 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 8500 Handle<JSObject> boilerplate_object, | 8407 Handle<JSObject> boilerplate_object, |
| 8501 HInstruction* target, | 8408 HInstruction* target, |
| 8502 HInstruction* data_target, | 8409 HInstruction* data_target, |
| 8503 int object_offset, | 8410 int object_offset, |
| 8504 int elements_offset, | 8411 int elements_offset, |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9157 HValue* context = environment()->LookupContext(); | 9064 HValue* context = environment()->LookupContext(); |
| 9158 HGlobalObject* global_object = Add<HGlobalObject>(context); | 9065 HGlobalObject* global_object = Add<HGlobalObject>(context); |
| 9159 HRandom* result = new(zone()) HRandom(global_object); | 9066 HRandom* result = new(zone()) HRandom(global_object); |
| 9160 return ast_context()->ReturnInstruction(result, call->id()); | 9067 return ast_context()->ReturnInstruction(result, call->id()); |
| 9161 } | 9068 } |
| 9162 | 9069 |
| 9163 | 9070 |
| 9164 // Fast support for StringAdd. | 9071 // Fast support for StringAdd. |
| 9165 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9072 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9166 ASSERT_EQ(2, call->arguments()->length()); | 9073 ASSERT_EQ(2, call->arguments()->length()); |
| 9167 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9074 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9075 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9076 HValue* right = Pop(); |
| 9077 HValue* left = Pop(); |
| 9168 HValue* context = environment()->LookupContext(); | 9078 HValue* context = environment()->LookupContext(); |
| 9169 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 9079 HInstruction* result = HStringAdd::New( |
| 9170 Drop(2); | 9080 zone(), context, left, right, STRING_ADD_CHECK_BOTH); |
| 9171 return ast_context()->ReturnInstruction(result, call->id()); | 9081 return ast_context()->ReturnInstruction(result, call->id()); |
| 9172 } | 9082 } |
| 9173 | 9083 |
| 9174 | 9084 |
| 9175 // Fast support for SubString. | 9085 // Fast support for SubString. |
| 9176 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9086 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9177 ASSERT_EQ(3, call->arguments()->length()); | 9087 ASSERT_EQ(3, call->arguments()->length()); |
| 9178 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9088 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9179 HValue* context = environment()->LookupContext(); | 9089 HValue* context = environment()->LookupContext(); |
| 9180 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 9090 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9996 if (ShouldProduceTraceOutput()) { | 9906 if (ShouldProduceTraceOutput()) { |
| 9997 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9907 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9998 } | 9908 } |
| 9999 | 9909 |
| 10000 #ifdef DEBUG | 9910 #ifdef DEBUG |
| 10001 graph_->Verify(false); // No full verify. | 9911 graph_->Verify(false); // No full verify. |
| 10002 #endif | 9912 #endif |
| 10003 } | 9913 } |
| 10004 | 9914 |
| 10005 } } // namespace v8::internal | 9915 } } // namespace v8::internal |
| OLD | NEW |