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 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
602 } | 602 } |
603 } | 603 } |
604 } | 604 } |
605 | 605 |
606 #endif | 606 #endif |
607 | 607 |
608 | 608 |
609 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, | 609 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, |
610 int32_t value) { | 610 int32_t value) { |
611 if (!pointer->is_set()) { | 611 if (!pointer->is_set()) { |
612 HConstant* constant = new(zone()) HConstant(value); | 612 HConstant* constant = HConstant::New(zone(), NULL, value); |
613 constant->InsertAfter(GetConstantUndefined()); | 613 constant->InsertAfter(GetConstantUndefined()); |
614 pointer->set(constant); | 614 pointer->set(constant); |
615 } | 615 } |
616 return pointer->get(); | 616 return pointer->get(); |
617 } | 617 } |
618 | 618 |
619 | 619 |
620 HConstant* HGraph::GetConstant0() { | 620 HConstant* HGraph::GetConstant0() { |
621 return GetConstant(&constant_0_, 0); | 621 return GetConstant(&constant_0_, 0); |
622 } | 622 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 deopt_else_ = true; | 828 deopt_else_ = true; |
829 } else { | 829 } else { |
830 deopt_then_ = true; | 830 deopt_then_ = true; |
831 } | 831 } |
832 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); | 832 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); |
833 } | 833 } |
834 | 834 |
835 | 835 |
836 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 836 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
837 HBasicBlock* block = builder_->current_block(); | 837 HBasicBlock* block = builder_->current_block(); |
838 HValue* context = builder_->environment()->LookupContext(); | |
839 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 838 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
840 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); | 839 block->FinishExit(builder_->NewAndCast<HReturn>(value, |
| 840 parameter_count)); |
841 builder_->set_current_block(NULL); | 841 builder_->set_current_block(NULL); |
842 if (did_else_) { | 842 if (did_else_) { |
843 first_false_block_ = NULL; | 843 first_false_block_ = NULL; |
844 } else { | 844 } else { |
845 first_true_block_ = NULL; | 845 first_true_block_ = NULL; |
846 } | 846 } |
847 } | 847 } |
848 | 848 |
849 | 849 |
850 void HGraphBuilder::IfBuilder::End() { | 850 void HGraphBuilder::IfBuilder::End() { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 984 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
985 } | 985 } |
986 return instr; | 986 return instr; |
987 } | 987 } |
988 | 988 |
989 | 989 |
990 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, | 990 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, |
991 HValue* context) { | 991 HValue* context) { |
992 if (FLAG_native_code_counters && counter->Enabled()) { | 992 if (FLAG_native_code_counters && counter->Enabled()) { |
993 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 993 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
994 HValue* old_value = AddLoad(reference, HObjectAccess::ForCounter(), NULL); | 994 HValue* old_value = Add<HLoadNamedField>(reference, |
995 HValue* new_value = AddInstruction( | 995 HObjectAccess::ForCounter()); |
996 HAdd::New(zone(), context, old_value, graph()->GetConstant1())); | 996 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
997 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 997 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
998 AddStore(reference, HObjectAccess::ForCounter(), new_value); | 998 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 999 new_value); |
999 } | 1000 } |
1000 } | 1001 } |
1001 | 1002 |
1002 | 1003 |
| 1004 void HGraphBuilder::AddSimulate(BailoutId id, |
| 1005 RemovableSimulate removable) { |
| 1006 ASSERT(current_block() != NULL); |
| 1007 ASSERT(no_side_effects_scope_count_ == 0); |
| 1008 current_block()->AddSimulate(id, removable); |
| 1009 } |
| 1010 |
| 1011 |
1003 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 1012 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
1004 HBasicBlock* b = graph()->CreateBasicBlock(); | 1013 HBasicBlock* b = graph()->CreateBasicBlock(); |
1005 b->SetInitialEnvironment(env); | 1014 b->SetInitialEnvironment(env); |
1006 return b; | 1015 return b; |
1007 } | 1016 } |
1008 | 1017 |
1009 | 1018 |
1010 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1019 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
1011 HBasicBlock* header = graph()->CreateBasicBlock(); | 1020 HBasicBlock* header = graph()->CreateBasicBlock(); |
1012 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1021 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 length_checker.Then(); | 1092 length_checker.Then(); |
1084 | 1093 |
1085 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1094 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
1086 | 1095 |
1087 IfBuilder capacity_checker(this); | 1096 IfBuilder capacity_checker(this); |
1088 | 1097 |
1089 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, | 1098 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, |
1090 Token::GTE); | 1099 Token::GTE); |
1091 capacity_checker.Then(); | 1100 capacity_checker.Then(); |
1092 | 1101 |
1093 HValue* context = environment()->LookupContext(); | 1102 HValue* context = environment()->context(); |
1094 | 1103 |
1095 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1104 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
1096 HValue* max_capacity = AddInstruction( | 1105 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); |
1097 HAdd::New(zone, context, current_capacity, max_gap)); | |
1098 IfBuilder key_checker(this); | 1106 IfBuilder key_checker(this); |
1099 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); | 1107 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); |
1100 key_checker.Then(); | 1108 key_checker.Then(); |
1101 key_checker.ElseDeopt(); | 1109 key_checker.ElseDeopt(); |
1102 key_checker.End(); | 1110 key_checker.End(); |
1103 | 1111 |
1104 HValue* new_capacity = BuildNewElementsCapacity(context, key); | 1112 HValue* new_capacity = BuildNewElementsCapacity(key); |
1105 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1113 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
1106 kind, kind, length, | 1114 kind, kind, length, |
1107 new_capacity); | 1115 new_capacity); |
1108 | 1116 |
1109 environment()->Push(new_elements); | 1117 environment()->Push(new_elements); |
1110 capacity_checker.Else(); | 1118 capacity_checker.Else(); |
1111 | 1119 |
1112 environment()->Push(elements); | 1120 environment()->Push(elements); |
1113 capacity_checker.End(); | 1121 capacity_checker.End(); |
1114 | 1122 |
1115 if (is_js_array) { | 1123 if (is_js_array) { |
1116 HValue* new_length = AddInstruction( | 1124 HValue* new_length = AddInstruction( |
1117 HAdd::New(zone, context, key, graph_->GetConstant1())); | 1125 HAdd::New(zone, context, key, graph_->GetConstant1())); |
1118 new_length->ClearFlag(HValue::kCanOverflow); | 1126 new_length->ClearFlag(HValue::kCanOverflow); |
1119 | 1127 |
1120 AddStore(object, HObjectAccess::ForArrayLength(kind), new_length); | 1128 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
| 1129 new_length); |
1121 } | 1130 } |
1122 | 1131 |
1123 length_checker.Else(); | 1132 length_checker.Else(); |
1124 Add<HBoundsCheck>(key, length); | 1133 Add<HBoundsCheck>(key, length); |
1125 | 1134 |
1126 environment()->Push(elements); | 1135 environment()->Push(elements); |
1127 length_checker.End(); | 1136 length_checker.End(); |
1128 | 1137 |
1129 return environment()->Pop(); | 1138 return environment()->Pop(); |
1130 } | 1139 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1167 IsFastHoleyElementsKind(to_kind)); | 1176 IsFastHoleyElementsKind(to_kind)); |
1168 | 1177 |
1169 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1178 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
1170 Add<HTrapAllocationMemento>(object); | 1179 Add<HTrapAllocationMemento>(object); |
1171 } | 1180 } |
1172 | 1181 |
1173 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1182 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
1174 HInstruction* elements = AddLoadElements(object); | 1183 HInstruction* elements = AddLoadElements(object); |
1175 | 1184 |
1176 HInstruction* empty_fixed_array = Add<HConstant>( | 1185 HInstruction* empty_fixed_array = Add<HConstant>( |
1177 isolate()->factory()->empty_fixed_array(), Representation::Tagged()); | 1186 isolate()->factory()->empty_fixed_array()); |
1178 | 1187 |
1179 IfBuilder if_builder(this); | 1188 IfBuilder if_builder(this); |
1180 | 1189 |
1181 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1190 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
1182 | 1191 |
1183 if_builder.Then(); | 1192 if_builder.Then(); |
1184 | 1193 |
1185 HInstruction* elements_length = AddLoadFixedArrayLength(elements); | 1194 HInstruction* elements_length = AddLoadFixedArrayLength(elements); |
1186 | 1195 |
1187 HInstruction* array_length = is_jsarray | 1196 HInstruction* array_length = is_jsarray |
1188 ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL) | 1197 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) |
1189 : elements_length; | 1198 : elements_length; |
1190 | 1199 |
1191 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1200 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1192 array_length, elements_length); | 1201 array_length, elements_length); |
1193 | 1202 |
1194 if_builder.End(); | 1203 if_builder.End(); |
1195 } | 1204 } |
1196 | 1205 |
1197 AddStore(object, HObjectAccess::ForMap(), map); | 1206 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
1198 } | 1207 } |
1199 | 1208 |
1200 | 1209 |
1201 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1210 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1202 HValue* object, | 1211 HValue* object, |
1203 HValue* key, | 1212 HValue* key, |
1204 HValue* val, | 1213 HValue* val, |
1205 HCheckMaps* mapcheck, | 1214 HCheckMaps* mapcheck, |
1206 bool is_js_array, | 1215 bool is_js_array, |
1207 ElementsKind elements_kind, | 1216 ElementsKind elements_kind, |
(...skipping 19 matching lines...) Expand all Loading... |
1227 HValue* elements = AddLoadElements(object, mapcheck); | 1236 HValue* elements = AddLoadElements(object, mapcheck); |
1228 if (is_store && (fast_elements || fast_smi_only_elements) && | 1237 if (is_store && (fast_elements || fast_smi_only_elements) && |
1229 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1238 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1230 HCheckMaps* check_cow_map = HCheckMaps::New( | 1239 HCheckMaps* check_cow_map = HCheckMaps::New( |
1231 elements, isolate()->factory()->fixed_array_map(), zone, top_info()); | 1240 elements, isolate()->factory()->fixed_array_map(), zone, top_info()); |
1232 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1241 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1233 AddInstruction(check_cow_map); | 1242 AddInstruction(check_cow_map); |
1234 } | 1243 } |
1235 HInstruction* length = NULL; | 1244 HInstruction* length = NULL; |
1236 if (is_js_array) { | 1245 if (is_js_array) { |
1237 length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind), | 1246 length = Add<HLoadNamedField>(object, |
1238 mapcheck); | 1247 HObjectAccess::ForArrayLength(elements_kind), mapcheck); |
1239 } else { | 1248 } else { |
1240 length = AddLoadFixedArrayLength(elements); | 1249 length = AddLoadFixedArrayLength(elements); |
1241 } | 1250 } |
1242 length->set_type(HType::Smi()); | 1251 length->set_type(HType::Smi()); |
1243 HValue* checked_key = NULL; | 1252 HValue* checked_key = NULL; |
1244 if (IsExternalArrayElementsKind(elements_kind)) { | 1253 if (IsExternalArrayElementsKind(elements_kind)) { |
1245 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1254 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1246 NoObservableSideEffectsScope no_effects(this); | 1255 NoObservableSideEffectsScope no_effects(this); |
1247 HLoadExternalArrayPointer* external_elements = | 1256 HLoadExternalArrayPointer* external_elements = |
1248 Add<HLoadExternalArrayPointer>(elements); | 1257 AddAndCast<HLoadExternalArrayPointer>(elements); |
1249 IfBuilder length_checker(this); | 1258 IfBuilder length_checker(this); |
1250 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1259 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
1251 length_checker.Then(); | 1260 length_checker.Then(); |
1252 IfBuilder negative_checker(this); | 1261 IfBuilder negative_checker(this); |
1253 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1262 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
1254 key, graph()->GetConstant0(), Token::GTE); | 1263 key, graph()->GetConstant0(), Token::GTE); |
1255 negative_checker.Then(); | 1264 negative_checker.Then(); |
1256 HInstruction* result = AddExternalArrayElementAccess( | 1265 HInstruction* result = AddExternalArrayElementAccess( |
1257 external_elements, key, val, bounds_check, elements_kind, is_store); | 1266 external_elements, key, val, bounds_check, elements_kind, is_store); |
1258 negative_checker.ElseDeopt(); | 1267 negative_checker.ElseDeopt(); |
1259 length_checker.End(); | 1268 length_checker.End(); |
1260 return result; | 1269 return result; |
1261 } else { | 1270 } else { |
1262 ASSERT(store_mode == STANDARD_STORE); | 1271 ASSERT(store_mode == STANDARD_STORE); |
1263 checked_key = Add<HBoundsCheck>(key, length); | 1272 checked_key = Add<HBoundsCheck>(key, length); |
1264 HLoadExternalArrayPointer* external_elements = | 1273 HLoadExternalArrayPointer* external_elements = |
1265 Add<HLoadExternalArrayPointer>(elements); | 1274 AddAndCast<HLoadExternalArrayPointer>(elements); |
1266 return AddExternalArrayElementAccess( | 1275 return AddExternalArrayElementAccess( |
1267 external_elements, checked_key, val, | 1276 external_elements, checked_key, val, |
1268 mapcheck, elements_kind, is_store); | 1277 mapcheck, elements_kind, is_store); |
1269 } | 1278 } |
1270 } | 1279 } |
1271 ASSERT(fast_smi_only_elements || | 1280 ASSERT(fast_smi_only_elements || |
1272 fast_elements || | 1281 fast_elements || |
1273 IsFastDoubleElementsKind(elements_kind)); | 1282 IsFastDoubleElementsKind(elements_kind)); |
1274 | 1283 |
1275 // In case val is stored into a fast smi array, assure that the value is a smi | 1284 // In case val is stored into a fast smi array, assure that the value is a smi |
(...skipping 25 matching lines...) Expand all Loading... |
1301 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1310 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1302 AddInstruction(check_cow_map); | 1311 AddInstruction(check_cow_map); |
1303 } | 1312 } |
1304 } | 1313 } |
1305 } | 1314 } |
1306 return AddFastElementAccess(elements, checked_key, val, mapcheck, | 1315 return AddFastElementAccess(elements, checked_key, val, mapcheck, |
1307 elements_kind, is_store, load_mode, store_mode); | 1316 elements_kind, is_store, load_mode, store_mode); |
1308 } | 1317 } |
1309 | 1318 |
1310 | 1319 |
1311 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1320 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
1312 ElementsKind kind, | |
1313 HValue* capacity) { | 1321 HValue* capacity) { |
1314 Zone* zone = this->zone(); | |
1315 | |
1316 int elements_size = IsFastDoubleElementsKind(kind) | 1322 int elements_size = IsFastDoubleElementsKind(kind) |
1317 ? kDoubleSize : kPointerSize; | 1323 ? kDoubleSize : kPointerSize; |
1318 HConstant* elements_size_value = Add<HConstant>(elements_size); | 1324 HConstant* elements_size_value = AddAndCast<HConstant>(elements_size); |
1319 HValue* mul = AddInstruction( | 1325 HValue* mul = Add<HMul>(capacity, elements_size_value); |
1320 HMul::New(zone, context, capacity, elements_size_value)); | |
1321 mul->ClearFlag(HValue::kCanOverflow); | 1326 mul->ClearFlag(HValue::kCanOverflow); |
1322 | 1327 |
1323 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | 1328 HConstant* header_size = AddAndCast<HConstant>(FixedArray::kHeaderSize); |
1324 HValue* total_size = AddInstruction( | 1329 HValue* total_size = Add<HAdd>(mul, header_size); |
1325 HAdd::New(zone, context, mul, header_size)); | |
1326 total_size->ClearFlag(HValue::kCanOverflow); | 1330 total_size->ClearFlag(HValue::kCanOverflow); |
1327 | 1331 |
1328 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); | 1332 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); |
1329 if (isolate()->heap()->ShouldGloballyPretenure()) { | 1333 if (isolate()->heap()->ShouldGloballyPretenure()) { |
1330 // TODO(hpayer): When pretenuring can be internalized, flags can become | 1334 // TODO(hpayer): When pretenuring can be internalized, flags can become |
1331 // private to HAllocate. | 1335 // private to HAllocate. |
1332 if (IsFastDoubleElementsKind(kind)) { | 1336 if (IsFastDoubleElementsKind(kind)) { |
1333 flags = static_cast<HAllocate::Flags>( | 1337 flags = static_cast<HAllocate::Flags>( |
1334 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 1338 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
1335 } else { | 1339 } else { |
1336 flags = static_cast<HAllocate::Flags>( | 1340 flags = static_cast<HAllocate::Flags>( |
1337 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 1341 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
1338 } | 1342 } |
1339 } | 1343 } |
1340 | 1344 |
1341 return Add<HAllocate>(context, total_size, HType::JSArray(), flags); | 1345 return Add<HAllocate>(total_size, HType::JSArray(), flags); |
1342 } | 1346 } |
1343 | 1347 |
1344 | 1348 |
1345 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1349 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
1346 ElementsKind kind, | 1350 ElementsKind kind, |
1347 HValue* capacity) { | 1351 HValue* capacity) { |
1348 Factory* factory = isolate()->factory(); | 1352 Factory* factory = isolate()->factory(); |
1349 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1353 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1350 ? factory->fixed_double_array_map() | 1354 ? factory->fixed_double_array_map() |
1351 : factory->fixed_array_map(); | 1355 : factory->fixed_array_map(); |
1352 | 1356 |
1353 AddStoreMapConstant(elements, map); | 1357 AddStoreMapConstant(elements, map); |
1354 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); | 1358 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), |
| 1359 capacity); |
1355 } | 1360 } |
1356 | 1361 |
1357 | 1362 |
1358 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1363 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
1359 HValue* context, | |
1360 ElementsKind kind, | 1364 ElementsKind kind, |
1361 HValue* capacity) { | 1365 HValue* capacity) { |
1362 // The HForceRepresentation is to prevent possible deopt on int-smi | 1366 // The HForceRepresentation is to prevent possible deopt on int-smi |
1363 // conversion after allocation but before the new object fields are set. | 1367 // conversion after allocation but before the new object fields are set. |
1364 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); | 1368 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); |
1365 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1369 HValue* new_elements = BuildAllocateElements(kind, capacity); |
1366 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1370 BuildInitializeElementsHeader(new_elements, kind, capacity); |
1367 return new_elements; | 1371 return new_elements; |
1368 } | 1372 } |
1369 | 1373 |
1370 | 1374 |
1371 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1375 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
1372 HValue* array_map, | 1376 HValue* array_map, |
1373 AllocationSiteMode mode, | 1377 AllocationSiteMode mode, |
1374 ElementsKind elements_kind, | 1378 ElementsKind elements_kind, |
1375 HValue* allocation_site_payload, | 1379 HValue* allocation_site_payload, |
1376 HValue* length_field) { | 1380 HValue* length_field) { |
1377 | 1381 |
1378 AddStore(array, HObjectAccess::ForMap(), array_map); | 1382 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
1379 | 1383 |
1380 HConstant* empty_fixed_array = | 1384 HConstant* empty_fixed_array = |
1381 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 1385 AddAndCast<HConstant>(isolate()->factory()->empty_fixed_array()); |
1382 | 1386 |
1383 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1387 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
1384 AddStore(array, access, empty_fixed_array); | 1388 Add<HStoreNamedField>(array, access, empty_fixed_array); |
1385 AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field); | 1389 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
| 1390 length_field); |
1386 | 1391 |
1387 if (mode == TRACK_ALLOCATION_SITE) { | 1392 if (mode == TRACK_ALLOCATION_SITE) { |
1388 BuildCreateAllocationMemento(array, | 1393 BuildCreateAllocationMemento(array, |
1389 JSArray::kSize, | 1394 JSArray::kSize, |
1390 allocation_site_payload); | 1395 allocation_site_payload); |
1391 } | 1396 } |
1392 | 1397 |
1393 int elements_location = JSArray::kSize; | 1398 int elements_location = JSArray::kSize; |
1394 if (mode == TRACK_ALLOCATION_SITE) { | 1399 if (mode == TRACK_ALLOCATION_SITE) { |
1395 elements_location += AllocationMemento::kSize; | 1400 elements_location += AllocationMemento::kSize; |
1396 } | 1401 } |
1397 | 1402 |
1398 HInnerAllocatedObject* elements = | 1403 HValue* elements = |
1399 Add<HInnerAllocatedObject>(array, elements_location); | 1404 Add<HInnerAllocatedObject>(array, elements_location); |
1400 AddStore(array, HObjectAccess::ForElementsPointer(), elements); | 1405 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
1401 return elements; | 1406 return static_cast<HInnerAllocatedObject*>(elements); |
1402 } | 1407 } |
1403 | 1408 |
1404 | 1409 |
1405 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( | 1410 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( |
1406 HValue* external_elements, | 1411 HValue* external_elements, |
1407 HValue* checked_key, | 1412 HValue* checked_key, |
1408 HValue* val, | 1413 HValue* val, |
1409 HValue* dependency, | 1414 HValue* dependency, |
1410 ElementsKind elements_kind, | 1415 ElementsKind elements_kind, |
1411 bool is_store) { | 1416 bool is_store) { |
(...skipping 22 matching lines...) Expand all Loading... |
1434 case FAST_HOLEY_ELEMENTS: | 1439 case FAST_HOLEY_ELEMENTS: |
1435 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1440 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1436 case DICTIONARY_ELEMENTS: | 1441 case DICTIONARY_ELEMENTS: |
1437 case NON_STRICT_ARGUMENTS_ELEMENTS: | 1442 case NON_STRICT_ARGUMENTS_ELEMENTS: |
1438 UNREACHABLE(); | 1443 UNREACHABLE(); |
1439 break; | 1444 break; |
1440 } | 1445 } |
1441 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); | 1446 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); |
1442 } else { | 1447 } else { |
1443 ASSERT(val == NULL); | 1448 ASSERT(val == NULL); |
1444 HLoadKeyed* load = Add<HLoadKeyed>(external_elements, checked_key, | 1449 HLoadKeyed* load = HLoadKeyed::cast(Add<HLoadKeyed>(external_elements, |
1445 dependency, elements_kind); | 1450 checked_key, |
| 1451 dependency, |
| 1452 elements_kind)); |
1446 if (FLAG_opt_safe_uint32_operations && | 1453 if (FLAG_opt_safe_uint32_operations && |
1447 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 1454 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
1448 graph()->RecordUint32Instruction(load); | 1455 graph()->RecordUint32Instruction(load); |
1449 } | 1456 } |
1450 return load; | 1457 return load; |
1451 } | 1458 } |
1452 } | 1459 } |
1453 | 1460 |
1454 | 1461 |
1455 HInstruction* HGraphBuilder::AddFastElementAccess( | 1462 HInstruction* HGraphBuilder::AddFastElementAccess( |
(...skipping 21 matching lines...) Expand all Loading... |
1477 } | 1484 } |
1478 } | 1485 } |
1479 // It's an element load (!is_store). | 1486 // It's an element load (!is_store). |
1480 return Add<HLoadKeyed>( | 1487 return Add<HLoadKeyed>( |
1481 elements, checked_key, load_dependency, elements_kind, load_mode); | 1488 elements, checked_key, load_dependency, elements_kind, load_mode); |
1482 } | 1489 } |
1483 | 1490 |
1484 | 1491 |
1485 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1492 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
1486 HValue* typecheck) { | 1493 HValue* typecheck) { |
1487 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1494 return AddAndCast<HLoadNamedField>(object, |
| 1495 HObjectAccess::ForElementsPointer(), |
| 1496 typecheck); |
1488 } | 1497 } |
1489 | 1498 |
1490 | 1499 |
1491 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1500 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
1492 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); | 1501 return AddAndCast<HLoadNamedField>(object, |
| 1502 HObjectAccess::ForFixedArrayLength()); |
1493 } | 1503 } |
1494 | 1504 |
1495 | 1505 |
1496 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1506 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
1497 HValue* old_capacity) { | 1507 HValue* half_old_capacity = Add<HShr>(old_capacity, graph_->GetConstant1()); |
1498 Zone* zone = this->zone(); | |
1499 HValue* half_old_capacity = | |
1500 AddInstruction(HShr::New(zone, context, old_capacity, | |
1501 graph_->GetConstant1())); | |
1502 | 1508 |
1503 HValue* new_capacity = AddInstruction( | 1509 HValue* new_capacity = Add<HAdd>(half_old_capacity, old_capacity); |
1504 HAdd::New(zone, context, half_old_capacity, old_capacity)); | |
1505 new_capacity->ClearFlag(HValue::kCanOverflow); | 1510 new_capacity->ClearFlag(HValue::kCanOverflow); |
1506 | 1511 |
1507 HValue* min_growth = Add<HConstant>(16); | 1512 HValue* min_growth = Add<HConstant>(16); |
1508 | 1513 |
1509 new_capacity = AddInstruction( | 1514 new_capacity = Add<HAdd>(new_capacity, min_growth); |
1510 HAdd::New(zone, context, new_capacity, min_growth)); | |
1511 new_capacity->ClearFlag(HValue::kCanOverflow); | 1515 new_capacity->ClearFlag(HValue::kCanOverflow); |
1512 | 1516 |
1513 return new_capacity; | 1517 return new_capacity; |
1514 } | 1518 } |
1515 | 1519 |
1516 | 1520 |
1517 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | 1521 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
1518 Heap* heap = isolate()->heap(); | 1522 Heap* heap = isolate()->heap(); |
1519 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | 1523 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
1520 : kPointerSize; | 1524 : kPointerSize; |
1521 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; | 1525 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; |
1522 max_size -= JSArray::kSize / element_size; | 1526 max_size -= JSArray::kSize / element_size; |
1523 HConstant* max_size_constant = Add<HConstant>(max_size); | 1527 HConstant* max_size_constant = AddAndCast<HConstant>(max_size); |
1524 Add<HBoundsCheck>(length, max_size_constant); | 1528 Add<HBoundsCheck>(length, max_size_constant); |
1525 } | 1529 } |
1526 | 1530 |
1527 | 1531 |
1528 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1532 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
1529 HValue* elements, | 1533 HValue* elements, |
1530 ElementsKind kind, | 1534 ElementsKind kind, |
1531 ElementsKind new_kind, | 1535 ElementsKind new_kind, |
1532 HValue* length, | 1536 HValue* length, |
1533 HValue* new_capacity) { | 1537 HValue* new_capacity) { |
1534 HValue* context = environment()->LookupContext(); | |
1535 | |
1536 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 1538 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
1537 | 1539 |
1538 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 1540 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
1539 context, new_kind, new_capacity); | 1541 new_kind, new_capacity); |
1540 | 1542 |
1541 BuildCopyElements(context, elements, kind, | 1543 BuildCopyElements(elements, kind, |
1542 new_elements, new_kind, | 1544 new_elements, new_kind, |
1543 length, new_capacity); | 1545 length, new_capacity); |
1544 | 1546 |
1545 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); | 1547 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1548 new_elements); |
1546 | 1549 |
1547 return new_elements; | 1550 return new_elements; |
1548 } | 1551 } |
1549 | 1552 |
1550 | 1553 |
1551 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1554 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
1552 HValue* elements, | |
1553 ElementsKind elements_kind, | 1555 ElementsKind elements_kind, |
1554 HValue* from, | 1556 HValue* from, |
1555 HValue* to) { | 1557 HValue* to) { |
1556 // Fast elements kinds need to be initialized in case statements below cause | 1558 // Fast elements kinds need to be initialized in case statements below cause |
1557 // a garbage collection. | 1559 // a garbage collection. |
1558 Factory* factory = isolate()->factory(); | 1560 Factory* factory = isolate()->factory(); |
1559 | 1561 |
1560 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 1562 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
1561 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 1563 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
1562 ? Add<HConstant>(factory->the_hole_value()) | 1564 ? Add<HConstant>(factory->the_hole_value()) |
(...skipping 21 matching lines...) Expand all Loading... |
1584 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 1586 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
1585 elements_kind = FAST_HOLEY_ELEMENTS; | 1587 elements_kind = FAST_HOLEY_ELEMENTS; |
1586 } | 1588 } |
1587 | 1589 |
1588 if (unfold_loop) { | 1590 if (unfold_loop) { |
1589 for (int i = 0; i < initial_capacity; i++) { | 1591 for (int i = 0; i < initial_capacity; i++) { |
1590 HInstruction* key = Add<HConstant>(i); | 1592 HInstruction* key = Add<HConstant>(i); |
1591 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 1593 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
1592 } | 1594 } |
1593 } else { | 1595 } else { |
1594 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1596 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
1595 | 1597 |
1596 HValue* key = builder.BeginBody(from, to, Token::LT); | 1598 HValue* key = builder.BeginBody(from, to, Token::LT); |
1597 | 1599 |
1598 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 1600 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
1599 | 1601 |
1600 builder.EndBody(); | 1602 builder.EndBody(); |
1601 } | 1603 } |
1602 } | 1604 } |
1603 | 1605 |
1604 | 1606 |
1605 void HGraphBuilder::BuildCopyElements(HValue* context, | 1607 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
1606 HValue* from_elements, | |
1607 ElementsKind from_elements_kind, | 1608 ElementsKind from_elements_kind, |
1608 HValue* to_elements, | 1609 HValue* to_elements, |
1609 ElementsKind to_elements_kind, | 1610 ElementsKind to_elements_kind, |
1610 HValue* length, | 1611 HValue* length, |
1611 HValue* capacity) { | 1612 HValue* capacity) { |
1612 bool pre_fill_with_holes = | 1613 bool pre_fill_with_holes = |
1613 IsFastDoubleElementsKind(from_elements_kind) && | 1614 IsFastDoubleElementsKind(from_elements_kind) && |
1614 IsFastObjectElementsKind(to_elements_kind); | 1615 IsFastObjectElementsKind(to_elements_kind); |
1615 | 1616 |
1616 if (pre_fill_with_holes) { | 1617 if (pre_fill_with_holes) { |
1617 // If the copy might trigger a GC, make sure that the FixedArray is | 1618 // If the copy might trigger a GC, make sure that the FixedArray is |
1618 // pre-initialized with holes to make sure that it's always in a consistent | 1619 // pre-initialized with holes to make sure that it's always in a consistent |
1619 // state. | 1620 // state. |
1620 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1621 BuildFillElementsWithHole(to_elements, to_elements_kind, |
1621 graph()->GetConstant0(), capacity); | 1622 graph()->GetConstant0(), capacity); |
1622 } | 1623 } |
1623 | 1624 |
1624 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1625 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
1625 | 1626 |
1626 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1627 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1627 | 1628 |
1628 HValue* element = Add<HLoadKeyed>(from_elements, key, | 1629 HValue* element = Add<HLoadKeyed>(from_elements, key, |
1629 static_cast<HValue*>(NULL), | 1630 static_cast<HValue*>(NULL), |
1630 from_elements_kind, | 1631 from_elements_kind, |
1631 ALLOW_RETURN_HOLE); | 1632 ALLOW_RETURN_HOLE); |
1632 | 1633 |
1633 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) | 1634 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) |
1634 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 1635 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
1635 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, | 1636 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, |
1636 element, holey_kind); | 1637 element, holey_kind); |
1637 // Allow NaN hole values to converted to their tagged counterparts. | 1638 // Allow NaN hole values to converted to their tagged counterparts. |
1638 if (IsFastHoleyElementsKind(to_elements_kind)) { | 1639 if (IsFastHoleyElementsKind(to_elements_kind)) { |
1639 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); | 1640 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); |
1640 } | 1641 } |
1641 | 1642 |
1642 builder.EndBody(); | 1643 builder.EndBody(); |
1643 | 1644 |
1644 if (!pre_fill_with_holes && length != capacity) { | 1645 if (!pre_fill_with_holes && length != capacity) { |
1645 // Fill unused capacity with the hole. | 1646 // Fill unused capacity with the hole. |
1646 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1647 BuildFillElementsWithHole(to_elements, to_elements_kind, |
1647 key, capacity); | 1648 key, capacity); |
1648 } | 1649 } |
1649 } | 1650 } |
1650 | 1651 |
1651 | 1652 |
1652 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 1653 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
1653 HValue* boilerplate, | |
1654 HValue* allocation_site, | 1654 HValue* allocation_site, |
1655 AllocationSiteMode mode, | 1655 AllocationSiteMode mode, |
1656 ElementsKind kind, | 1656 ElementsKind kind, |
1657 int length) { | 1657 int length) { |
1658 NoObservableSideEffectsScope no_effects(this); | 1658 NoObservableSideEffectsScope no_effects(this); |
1659 | 1659 |
1660 // All sizes here are multiples of kPointerSize. | 1660 // All sizes here are multiples of kPointerSize. |
1661 int size = JSArray::kSize; | 1661 int size = JSArray::kSize; |
1662 if (mode == TRACK_ALLOCATION_SITE) { | 1662 if (mode == TRACK_ALLOCATION_SITE) { |
1663 size += AllocationMemento::kSize; | 1663 size += AllocationMemento::kSize; |
1664 } | 1664 } |
1665 int elems_offset = size; | 1665 int elems_offset = size; |
1666 if (length > 0) { | 1666 if (length > 0) { |
1667 size += IsFastDoubleElementsKind(kind) | 1667 size += IsFastDoubleElementsKind(kind) |
1668 ? FixedDoubleArray::SizeFor(length) | 1668 ? FixedDoubleArray::SizeFor(length) |
1669 : FixedArray::SizeFor(length); | 1669 : FixedArray::SizeFor(length); |
1670 } | 1670 } |
1671 | 1671 |
1672 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); | 1672 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); |
1673 // Allocate both the JS array and the elements array in one big | 1673 // Allocate both the JS array and the elements array in one big |
1674 // allocation. This avoids multiple limit checks. | 1674 // allocation. This avoids multiple limit checks. |
1675 HValue* size_in_bytes = Add<HConstant>(size); | 1675 HValue* size_in_bytes = Add<HConstant>(size); |
1676 HInstruction* object = Add<HAllocate>(context, | 1676 HInstruction* object = Add<HAllocate>(size_in_bytes, |
1677 size_in_bytes, | |
1678 HType::JSObject(), | 1677 HType::JSObject(), |
1679 allocate_flags); | 1678 allocate_flags); |
1680 | 1679 |
1681 // Copy the JS array part. | 1680 // Copy the JS array part. |
1682 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1681 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
1683 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1682 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
1684 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 1683 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
1685 AddStore(object, access, AddLoad(boilerplate, access)); | 1684 Add<HStoreNamedField>(object, access, |
| 1685 Add<HLoadNamedField>(boilerplate, access)); |
1686 } | 1686 } |
1687 } | 1687 } |
1688 | 1688 |
1689 // Create an allocation site info if requested. | 1689 // Create an allocation site info if requested. |
1690 if (mode == TRACK_ALLOCATION_SITE) { | 1690 if (mode == TRACK_ALLOCATION_SITE) { |
1691 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 1691 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
1692 } | 1692 } |
1693 | 1693 |
1694 if (length > 0) { | 1694 if (length > 0) { |
1695 // Get hold of the elements array of the boilerplate and setup the | 1695 // Get hold of the elements array of the boilerplate and setup the |
1696 // elements pointer in the resulting object. | 1696 // elements pointer in the resulting object. |
1697 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1697 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
1698 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1698 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
1699 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); | 1699 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1700 object_elements); |
1700 | 1701 |
1701 // Copy the elements array header. | 1702 // Copy the elements array header. |
1702 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1703 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
1703 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1704 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
1704 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); | 1705 Add<HStoreNamedField>(object_elements, access, |
| 1706 Add<HLoadNamedField>(boilerplate_elements, access)); |
1705 } | 1707 } |
1706 | 1708 |
1707 // Copy the elements array contents. | 1709 // Copy the elements array contents. |
1708 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1710 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
1709 // copying loops with constant length up to a given boundary and use this | 1711 // copying loops with constant length up to a given boundary and use this |
1710 // helper here instead. | 1712 // helper here instead. |
1711 for (int i = 0; i < length; i++) { | 1713 for (int i = 0; i < length; i++) { |
1712 HValue* key_constant = Add<HConstant>(i); | 1714 HValue* key_constant = Add<HConstant>(i); |
1713 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | 1715 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
1714 static_cast<HValue*>(NULL), kind); | 1716 static_cast<HValue*>(NULL), kind); |
1715 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | 1717 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
1716 } | 1718 } |
1717 } | 1719 } |
1718 | 1720 |
1719 return object; | 1721 return object; |
1720 } | 1722 } |
1721 | 1723 |
1722 | 1724 |
| 1725 HValue* HGraphBuilder::BuildKeyHash(HValue* key) { |
| 1726 int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed()); |
| 1727 HValue* seed = Add<HConstant>(seed_value); |
| 1728 HValue* hash = Add<HBitwise>(Token::BIT_XOR, key, seed); |
| 1729 |
| 1730 // hash = ~hash + (hash << 15); |
| 1731 HValue* shifted_hash = Add<HShl>(hash, Add<HConstant>(15)); |
| 1732 hash = Add<HAdd>(shifted_hash, static_cast<HValue*>(Add<HBitNot>(hash))); |
| 1733 |
| 1734 // hash = hash ^ (hash >> 12); |
| 1735 shifted_hash = Add<HShr>(hash, Add<HConstant>(12)); |
| 1736 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1737 |
| 1738 // hash = hash + (hash << 2); |
| 1739 shifted_hash = Add<HShl>(hash, Add<HConstant>(2)); |
| 1740 hash = Add<HAdd>(hash, shifted_hash); |
| 1741 |
| 1742 // hash = hash ^ (hash >> 4); |
| 1743 shifted_hash = Add<HShr>(hash, Add<HConstant>(4)); |
| 1744 hash = Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1745 |
| 1746 // hash = hash * 2057; |
| 1747 hash = Add<HMul>(hash, Add<HConstant>(2057)); |
| 1748 hash->ClearFlag(HValue::kCanOverflow); |
| 1749 |
| 1750 // hash = hash ^ (hash >> 16); |
| 1751 shifted_hash = Add<HShr>(hash, Add<HConstant>(16)); |
| 1752 return Add<HBitwise>(Token::BIT_XOR, hash, shifted_hash); |
| 1753 } |
| 1754 |
| 1755 |
1723 HInstruction* HGraphBuilder::BuildUnaryMathOp( | 1756 HInstruction* HGraphBuilder::BuildUnaryMathOp( |
1724 HValue* input, Handle<Type> type, Token::Value operation) { | 1757 HValue* input, Handle<Type> type, Token::Value operation) { |
1725 // We only handle the numeric cases here | 1758 // We only handle the numeric cases here |
1726 type = handle( | 1759 type = handle( |
1727 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); | 1760 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); |
1728 | 1761 |
1729 switch (operation) { | 1762 switch (operation) { |
1730 default: | 1763 default: |
1731 UNREACHABLE(); | 1764 UNREACHABLE(); |
1732 case Token::SUB: { | 1765 case Token::SUB: { |
1733 HInstruction* instr = | 1766 HInstruction* instr = |
1734 HMul::New(zone(), environment()->LookupContext(), | 1767 New<HMul>(input, graph()->GetConstantMinus1()); |
1735 input, graph()->GetConstantMinus1()); | |
1736 Representation rep = Representation::FromType(type); | 1768 Representation rep = Representation::FromType(type); |
1737 if (type->Is(Type::None())) { | 1769 if (type->Is(Type::None())) { |
1738 Add<HDeoptimize>(Deoptimizer::SOFT); | 1770 Add<HDeoptimize>(Deoptimizer::SOFT); |
1739 } | 1771 } |
1740 if (instr->IsBinaryOperation()) { | 1772 if (instr->IsBinaryOperation()) { |
1741 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1773 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
1742 binop->set_observed_input_representation(1, rep); | 1774 binop->set_observed_input_representation(1, rep); |
1743 binop->set_observed_input_representation(2, rep); | 1775 binop->set_observed_input_representation(2, rep); |
1744 } | 1776 } |
1745 return instr; | 1777 return instr; |
1746 } | 1778 } |
1747 case Token::BIT_NOT: | 1779 case Token::BIT_NOT: |
1748 if (type->Is(Type::None())) { | 1780 if (type->Is(Type::None())) { |
1749 Add<HDeoptimize>(Deoptimizer::SOFT); | 1781 Add<HDeoptimize>(Deoptimizer::SOFT); |
1750 } | 1782 } |
1751 return new(zone()) HBitNot(input); | 1783 return New<HBitNot>(input); |
1752 } | 1784 } |
1753 } | 1785 } |
1754 | 1786 |
1755 | 1787 |
1756 void HGraphBuilder::BuildCompareNil( | 1788 void HGraphBuilder::BuildCompareNil( |
1757 HValue* value, | 1789 HValue* value, |
1758 Handle<Type> type, | 1790 Handle<Type> type, |
1759 int position, | 1791 int position, |
1760 HIfContinuation* continuation) { | 1792 HIfContinuation* continuation) { |
1761 IfBuilder if_nil(this, position); | 1793 IfBuilder if_nil(this, position); |
(...skipping 28 matching lines...) Expand all Loading... |
1790 } | 1822 } |
1791 | 1823 |
1792 if_nil.CaptureContinuation(continuation); | 1824 if_nil.CaptureContinuation(continuation); |
1793 } | 1825 } |
1794 | 1826 |
1795 | 1827 |
1796 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 1828 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
1797 int previous_object_size, | 1829 int previous_object_size, |
1798 HValue* alloc_site) { | 1830 HValue* alloc_site) { |
1799 ASSERT(alloc_site != NULL); | 1831 ASSERT(alloc_site != NULL); |
1800 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 1832 HInnerAllocatedObject* alloc_memento = AddAndCast<HInnerAllocatedObject>( |
1801 previous_object, previous_object_size); | 1833 previous_object, previous_object_size); |
1802 Handle<Map> alloc_memento_map( | 1834 Handle<Map> alloc_memento_map( |
1803 isolate()->heap()->allocation_memento_map()); | 1835 isolate()->heap()->allocation_memento_map()); |
1804 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 1836 AddStoreMapConstant(alloc_memento, alloc_memento_map); |
1805 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 1837 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
1806 AddStore(alloc_memento, access, alloc_site); | 1838 Add<HStoreNamedField>(alloc_memento, access, alloc_site); |
1807 return alloc_memento; | 1839 return alloc_memento; |
1808 } | 1840 } |
1809 | 1841 |
1810 | 1842 |
1811 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { | 1843 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
1812 // Get the global context, then the native context | 1844 // Get the global context, then the native context |
1813 HInstruction* global_object = Add<HGlobalObject>(context); | 1845 HInstruction* global_object = Add<HGlobalObject>(); |
1814 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1846 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
1815 GlobalObject::kNativeContextOffset); | 1847 GlobalObject::kNativeContextOffset); |
1816 return AddLoad(global_object, access); | 1848 return Add<HLoadNamedField>(global_object, access); |
1817 } | 1849 } |
1818 | 1850 |
1819 | 1851 |
1820 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { | 1852 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
1821 HInstruction* native_context = BuildGetNativeContext(context); | 1853 HInstruction* native_context = BuildGetNativeContext(); |
1822 HInstruction* index = | 1854 HInstruction* index = |
1823 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | 1855 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
1824 return Add<HLoadKeyed>( | 1856 return Add<HLoadKeyed>( |
1825 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1857 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1826 } | 1858 } |
1827 | 1859 |
1828 | 1860 |
1829 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1861 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
1830 ElementsKind kind, | 1862 ElementsKind kind, |
1831 HValue* allocation_site_payload, | 1863 HValue* allocation_site_payload, |
(...skipping 13 matching lines...) Expand all Loading... |
1845 ElementsKind kind, | 1877 ElementsKind kind, |
1846 HValue* constructor_function) : | 1878 HValue* constructor_function) : |
1847 builder_(builder), | 1879 builder_(builder), |
1848 kind_(kind), | 1880 kind_(kind), |
1849 mode_(DONT_TRACK_ALLOCATION_SITE), | 1881 mode_(DONT_TRACK_ALLOCATION_SITE), |
1850 allocation_site_payload_(NULL), | 1882 allocation_site_payload_(NULL), |
1851 constructor_function_(constructor_function) { | 1883 constructor_function_(constructor_function) { |
1852 } | 1884 } |
1853 | 1885 |
1854 | 1886 |
1855 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1887 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
1856 if (kind_ == GetInitialFastElementsKind()) { | 1888 if (kind_ == GetInitialFastElementsKind()) { |
1857 // No need for a context lookup if the kind_ matches the initial | 1889 // No need for a context lookup if the kind_ matches the initial |
1858 // map, because we can just load the map in that case. | 1890 // map, because we can just load the map in that case. |
1859 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1891 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1860 return builder()->AddInstruction( | 1892 return builder()->AddInstruction( |
1861 builder()->BuildLoadNamedField(constructor_function_, access)); | 1893 builder()->BuildLoadNamedField(constructor_function_, access)); |
1862 } | 1894 } |
1863 | 1895 |
1864 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1896 HInstruction* native_context = builder()->BuildGetNativeContext(); |
1865 HInstruction* index = builder()->Add<HConstant>( | 1897 HInstruction* index = builder()->Add<HConstant>( |
1866 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1898 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
1867 | 1899 |
1868 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1900 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
1869 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1901 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1870 | 1902 |
1871 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1903 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
1872 | 1904 |
1873 return builder()->Add<HLoadKeyed>( | 1905 return builder()->Add<HLoadKeyed>( |
1874 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1906 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1875 } | 1907 } |
1876 | 1908 |
1877 | 1909 |
1878 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1910 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1879 // Find the map near the constructor function | 1911 // Find the map near the constructor function |
1880 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1912 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1881 return builder()->AddInstruction( | 1913 return builder()->AddInstruction( |
1882 builder()->BuildLoadNamedField(constructor_function_, access)); | 1914 builder()->BuildLoadNamedField(constructor_function_, access)); |
1883 } | 1915 } |
1884 | 1916 |
1885 | 1917 |
1886 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1918 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1887 HValue* length_node) { | 1919 HValue* length_node) { |
1888 HValue* context = builder()->environment()->LookupContext(); | |
1889 ASSERT(length_node != NULL); | 1920 ASSERT(length_node != NULL); |
1890 | 1921 |
1891 int base_size = JSArray::kSize; | 1922 int base_size = JSArray::kSize; |
1892 if (mode_ == TRACK_ALLOCATION_SITE) { | 1923 if (mode_ == TRACK_ALLOCATION_SITE) { |
1893 base_size += AllocationMemento::kSize; | 1924 base_size += AllocationMemento::kSize; |
1894 } | 1925 } |
1895 | 1926 |
1896 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | 1927 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
1897 base_size += FixedArray::kHeaderSize; | 1928 base_size += FixedArray::kHeaderSize; |
1898 | 1929 |
1899 HInstruction* elements_size_value = | 1930 HInstruction* elements_size_value = |
1900 builder()->Add<HConstant>(elements_size()); | 1931 builder()->Add<HConstant>(elements_size()); |
1901 HInstruction* mul = HMul::New(zone(), context, length_node, | 1932 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); |
1902 elements_size_value); | |
1903 mul->ClearFlag(HValue::kCanOverflow); | 1933 mul->ClearFlag(HValue::kCanOverflow); |
1904 builder()->AddInstruction(mul); | |
1905 | 1934 |
1906 HInstruction* base = builder()->Add<HConstant>(base_size); | 1935 HInstruction* base = builder()->Add<HConstant>(base_size); |
1907 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1936 HInstruction* total_size = builder()->Add<HAdd>(base, mul); |
1908 total_size->ClearFlag(HValue::kCanOverflow); | 1937 total_size->ClearFlag(HValue::kCanOverflow); |
1909 builder()->AddInstruction(total_size); | |
1910 return total_size; | 1938 return total_size; |
1911 } | 1939 } |
1912 | 1940 |
1913 | 1941 |
1914 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 1942 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
1915 int base_size = JSArray::kSize; | 1943 int base_size = JSArray::kSize; |
1916 if (mode_ == TRACK_ALLOCATION_SITE) { | 1944 if (mode_ == TRACK_ALLOCATION_SITE) { |
1917 base_size += AllocationMemento::kSize; | 1945 base_size += AllocationMemento::kSize; |
1918 } | 1946 } |
1919 | 1947 |
1920 base_size += IsFastDoubleElementsKind(kind_) | 1948 base_size += IsFastDoubleElementsKind(kind_) |
1921 ? FixedDoubleArray::SizeFor(initial_capacity()) | 1949 ? FixedDoubleArray::SizeFor(initial_capacity()) |
1922 : FixedArray::SizeFor(initial_capacity()); | 1950 : FixedArray::SizeFor(initial_capacity()); |
1923 | 1951 |
1924 return builder()->Add<HConstant>(base_size); | 1952 return builder()->Add<HConstant>(base_size); |
1925 } | 1953 } |
1926 | 1954 |
1927 | 1955 |
1928 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { | 1956 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { |
1929 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); | 1957 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); |
1930 HConstant* capacity = builder()->Add<HConstant>(initial_capacity()); | 1958 HConstant* capacity = builder()->AddAndCast<HConstant>(initial_capacity()); |
1931 return AllocateArray(size_in_bytes, | 1959 return AllocateArray(size_in_bytes, |
1932 capacity, | 1960 capacity, |
1933 builder()->graph()->GetConstant0(), | 1961 builder()->graph()->GetConstant0(), |
1934 true); | 1962 true); |
1935 } | 1963 } |
1936 | 1964 |
1937 | 1965 |
1938 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, | 1966 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, |
1939 HValue* length_field, | 1967 HValue* length_field, |
1940 bool fill_with_hole) { | 1968 bool fill_with_hole) { |
1941 HValue* size_in_bytes = EstablishAllocationSize(capacity); | 1969 HValue* size_in_bytes = EstablishAllocationSize(capacity); |
1942 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | 1970 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); |
1943 } | 1971 } |
1944 | 1972 |
1945 | 1973 |
1946 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 1974 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
1947 HValue* capacity, | 1975 HValue* capacity, |
1948 HValue* length_field, | 1976 HValue* length_field, |
1949 bool fill_with_hole) { | 1977 bool fill_with_hole) { |
1950 HValue* context = builder()->environment()->LookupContext(); | |
1951 | |
1952 // These HForceRepresentations are because we store these as fields in the | 1978 // These HForceRepresentations are because we store these as fields in the |
1953 // objects we construct, and an int32-to-smi HChange could deopt. Accept | 1979 // objects we construct, and an int32-to-smi HChange could deopt. Accept |
1954 // the deopt possibility now, before allocation occurs. | 1980 // the deopt possibility now, before allocation occurs. |
1955 capacity = builder()->Add<HForceRepresentation>(capacity, | 1981 capacity = builder()->Add<HForceRepresentation>(capacity, |
1956 Representation::Smi()); | 1982 Representation::Smi()); |
1957 length_field = builder()->Add<HForceRepresentation>(length_field, | 1983 length_field = builder()->Add<HForceRepresentation>(length_field, |
1958 Representation::Smi()); | 1984 Representation::Smi()); |
1959 | |
1960 // Allocate (dealing with failure appropriately) | 1985 // Allocate (dealing with failure appropriately) |
1961 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); | 1986 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); |
1962 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, | 1987 HAllocate* new_object = |
1963 HType::JSArray(), flags); | 1988 builder()->AddAndCast<HAllocate>(size_in_bytes, HType::JSArray(), flags); |
1964 | 1989 |
1965 // Fill in the fields: map, properties, length | 1990 // Fill in the fields: map, properties, length |
1966 HValue* map; | 1991 HValue* map; |
1967 if (allocation_site_payload_ == NULL) { | 1992 if (allocation_site_payload_ == NULL) { |
1968 map = EmitInternalMapCode(); | 1993 map = EmitInternalMapCode(); |
1969 } else { | 1994 } else { |
1970 map = EmitMapCode(context); | 1995 map = EmitMapCode(); |
1971 } | 1996 } |
1972 elements_location_ = builder()->BuildJSArrayHeader(new_object, | 1997 elements_location_ = builder()->BuildJSArrayHeader(new_object, |
1973 map, | 1998 map, |
1974 mode_, | 1999 mode_, |
1975 kind_, | 2000 kind_, |
1976 allocation_site_payload_, | 2001 allocation_site_payload_, |
1977 length_field); | 2002 length_field); |
1978 | 2003 |
1979 // Initialize the elements | 2004 // Initialize the elements |
1980 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 2005 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
1981 | 2006 |
1982 if (fill_with_hole) { | 2007 if (fill_with_hole) { |
1983 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 2008 builder()->BuildFillElementsWithHole(elements_location_, kind_, |
1984 graph()->GetConstant0(), capacity); | 2009 graph()->GetConstant0(), capacity); |
1985 } | 2010 } |
1986 | 2011 |
1987 return new_object; | 2012 return new_object; |
1988 } | 2013 } |
1989 | 2014 |
1990 | 2015 |
1991 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | |
1992 HObjectAccess access, | |
1993 HValue *val) { | |
1994 return Add<HStoreNamedField>(object, access, val); | |
1995 } | |
1996 | |
1997 | |
1998 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | |
1999 HObjectAccess access, | |
2000 HValue *typecheck) { | |
2001 return Add<HLoadNamedField>(object, access, typecheck); | |
2002 } | |
2003 | |
2004 | |
2005 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 2016 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
2006 Handle<Map> map) { | 2017 Handle<Map> map) { |
2007 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 2018 return AddAndCast<HStoreNamedField>(object, HObjectAccess::ForMap(), |
2008 Add<HConstant>(map)); | 2019 Add<HConstant>(map)); |
2009 } | 2020 } |
2010 | 2021 |
2011 | 2022 |
2012 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, | 2023 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { |
2013 HValue* context) { | 2024 HGlobalObject* global_object = AddAndCast<HGlobalObject>(); |
2014 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
2015 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2025 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
2016 GlobalObject::kBuiltinsOffset); | 2026 GlobalObject::kBuiltinsOffset); |
2017 HValue* builtins = AddLoad(global_object, access); | 2027 HValue* builtins = Add<HLoadNamedField>(global_object, access); |
2018 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( | 2028 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( |
2019 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); | 2029 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); |
2020 return AddLoad(builtins, function_access); | 2030 return Add<HLoadNamedField>(builtins, function_access); |
2021 } | 2031 } |
2022 | 2032 |
2023 | 2033 |
2024 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 2034 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
2025 : HGraphBuilder(info), | 2035 : HGraphBuilder(info), |
2026 function_state_(NULL), | 2036 function_state_(NULL), |
2027 initial_function_state_(this, info, NORMAL_RETURN), | 2037 initial_function_state_(this, info, NORMAL_RETURN), |
2028 ast_context_(NULL), | 2038 ast_context_(NULL), |
2029 break_scope_(NULL), | 2039 break_scope_(NULL), |
2030 inlined_count_(0), | 2040 inlined_count_(0), |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2902 set_current_block(body_entry); | 2912 set_current_block(body_entry); |
2903 | 2913 |
2904 // Handle implicit declaration of the function name in named function | 2914 // Handle implicit declaration of the function name in named function |
2905 // expressions before other declarations. | 2915 // expressions before other declarations. |
2906 if (scope->is_function_scope() && scope->function() != NULL) { | 2916 if (scope->is_function_scope() && scope->function() != NULL) { |
2907 VisitVariableDeclaration(scope->function()); | 2917 VisitVariableDeclaration(scope->function()); |
2908 } | 2918 } |
2909 VisitDeclarations(scope->declarations()); | 2919 VisitDeclarations(scope->declarations()); |
2910 Add<HSimulate>(BailoutId::Declarations()); | 2920 Add<HSimulate>(BailoutId::Declarations()); |
2911 | 2921 |
2912 HValue* context = environment()->LookupContext(); | 2922 HValue* context = environment()->context(); |
2913 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2923 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
2914 | 2924 |
2915 VisitStatements(current_info()->function()->body()); | 2925 VisitStatements(current_info()->function()->body()); |
2916 if (HasStackOverflow()) return false; | 2926 if (HasStackOverflow()) return false; |
2917 | 2927 |
2918 if (current_block() != NULL) { | 2928 if (current_block() != NULL) { |
2919 Add<HReturn>(graph()->GetConstantUndefined()); | 2929 Add<HReturn>(graph()->GetConstantUndefined()); |
2920 set_current_block(NULL); | 2930 set_current_block(NULL); |
2921 } | 2931 } |
2922 | 2932 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3113 } | 3123 } |
3114 | 3124 |
3115 while (!arguments.is_empty()) { | 3125 while (!arguments.is_empty()) { |
3116 Add<HPushArgument>(arguments.RemoveLast()); | 3126 Add<HPushArgument>(arguments.RemoveLast()); |
3117 } | 3127 } |
3118 return call; | 3128 return call; |
3119 } | 3129 } |
3120 | 3130 |
3121 | 3131 |
3122 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3132 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
3123 HConstant* undefined_constant = Add<HConstant>( | 3133 // First special is HContext. |
3124 isolate()->factory()->undefined_value()); | 3134 HInstruction* context = Add<HContext>(); |
| 3135 environment()->BindContext(context); |
| 3136 |
| 3137 HConstant* undefined_constant = HConstant::cast(Add<HConstant>( |
| 3138 isolate()->factory()->undefined_value())); |
3125 graph()->set_undefined_constant(undefined_constant); | 3139 graph()->set_undefined_constant(undefined_constant); |
3126 | 3140 |
3127 // Create an arguments object containing the initial parameters. Set the | 3141 // Create an arguments object containing the initial parameters. Set the |
3128 // initial values of parameters including "this" having parameter index 0. | 3142 // initial values of parameters including "this" having parameter index 0. |
3129 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3143 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
3130 HArgumentsObject* arguments_object = | 3144 HArgumentsObject* arguments_object = |
3131 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); | 3145 NewAndCast<HArgumentsObject>(environment()->parameter_count()); |
3132 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3146 for (int i = 0; i < environment()->parameter_count(); ++i) { |
3133 HInstruction* parameter = Add<HParameter>(i); | 3147 HInstruction* parameter = Add<HParameter>(i); |
3134 arguments_object->AddArgument(parameter, zone()); | 3148 arguments_object->AddArgument(parameter, zone()); |
3135 environment()->Bind(i, parameter); | 3149 environment()->Bind(i, parameter); |
3136 } | 3150 } |
3137 AddInstruction(arguments_object); | 3151 AddInstruction(arguments_object); |
3138 graph()->SetArgumentsObject(arguments_object); | 3152 graph()->SetArgumentsObject(arguments_object); |
3139 | 3153 |
3140 // First special is HContext. | |
3141 HInstruction* context = Add<HContext>(); | |
3142 environment()->BindContext(context); | |
3143 | |
3144 // Initialize specials and locals to undefined. | 3154 // Initialize specials and locals to undefined. |
3145 for (int i = environment()->parameter_count() + 1; | 3155 for (int i = environment()->parameter_count() + 1; |
3146 i < environment()->length(); | 3156 i < environment()->length(); |
3147 ++i) { | 3157 ++i) { |
3148 environment()->Bind(i, undefined_constant); | 3158 environment()->Bind(i, undefined_constant); |
3149 } | 3159 } |
3150 | 3160 |
3151 // Handle the arguments and arguments shadow variables specially (they do | 3161 // Handle the arguments and arguments shadow variables specially (they do |
3152 // not have declarations). | 3162 // not have declarations). |
3153 if (scope->arguments() != NULL) { | 3163 if (scope->arguments() != NULL) { |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3401 int clause_count = clauses->length(); | 3411 int clause_count = clauses->length(); |
3402 if (clause_count > kCaseClauseLimit) { | 3412 if (clause_count > kCaseClauseLimit) { |
3403 return Bailout("SwitchStatement: too many clauses"); | 3413 return Bailout("SwitchStatement: too many clauses"); |
3404 } | 3414 } |
3405 | 3415 |
3406 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3416 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3407 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3417 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3408 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3418 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
3409 } | 3419 } |
3410 | 3420 |
3411 HValue* context = environment()->LookupContext(); | 3421 HValue* context = environment()->context(); |
3412 | 3422 |
3413 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3423 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3414 Add<HSimulate>(stmt->EntryId()); | 3424 Add<HSimulate>(stmt->EntryId()); |
3415 HValue* tag_value = Pop(); | 3425 HValue* tag_value = Pop(); |
3416 HBasicBlock* first_test_block = current_block(); | 3426 HBasicBlock* first_test_block = current_block(); |
3417 | 3427 |
3418 HUnaryControlInstruction* string_check = NULL; | 3428 HUnaryControlInstruction* string_check = NULL; |
3419 HBasicBlock* not_string_block = NULL; | 3429 HBasicBlock* not_string_block = NULL; |
3420 | 3430 |
3421 // Test switch's tag value if all clauses are string literals | 3431 // Test switch's tag value if all clauses are string literals |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3549 set_current_block(break_block); | 3559 set_current_block(break_block); |
3550 } | 3560 } |
3551 } | 3561 } |
3552 | 3562 |
3553 | 3563 |
3554 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3564 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
3555 HBasicBlock* loop_entry, | 3565 HBasicBlock* loop_entry, |
3556 BreakAndContinueInfo* break_info) { | 3566 BreakAndContinueInfo* break_info) { |
3557 BreakAndContinueScope push(break_info, this); | 3567 BreakAndContinueScope push(break_info, this); |
3558 Add<HSimulate>(stmt->StackCheckId()); | 3568 Add<HSimulate>(stmt->StackCheckId()); |
3559 HValue* context = environment()->LookupContext(); | 3569 HValue* context = environment()->context(); |
3560 HStackCheck* stack_check = Add<HStackCheck>( | 3570 HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>( |
3561 context, HStackCheck::kBackwardsBranch); | 3571 context, HStackCheck::kBackwardsBranch)); |
3562 ASSERT(loop_entry->IsLoopHeader()); | 3572 ASSERT(loop_entry->IsLoopHeader()); |
3563 loop_entry->loop_information()->set_stack_check(stack_check); | 3573 loop_entry->loop_information()->set_stack_check(stack_check); |
3564 CHECK_BAILOUT(Visit(stmt->body())); | 3574 CHECK_BAILOUT(Visit(stmt->body())); |
3565 } | 3575 } |
3566 | 3576 |
3567 | 3577 |
3568 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3578 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
3569 ASSERT(!HasStackOverflow()); | 3579 ASSERT(!HasStackOverflow()); |
3570 ASSERT(current_block() != NULL); | 3580 ASSERT(current_block() != NULL); |
3571 ASSERT(current_block()->HasPredecessor()); | 3581 ASSERT(current_block()->HasPredecessor()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3707 if (!stmt->each()->IsVariableProxy() || | 3717 if (!stmt->each()->IsVariableProxy() || |
3708 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 3718 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
3709 return Bailout("ForInStatement with non-local each variable"); | 3719 return Bailout("ForInStatement with non-local each variable"); |
3710 } | 3720 } |
3711 | 3721 |
3712 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3722 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3713 | 3723 |
3714 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3724 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3715 HValue* enumerable = Top(); // Leave enumerable at the top. | 3725 HValue* enumerable = Top(); // Leave enumerable at the top. |
3716 | 3726 |
3717 HInstruction* map = Add<HForInPrepareMap>( | 3727 HInstruction* map = Add<HForInPrepareMap>(enumerable); |
3718 environment()->LookupContext(), enumerable); | |
3719 Add<HSimulate>(stmt->PrepareId()); | 3728 Add<HSimulate>(stmt->PrepareId()); |
3720 | 3729 |
3721 HInstruction* array = Add<HForInCacheArray>( | 3730 HInstruction* array = Add<HForInCacheArray>( |
3722 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3731 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
3723 | 3732 |
3724 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3733 HInstruction* enum_length = Add<HMapEnumLength>(map); |
3725 | 3734 |
3726 HInstruction* start_index = Add<HConstant>(0); | 3735 HInstruction* start_index = Add<HConstant>(0); |
3727 | 3736 |
3728 Push(map); | 3737 Push(map); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3774 BreakAndContinueInfo break_info(stmt, 5); | 3783 BreakAndContinueInfo break_info(stmt, 5); |
3775 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 3784 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
3776 | 3785 |
3777 HBasicBlock* body_exit = | 3786 HBasicBlock* body_exit = |
3778 JoinContinue(stmt, current_block(), break_info.continue_block()); | 3787 JoinContinue(stmt, current_block(), break_info.continue_block()); |
3779 | 3788 |
3780 if (body_exit != NULL) { | 3789 if (body_exit != NULL) { |
3781 set_current_block(body_exit); | 3790 set_current_block(body_exit); |
3782 | 3791 |
3783 HValue* current_index = Pop(); | 3792 HValue* current_index = Pop(); |
3784 HInstruction* new_index = HAdd::New(zone(), | 3793 HInstruction* new_index = New<HAdd>(current_index, |
3785 environment()->LookupContext(), | |
3786 current_index, | |
3787 graph()->GetConstant1()); | 3794 graph()->GetConstant1()); |
3788 PushAndAdd(new_index); | 3795 PushAndAdd(new_index); |
3789 body_exit = current_block(); | 3796 body_exit = current_block(); |
3790 } | 3797 } |
3791 | 3798 |
3792 HBasicBlock* loop_exit = CreateLoop(stmt, | 3799 HBasicBlock* loop_exit = CreateLoop(stmt, |
3793 loop_entry, | 3800 loop_entry, |
3794 body_exit, | 3801 body_exit, |
3795 loop_successor, | 3802 loop_successor, |
3796 break_info.break_block()); | 3803 break_info.break_block()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3855 ASSERT(!HasStackOverflow()); | 3862 ASSERT(!HasStackOverflow()); |
3856 ASSERT(current_block() != NULL); | 3863 ASSERT(current_block() != NULL); |
3857 ASSERT(current_block()->HasPredecessor()); | 3864 ASSERT(current_block()->HasPredecessor()); |
3858 Handle<SharedFunctionInfo> shared_info = | 3865 Handle<SharedFunctionInfo> shared_info = |
3859 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); | 3866 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); |
3860 if (shared_info.is_null()) { | 3867 if (shared_info.is_null()) { |
3861 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); | 3868 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
3862 } | 3869 } |
3863 // We also have a stack overflow if the recursive compilation did. | 3870 // We also have a stack overflow if the recursive compilation did. |
3864 if (HasStackOverflow()) return; | 3871 if (HasStackOverflow()) return; |
3865 HValue* context = environment()->LookupContext(); | 3872 HValue* context = environment()->context(); |
3866 HFunctionLiteral* instr = | 3873 HFunctionLiteral* instr = |
3867 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 3874 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
3868 return ast_context()->ReturnInstruction(instr, expr->id()); | 3875 return ast_context()->ReturnInstruction(instr, expr->id()); |
3869 } | 3876 } |
3870 | 3877 |
3871 | 3878 |
3872 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 3879 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
3873 SharedFunctionInfoLiteral* expr) { | 3880 SharedFunctionInfoLiteral* expr) { |
3874 ASSERT(!HasStackOverflow()); | 3881 ASSERT(!HasStackOverflow()); |
3875 ASSERT(current_block() != NULL); | 3882 ASSERT(current_block() != NULL); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3929 lookup->holder() != *global) { | 3936 lookup->holder() != *global) { |
3930 return kUseGeneric; | 3937 return kUseGeneric; |
3931 } | 3938 } |
3932 | 3939 |
3933 return kUseCell; | 3940 return kUseCell; |
3934 } | 3941 } |
3935 | 3942 |
3936 | 3943 |
3937 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 3944 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
3938 ASSERT(var->IsContextSlot()); | 3945 ASSERT(var->IsContextSlot()); |
3939 HValue* context = environment()->LookupContext(); | 3946 HValue* context = environment()->context(); |
3940 int length = current_info()->scope()->ContextChainLength(var->scope()); | 3947 int length = current_info()->scope()->ContextChainLength(var->scope()); |
3941 while (length-- > 0) { | 3948 while (length-- > 0) { |
3942 context = Add<HOuterContext>(context); | 3949 context = Add<HOuterContext>(context); |
3943 } | 3950 } |
3944 return context; | 3951 return context; |
3945 } | 3952 } |
3946 | 3953 |
3947 | 3954 |
3948 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 3955 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
3949 ASSERT(!HasStackOverflow()); | 3956 ASSERT(!HasStackOverflow()); |
3950 ASSERT(current_block() != NULL); | 3957 ASSERT(current_block() != NULL); |
3951 ASSERT(current_block()->HasPredecessor()); | 3958 ASSERT(current_block()->HasPredecessor()); |
3952 Variable* variable = expr->var(); | 3959 Variable* variable = expr->var(); |
3953 switch (variable->location()) { | 3960 switch (variable->location()) { |
3954 case Variable::UNALLOCATED: { | 3961 case Variable::UNALLOCATED: { |
3955 if (IsLexicalVariableMode(variable->mode())) { | 3962 if (IsLexicalVariableMode(variable->mode())) { |
3956 // TODO(rossberg): should this be an ASSERT? | 3963 // TODO(rossberg): should this be an ASSERT? |
3957 return Bailout("reference to global lexical variable"); | 3964 return Bailout("reference to global lexical variable"); |
3958 } | 3965 } |
3959 // Handle known global constants like 'undefined' specially to avoid a | 3966 // Handle known global constants like 'undefined' specially to avoid a |
3960 // load from a global cell for them. | 3967 // load from a global cell for them. |
3961 Handle<Object> constant_value = | 3968 Handle<Object> constant_value = |
3962 isolate()->factory()->GlobalConstantFor(variable->name()); | 3969 isolate()->factory()->GlobalConstantFor(variable->name()); |
3963 if (!constant_value.is_null()) { | 3970 if (!constant_value.is_null()) { |
3964 HConstant* instr = new(zone()) HConstant(constant_value); | 3971 HConstant* instr = NewAndCast<HConstant>(constant_value); |
3965 return ast_context()->ReturnInstruction(instr, expr->id()); | 3972 return ast_context()->ReturnInstruction(instr, expr->id()); |
3966 } | 3973 } |
3967 | 3974 |
3968 LookupResult lookup(isolate()); | 3975 LookupResult lookup(isolate()); |
3969 GlobalPropertyAccess type = | 3976 GlobalPropertyAccess type = |
3970 LookupGlobalProperty(variable, &lookup, false); | 3977 LookupGlobalProperty(variable, &lookup, false); |
3971 | 3978 |
3972 if (type == kUseCell && | 3979 if (type == kUseCell && |
3973 current_info()->global_object()->IsAccessCheckNeeded()) { | 3980 current_info()->global_object()->IsAccessCheckNeeded()) { |
3974 type = kUseGeneric; | 3981 type = kUseGeneric; |
3975 } | 3982 } |
3976 | 3983 |
3977 if (type == kUseCell) { | 3984 if (type == kUseCell) { |
3978 Handle<GlobalObject> global(current_info()->global_object()); | 3985 Handle<GlobalObject> global(current_info()->global_object()); |
3979 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 3986 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
3980 if (cell->type()->IsConstant()) { | 3987 if (cell->type()->IsConstant()) { |
3981 cell->AddDependentCompilationInfo(top_info()); | 3988 cell->AddDependentCompilationInfo(top_info()); |
3982 Handle<Object> constant_object = cell->type()->AsConstant(); | 3989 Handle<Object> constant_object = cell->type()->AsConstant(); |
3983 if (constant_object->IsConsString()) { | 3990 if (constant_object->IsConsString()) { |
3984 constant_object = | 3991 constant_object = |
3985 FlattenGetString(Handle<String>::cast(constant_object)); | 3992 FlattenGetString(Handle<String>::cast(constant_object)); |
3986 } | 3993 } |
3987 HConstant* constant = new(zone()) HConstant(constant_object); | 3994 HConstant* constant = NewAndCast<HConstant>(constant_object); |
3988 return ast_context()->ReturnInstruction(constant, expr->id()); | 3995 return ast_context()->ReturnInstruction(constant, expr->id()); |
3989 } else { | 3996 } else { |
3990 HLoadGlobalCell* instr = | 3997 HLoadGlobalCell* instr = |
3991 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 3998 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
3992 return ast_context()->ReturnInstruction(instr, expr->id()); | 3999 return ast_context()->ReturnInstruction(instr, expr->id()); |
3993 } | 4000 } |
3994 } else { | 4001 } else { |
3995 HValue* context = environment()->LookupContext(); | 4002 HValue* context = environment()->context(); |
3996 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4003 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
3997 AddInstruction(global_object); | 4004 AddInstruction(global_object); |
3998 HLoadGlobalGeneric* instr = | 4005 HLoadGlobalGeneric* instr = |
3999 new(zone()) HLoadGlobalGeneric(context, | 4006 new(zone()) HLoadGlobalGeneric(context, |
4000 global_object, | 4007 global_object, |
4001 variable->name(), | 4008 variable->name(), |
4002 ast_context()->is_for_typeof()); | 4009 ast_context()->is_for_typeof()); |
4003 instr->set_position(expr->position()); | 4010 instr->set_position(expr->position()); |
4004 return ast_context()->ReturnInstruction(instr, expr->id()); | 4011 return ast_context()->ReturnInstruction(instr, expr->id()); |
4005 } | 4012 } |
(...skipping 19 matching lines...) Expand all Loading... |
4025 case Variable::LOOKUP: | 4032 case Variable::LOOKUP: |
4026 return Bailout("reference to a variable which requires dynamic lookup"); | 4033 return Bailout("reference to a variable which requires dynamic lookup"); |
4027 } | 4034 } |
4028 } | 4035 } |
4029 | 4036 |
4030 | 4037 |
4031 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 4038 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
4032 ASSERT(!HasStackOverflow()); | 4039 ASSERT(!HasStackOverflow()); |
4033 ASSERT(current_block() != NULL); | 4040 ASSERT(current_block() != NULL); |
4034 ASSERT(current_block()->HasPredecessor()); | 4041 ASSERT(current_block()->HasPredecessor()); |
4035 HConstant* instr = new(zone()) HConstant(expr->value()); | 4042 HConstant* instr = NewAndCast<HConstant>(expr->value()); |
4036 return ast_context()->ReturnInstruction(instr, expr->id()); | 4043 return ast_context()->ReturnInstruction(instr, expr->id()); |
4037 } | 4044 } |
4038 | 4045 |
4039 | 4046 |
4040 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4047 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
4041 ASSERT(!HasStackOverflow()); | 4048 ASSERT(!HasStackOverflow()); |
4042 ASSERT(current_block() != NULL); | 4049 ASSERT(current_block() != NULL); |
4043 ASSERT(current_block()->HasPredecessor()); | 4050 ASSERT(current_block()->HasPredecessor()); |
4044 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4051 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4045 Handle<FixedArray> literals(closure->literals()); | 4052 Handle<FixedArray> literals(closure->literals()); |
4046 HValue* context = environment()->LookupContext(); | 4053 HValue* context = environment()->context(); |
4047 | 4054 |
4048 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4055 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
4049 literals, | 4056 literals, |
4050 expr->pattern(), | 4057 expr->pattern(), |
4051 expr->flags(), | 4058 expr->flags(), |
4052 expr->literal_index()); | 4059 expr->literal_index()); |
4053 return ast_context()->ReturnInstruction(instr, expr->id()); | 4060 return ast_context()->ReturnInstruction(instr, expr->id()); |
4054 } | 4061 } |
4055 | 4062 |
4056 | 4063 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4213 *pointer_size += boilerplate->map()->instance_size(); | 4220 *pointer_size += boilerplate->map()->instance_size(); |
4214 return true; | 4221 return true; |
4215 } | 4222 } |
4216 | 4223 |
4217 | 4224 |
4218 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4225 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
4219 ASSERT(!HasStackOverflow()); | 4226 ASSERT(!HasStackOverflow()); |
4220 ASSERT(current_block() != NULL); | 4227 ASSERT(current_block() != NULL); |
4221 ASSERT(current_block()->HasPredecessor()); | 4228 ASSERT(current_block()->HasPredecessor()); |
4222 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4229 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4223 HValue* context = environment()->LookupContext(); | 4230 HValue* context = environment()->context(); |
4224 HInstruction* literal; | 4231 HInstruction* literal; |
4225 | 4232 |
4226 // Check whether to use fast or slow deep-copying for boilerplate. | 4233 // Check whether to use fast or slow deep-copying for boilerplate. |
4227 int data_size = 0; | 4234 int data_size = 0; |
4228 int pointer_size = 0; | 4235 int pointer_size = 0; |
4229 int max_properties = kMaxFastLiteralProperties; | 4236 int max_properties = kMaxFastLiteralProperties; |
4230 Handle<Object> original_boilerplate(closure->literals()->get( | 4237 Handle<Object> original_boilerplate(closure->literals()->get( |
4231 expr->literal_index()), isolate()); | 4238 expr->literal_index()), isolate()); |
4232 if (original_boilerplate->IsJSObject() && | 4239 if (original_boilerplate->IsJSObject() && |
4233 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | 4240 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), |
(...skipping 24 matching lines...) Expand all Loading... |
4258 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 4265 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
4259 | 4266 |
4260 Add<HPushArgument>(Add<HConstant>(closure_literals)); | 4267 Add<HPushArgument>(Add<HConstant>(closure_literals)); |
4261 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4268 Add<HPushArgument>(Add<HConstant>(literal_index)); |
4262 Add<HPushArgument>(Add<HConstant>(constant_properties)); | 4269 Add<HPushArgument>(Add<HConstant>(constant_properties)); |
4263 Add<HPushArgument>(Add<HConstant>(flags)); | 4270 Add<HPushArgument>(Add<HConstant>(flags)); |
4264 | 4271 |
4265 Runtime::FunctionId function_id = | 4272 Runtime::FunctionId function_id = |
4266 (expr->depth() > 1 || expr->may_store_doubles()) | 4273 (expr->depth() > 1 || expr->may_store_doubles()) |
4267 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; | 4274 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; |
4268 literal = Add<HCallRuntime>(context, | 4275 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4269 isolate()->factory()->empty_string(), | |
4270 Runtime::FunctionForId(function_id), | 4276 Runtime::FunctionForId(function_id), |
4271 4); | 4277 4); |
4272 } | 4278 } |
4273 | 4279 |
4274 // The object is expected in the bailout environment during computation | 4280 // The object is expected in the bailout environment during computation |
4275 // of the property values and is the value of the entire expression. | 4281 // of the property values and is the value of the entire expression. |
4276 Push(literal); | 4282 Push(literal); |
4277 | 4283 |
4278 expr->CalculateEmitStore(zone()); | 4284 expr->CalculateEmitStore(zone()); |
4279 | 4285 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4327 default: UNREACHABLE(); | 4333 default: UNREACHABLE(); |
4328 } | 4334 } |
4329 } | 4335 } |
4330 | 4336 |
4331 if (expr->has_function()) { | 4337 if (expr->has_function()) { |
4332 // Return the result of the transformation to fast properties | 4338 // Return the result of the transformation to fast properties |
4333 // instead of the original since this operation changes the map | 4339 // instead of the original since this operation changes the map |
4334 // of the object. This makes sure that the original object won't | 4340 // of the object. This makes sure that the original object won't |
4335 // be used by other optimized code before it is transformed | 4341 // be used by other optimized code before it is transformed |
4336 // (e.g. because of code motion). | 4342 // (e.g. because of code motion). |
4337 HToFastProperties* result = Add<HToFastProperties>(Pop()); | 4343 HToFastProperties* result = AddAndCast<HToFastProperties>(Pop()); |
4338 return ast_context()->ReturnValue(result); | 4344 return ast_context()->ReturnValue(result); |
4339 } else { | 4345 } else { |
4340 return ast_context()->ReturnValue(Pop()); | 4346 return ast_context()->ReturnValue(Pop()); |
4341 } | 4347 } |
4342 } | 4348 } |
4343 | 4349 |
4344 | 4350 |
4345 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4351 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
4346 ASSERT(!HasStackOverflow()); | 4352 ASSERT(!HasStackOverflow()); |
4347 ASSERT(current_block() != NULL); | 4353 ASSERT(current_block() != NULL); |
4348 ASSERT(current_block()->HasPredecessor()); | 4354 ASSERT(current_block()->HasPredecessor()); |
4349 ZoneList<Expression*>* subexprs = expr->values(); | 4355 ZoneList<Expression*>* subexprs = expr->values(); |
4350 int length = subexprs->length(); | 4356 int length = subexprs->length(); |
4351 HValue* context = environment()->LookupContext(); | 4357 HValue* context = environment()->context(); |
4352 HInstruction* literal; | 4358 HInstruction* literal; |
4353 | 4359 |
4354 Handle<AllocationSite> site; | 4360 Handle<AllocationSite> site; |
4355 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4361 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
4356 bool uninitialized = false; | 4362 bool uninitialized = false; |
4357 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4363 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
4358 isolate()); | 4364 isolate()); |
4359 Handle<Object> raw_boilerplate; | 4365 Handle<Object> raw_boilerplate; |
4360 if (literals_cell->IsUndefined()) { | 4366 if (literals_cell->IsUndefined()) { |
4361 uninitialized = true; | 4367 uninitialized = true; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4420 // pass an empty fixed array to the runtime function instead. | 4426 // pass an empty fixed array to the runtime function instead. |
4421 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4427 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
4422 int literal_index = expr->literal_index(); | 4428 int literal_index = expr->literal_index(); |
4423 | 4429 |
4424 Add<HPushArgument>(Add<HConstant>(literals)); | 4430 Add<HPushArgument>(Add<HConstant>(literals)); |
4425 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4431 Add<HPushArgument>(Add<HConstant>(literal_index)); |
4426 Add<HPushArgument>(Add<HConstant>(constants)); | 4432 Add<HPushArgument>(Add<HConstant>(constants)); |
4427 | 4433 |
4428 Runtime::FunctionId function_id = (expr->depth() > 1) | 4434 Runtime::FunctionId function_id = (expr->depth() > 1) |
4429 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4435 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
4430 literal = Add<HCallRuntime>(context, | 4436 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4431 isolate()->factory()->empty_string(), | |
4432 Runtime::FunctionForId(function_id), | 4437 Runtime::FunctionForId(function_id), |
4433 3); | 4438 3); |
4434 | 4439 |
4435 // De-opt if elements kind changed from boilerplate_elements_kind. | 4440 // De-opt if elements kind changed from boilerplate_elements_kind. |
4436 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4441 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
4437 isolate()); | 4442 isolate()); |
4438 AddInstruction(HCheckMaps::New(literal, map, zone(), top_info())); | 4443 AddInstruction(HCheckMaps::New(literal, map, zone(), top_info())); |
4439 } | 4444 } |
4440 | 4445 |
4441 // The array is expected in the bailout environment during computation | 4446 // The array is expected in the bailout environment during computation |
(...skipping 18 matching lines...) Expand all Loading... |
4460 | 4465 |
4461 HValue* key = Add<HConstant>(i); | 4466 HValue* key = Add<HConstant>(i); |
4462 | 4467 |
4463 switch (boilerplate_elements_kind) { | 4468 switch (boilerplate_elements_kind) { |
4464 case FAST_SMI_ELEMENTS: | 4469 case FAST_SMI_ELEMENTS: |
4465 case FAST_HOLEY_SMI_ELEMENTS: | 4470 case FAST_HOLEY_SMI_ELEMENTS: |
4466 case FAST_ELEMENTS: | 4471 case FAST_ELEMENTS: |
4467 case FAST_HOLEY_ELEMENTS: | 4472 case FAST_HOLEY_ELEMENTS: |
4468 case FAST_DOUBLE_ELEMENTS: | 4473 case FAST_DOUBLE_ELEMENTS: |
4469 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 4474 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
4470 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, | 4475 HStoreKeyed* instr = AddAndCast<HStoreKeyed>(elements, key, value, |
4471 boilerplate_elements_kind); | 4476 boilerplate_elements_kind); |
4472 instr->SetUninitialized(uninitialized); | 4477 instr->SetUninitialized(uninitialized); |
4473 break; | 4478 break; |
4474 } | 4479 } |
4475 default: | 4480 default: |
4476 UNREACHABLE(); | 4481 UNREACHABLE(); |
4477 break; | 4482 break; |
4478 } | 4483 } |
4479 | 4484 |
4480 Add<HSimulate>(expr->GetIdForElement(i)); | 4485 Add<HSimulate>(expr->GetIdForElement(i)); |
4481 } | 4486 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4548 // We only need to check up to the preexisting property. | 4553 // We only need to check up to the preexisting property. |
4549 proto = proto_result.holder(); | 4554 proto = proto_result.holder(); |
4550 } else { | 4555 } else { |
4551 // Otherwise, find the top prototype. | 4556 // Otherwise, find the top prototype. |
4552 while (proto->GetPrototype(isolate())->IsJSObject()) { | 4557 while (proto->GetPrototype(isolate())->IsJSObject()) { |
4553 proto = proto->GetPrototype(isolate()); | 4558 proto = proto->GetPrototype(isolate()); |
4554 } | 4559 } |
4555 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4560 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
4556 } | 4561 } |
4557 ASSERT(proto->IsJSObject()); | 4562 ASSERT(proto->IsJSObject()); |
4558 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), | 4563 Add<HCheckPrototypeMaps>( |
4559 Handle<JSObject>(JSObject::cast(proto)), | 4564 Handle<JSObject>(JSObject::cast(map->prototype())), |
4560 zone(), top_info()); | 4565 Handle<JSObject>(JSObject::cast(proto)), top_info()); |
4561 } | 4566 } |
4562 | 4567 |
4563 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4568 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
4564 bool transition_to_field = lookup->IsTransitionToField(*map); | 4569 bool transition_to_field = lookup->IsTransitionToField(*map); |
4565 | 4570 |
4566 HStoreNamedField *instr; | 4571 HStoreNamedField *instr; |
4567 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { | 4572 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
4568 HObjectAccess heap_number_access = | 4573 HObjectAccess heap_number_access = |
4569 field_access.WithRepresentation(Representation::Tagged()); | 4574 field_access.WithRepresentation(Representation::Tagged()); |
4570 if (transition_to_field) { | 4575 if (transition_to_field) { |
4571 // The store requires a mutable HeapNumber to be allocated. | 4576 // The store requires a mutable HeapNumber to be allocated. |
4572 NoObservableSideEffectsScope no_side_effects(this); | 4577 NoObservableSideEffectsScope no_side_effects(this); |
4573 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 4578 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
4574 HInstruction* heap_number = Add<HAllocate>( | 4579 HInstruction* heap_number = Add<HAllocate>(heap_number_size, |
4575 environment()->LookupContext(), heap_number_size, | |
4576 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); | 4580 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE); |
4577 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); | 4581 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
4578 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); | 4582 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), |
4579 instr = new(zone()) HStoreNamedField( | 4583 value); |
4580 object, heap_number_access, heap_number); | 4584 instr = NewAndCast<HStoreNamedField>(object, heap_number_access, |
| 4585 heap_number); |
4581 } else { | 4586 } else { |
4582 // Already holds a HeapNumber; load the box and write its value field. | 4587 // Already holds a HeapNumber; load the box and write its value field. |
4583 HInstruction* heap_number = AddLoad(object, heap_number_access); | 4588 HInstruction* heap_number = Add<HLoadNamedField>(object, |
| 4589 heap_number_access); |
4584 heap_number->set_type(HType::HeapNumber()); | 4590 heap_number->set_type(HType::HeapNumber()); |
4585 instr = new(zone()) HStoreNamedField(heap_number, | 4591 instr = NewAndCast<HStoreNamedField>(heap_number, |
4586 HObjectAccess::ForHeapNumberValue(), value); | 4592 HObjectAccess::ForHeapNumberValue(), |
| 4593 value); |
4587 } | 4594 } |
4588 } else { | 4595 } else { |
4589 // This is a normal store. | 4596 // This is a normal store. |
4590 instr = new(zone()) HStoreNamedField(object, field_access, value); | 4597 instr = NewAndCast<HStoreNamedField>(object, field_access, value); |
4591 } | 4598 } |
4592 | 4599 |
4593 if (transition_to_field) { | 4600 if (transition_to_field) { |
4594 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4601 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4595 instr->SetTransition(transition, top_info()); | 4602 instr->SetTransition(transition, top_info()); |
4596 // TODO(fschneider): Record the new map type of the object in the IR to | 4603 // TODO(fschneider): Record the new map type of the object in the IR to |
4597 // enable elimination of redundant checks after the transition store. | 4604 // enable elimination of redundant checks after the transition store. |
4598 instr->SetGVNFlag(kChangesMaps); | 4605 instr->SetGVNFlag(kChangesMaps); |
4599 } | 4606 } |
4600 return instr; | 4607 return instr; |
4601 } | 4608 } |
4602 | 4609 |
4603 | 4610 |
4604 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 4611 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
4605 HValue* object, | 4612 HValue* object, |
4606 Handle<String> name, | 4613 Handle<String> name, |
4607 HValue* value) { | 4614 HValue* value) { |
4608 HValue* context = environment()->LookupContext(); | 4615 HValue* context = environment()->context(); |
4609 return new(zone()) HStoreNamedGeneric( | 4616 return new(zone()) HStoreNamedGeneric( |
4610 context, | 4617 context, |
4611 object, | 4618 object, |
4612 name, | 4619 name, |
4613 value, | 4620 value, |
4614 function_strict_mode_flag()); | 4621 function_strict_mode_flag()); |
4615 } | 4622 } |
4616 | 4623 |
4617 | 4624 |
4618 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 4625 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4701 } | 4708 } |
4702 | 4709 |
4703 LookupInPrototypes(map, name, &lookup); | 4710 LookupInPrototypes(map, name, &lookup); |
4704 if (!lookup.IsField()) return NULL; | 4711 if (!lookup.IsField()) return NULL; |
4705 | 4712 |
4706 BuildCheckHeapObject(object); | 4713 BuildCheckHeapObject(object); |
4707 AddInstruction(HCheckMaps::New(object, types, zone())); | 4714 AddInstruction(HCheckMaps::New(object, types, zone())); |
4708 | 4715 |
4709 Handle<JSObject> holder(lookup.holder()); | 4716 Handle<JSObject> holder(lookup.holder()); |
4710 Handle<Map> holder_map(holder->map()); | 4717 Handle<Map> holder_map(holder->map()); |
4711 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4718 Add<HCheckPrototypeMaps>( |
4712 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); | 4719 Handle<JSObject>::cast(prototype), holder, top_info()); |
4713 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); | 4720 HValue* holder_value = Add<HConstant>(holder); |
4714 return BuildLoadNamedField(holder_value, | 4721 return BuildLoadNamedField(holder_value, |
4715 HObjectAccess::ForField(holder_map, &lookup, name)); | 4722 HObjectAccess::ForField(holder_map, &lookup, name)); |
4716 } | 4723 } |
4717 | 4724 |
4718 | 4725 |
4719 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4726 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4720 Property* expr, | 4727 Property* expr, |
4721 HValue* object, | 4728 HValue* object, |
4722 SmallMapList* types, | 4729 SmallMapList* types, |
4723 Handle<String> name) { | 4730 Handle<String> name) { |
4724 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 4731 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
4725 expr, object, types, name); | 4732 expr, object, types, name); |
4726 if (instr == NULL) { | 4733 if (instr == NULL) { |
4727 // Something did not match; must use a polymorphic load. | 4734 // Something did not match; must use a polymorphic load. |
4728 BuildCheckHeapObject(object); | 4735 BuildCheckHeapObject(object); |
4729 HValue* context = environment()->LookupContext(); | 4736 HValue* context = environment()->context(); |
4730 instr = new(zone()) HLoadNamedFieldPolymorphic( | 4737 instr = new(zone()) HLoadNamedFieldPolymorphic( |
4731 context, object, types, name, zone()); | 4738 context, object, types, name, zone()); |
4732 } | 4739 } |
4733 | 4740 |
4734 instr->set_position(expr->position()); | 4741 instr->set_position(expr->position()); |
4735 return ast_context()->ReturnInstruction(instr, expr->id()); | 4742 return ast_context()->ReturnInstruction(instr, expr->id()); |
4736 } | 4743 } |
4737 | 4744 |
4738 | 4745 |
4739 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4746 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4948 Add<HDeoptimize>(Deoptimizer::EAGER); | 4955 Add<HDeoptimize>(Deoptimizer::EAGER); |
4949 builder.End(); | 4956 builder.End(); |
4950 } | 4957 } |
4951 HInstruction* instr = | 4958 HInstruction* instr = |
4952 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4959 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
4953 instr->set_position(position); | 4960 instr->set_position(position); |
4954 if (instr->HasObservableSideEffects()) { | 4961 if (instr->HasObservableSideEffects()) { |
4955 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4962 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4956 } | 4963 } |
4957 } else { | 4964 } else { |
4958 HValue* context = environment()->LookupContext(); | 4965 HGlobalObject* global_object = AddAndCast<HGlobalObject>(); |
4959 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
4960 HStoreGlobalGeneric* instr = | 4966 HStoreGlobalGeneric* instr = |
4961 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 4967 AddAndCast<HStoreGlobalGeneric>(global_object, var->name(), |
4962 value, function_strict_mode_flag()); | 4968 value, function_strict_mode_flag()); |
4963 instr->set_position(position); | 4969 instr->set_position(position); |
4964 ASSERT(instr->HasObservableSideEffects()); | 4970 ASSERT(instr->HasObservableSideEffects()); |
4965 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4971 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4966 } | 4972 } |
4967 } | 4973 } |
4968 | 4974 |
4969 | 4975 |
4970 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4976 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
4971 BailoutId id, | 4977 BailoutId id, |
4972 int position, | 4978 int position, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5092 return ast_context()->ReturnValue(Pop()); | 5098 return ast_context()->ReturnValue(Pop()); |
5093 case CONST_HARMONY: | 5099 case CONST_HARMONY: |
5094 // This case is checked statically so no need to | 5100 // This case is checked statically so no need to |
5095 // perform checks here | 5101 // perform checks here |
5096 UNREACHABLE(); | 5102 UNREACHABLE(); |
5097 default: | 5103 default: |
5098 mode = HStoreContextSlot::kNoCheck; | 5104 mode = HStoreContextSlot::kNoCheck; |
5099 } | 5105 } |
5100 | 5106 |
5101 HValue* context = BuildContextChainWalk(var); | 5107 HValue* context = BuildContextChainWalk(var); |
5102 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5108 HStoreContextSlot* instr = AddAndCast<HStoreContextSlot>( |
5103 mode, Top()); | 5109 context, var->index(), mode, Top()); |
5104 if (instr->HasObservableSideEffects()) { | 5110 if (instr->HasObservableSideEffects()) { |
5105 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5111 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5106 } | 5112 } |
5107 break; | 5113 break; |
5108 } | 5114 } |
5109 | 5115 |
5110 case Variable::LOOKUP: | 5116 case Variable::LOOKUP: |
5111 return Bailout("compound assignment to lookup slot"); | 5117 return Bailout("compound assignment to lookup slot"); |
5112 } | 5118 } |
5113 return ast_context()->ReturnValue(Pop()); | 5119 return ast_context()->ReturnValue(Pop()); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5304 expr->op() == Token::INIT_LET || | 5310 expr->op() == Token::INIT_LET || |
5305 expr->op() == Token::INIT_CONST_HARMONY) { | 5311 expr->op() == Token::INIT_CONST_HARMONY) { |
5306 mode = HStoreContextSlot::kNoCheck; | 5312 mode = HStoreContextSlot::kNoCheck; |
5307 } else { | 5313 } else { |
5308 ASSERT(expr->op() == Token::INIT_CONST); | 5314 ASSERT(expr->op() == Token::INIT_CONST); |
5309 | 5315 |
5310 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5316 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
5311 } | 5317 } |
5312 | 5318 |
5313 HValue* context = BuildContextChainWalk(var); | 5319 HValue* context = BuildContextChainWalk(var); |
5314 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5320 HStoreContextSlot* instr = AddAndCast<HStoreContextSlot>( |
5315 mode, Top()); | 5321 context, var->index(), mode, Top()); |
5316 if (instr->HasObservableSideEffects()) { | 5322 if (instr->HasObservableSideEffects()) { |
5317 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5323 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5318 } | 5324 } |
5319 return ast_context()->ReturnValue(Pop()); | 5325 return ast_context()->ReturnValue(Pop()); |
5320 } | 5326 } |
5321 | 5327 |
5322 case Variable::LOOKUP: | 5328 case Variable::LOOKUP: |
5323 return Bailout("assignment to LOOKUP variable"); | 5329 return Bailout("assignment to LOOKUP variable"); |
5324 } | 5330 } |
5325 } else { | 5331 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
5337 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 5343 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { |
5338 ASSERT(!HasStackOverflow()); | 5344 ASSERT(!HasStackOverflow()); |
5339 ASSERT(current_block() != NULL); | 5345 ASSERT(current_block() != NULL); |
5340 ASSERT(current_block()->HasPredecessor()); | 5346 ASSERT(current_block()->HasPredecessor()); |
5341 // We don't optimize functions with invalid left-hand sides in | 5347 // We don't optimize functions with invalid left-hand sides in |
5342 // assignments, count operations, or for-in. Consequently throw can | 5348 // assignments, count operations, or for-in. Consequently throw can |
5343 // currently only occur in an effect context. | 5349 // currently only occur in an effect context. |
5344 ASSERT(ast_context()->IsEffect()); | 5350 ASSERT(ast_context()->IsEffect()); |
5345 CHECK_ALIVE(VisitForValue(expr->exception())); | 5351 CHECK_ALIVE(VisitForValue(expr->exception())); |
5346 | 5352 |
5347 HValue* context = environment()->LookupContext(); | |
5348 HValue* value = environment()->Pop(); | 5353 HValue* value = environment()->Pop(); |
5349 HThrow* instr = Add<HThrow>(context, value); | 5354 HThrow* instr = AddAndCast<HThrow>(value); |
5350 instr->set_position(expr->position()); | 5355 instr->set_position(expr->position()); |
5351 Add<HSimulate>(expr->id()); | 5356 Add<HSimulate>(expr->id()); |
5352 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5357 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5353 set_current_block(NULL); | 5358 set_current_block(NULL); |
5354 } | 5359 } |
5355 | 5360 |
5356 | 5361 |
5357 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5362 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5358 HObjectAccess access) { | 5363 HObjectAccess access) { |
5359 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5364 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
5360 // load the heap number | 5365 // load the heap number |
5361 HLoadNamedField* heap_number = | 5366 HLoadNamedField* heap_number = AddAndCast<HLoadNamedField>( |
5362 AddLoad(object, access.WithRepresentation(Representation::Tagged())); | 5367 object, access.WithRepresentation(Representation::Tagged())); |
5363 heap_number->set_type(HType::HeapNumber()); | 5368 heap_number->set_type(HType::HeapNumber()); |
5364 // load the double value from it | 5369 // load the double value from it |
5365 return new(zone()) HLoadNamedField(heap_number, | 5370 return NewAndCast<HLoadNamedField>(heap_number, |
5366 HObjectAccess::ForHeapNumberValue(), NULL); | 5371 HObjectAccess::ForHeapNumberValue()); |
5367 } | 5372 } |
5368 return new(zone()) HLoadNamedField(object, access, NULL); | 5373 return NewAndCast<HLoadNamedField>(object, access); |
5369 } | 5374 } |
5370 | 5375 |
5371 | 5376 |
5372 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5377 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5373 HValue* object, | 5378 HValue* object, |
5374 Handle<String> name, | 5379 Handle<String> name, |
5375 Property* expr) { | 5380 Property* expr) { |
5376 if (expr->IsUninitialized()) { | 5381 if (expr->IsUninitialized()) { |
5377 Add<HDeoptimize>(Deoptimizer::SOFT); | 5382 Add<HDeoptimize>(Deoptimizer::SOFT); |
5378 } | 5383 } |
5379 HValue* context = environment()->LookupContext(); | 5384 HValue* context = environment()->context(); |
5380 return new(zone()) HLoadNamedGeneric(context, object, name); | 5385 return new(zone()) HLoadNamedGeneric(context, object, name); |
5381 } | 5386 } |
5382 | 5387 |
5383 | 5388 |
5384 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5389 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
5385 HValue* object, | 5390 HValue* object, |
5386 Handle<Map> map, | 5391 Handle<Map> map, |
5387 Handle<JSFunction> getter, | 5392 Handle<JSFunction> getter, |
5388 Handle<JSObject> holder) { | 5393 Handle<JSObject> holder) { |
5389 AddCheckConstantFunction(holder, object, map); | 5394 AddCheckConstantFunction(holder, object, map); |
5390 Add<HPushArgument>(object); | 5395 Add<HPushArgument>(object); |
5391 return new(zone()) HCallConstantFunction(getter, 1); | 5396 return new(zone()) HCallConstantFunction(getter, 1); |
5392 } | 5397 } |
5393 | 5398 |
5394 | 5399 |
5395 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5400 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
5396 HValue* object, | 5401 HValue* object, |
5397 Handle<String> name, | 5402 Handle<String> name, |
5398 Property* expr, | 5403 Property* expr, |
5399 Handle<Map> map) { | 5404 Handle<Map> map) { |
5400 // Handle a load from a known field. | 5405 // Handle a load from a known field. |
5401 ASSERT(!map->is_dictionary_map()); | 5406 ASSERT(!map->is_dictionary_map()); |
5402 | 5407 |
5403 // Handle access to various length properties | 5408 // Handle access to various length properties |
5404 if (name->Equals(isolate()->heap()->length_string())) { | 5409 if (name->Equals(isolate()->heap()->length_string())) { |
5405 if (map->instance_type() == JS_ARRAY_TYPE) { | 5410 if (map->instance_type() == JS_ARRAY_TYPE) { |
5406 AddCheckMapsWithTransitions(object, map); | 5411 AddCheckMapsWithTransitions(object, map); |
5407 return new(zone()) HLoadNamedField(object, | 5412 return New<HLoadNamedField>(object, |
5408 HObjectAccess::ForArrayLength(map->elements_kind())); | 5413 HObjectAccess::ForArrayLength(map->elements_kind())); |
5409 } | 5414 } |
5410 } | 5415 } |
5411 | 5416 |
5412 LookupResult lookup(isolate()); | 5417 LookupResult lookup(isolate()); |
5413 map->LookupDescriptor(NULL, *name, &lookup); | 5418 map->LookupDescriptor(NULL, *name, &lookup); |
5414 if (lookup.IsField()) { | 5419 if (lookup.IsField()) { |
5415 AddCheckMap(object, map); | 5420 AddCheckMap(object, map); |
5416 return BuildLoadNamedField(object, | 5421 return BuildLoadNamedField(object, |
5417 HObjectAccess::ForField(map, &lookup, name)); | 5422 HObjectAccess::ForField(map, &lookup, name)); |
5418 } | 5423 } |
5419 | 5424 |
5420 // Handle a load of a constant known function. | 5425 // Handle a load of a constant known function. |
5421 if (lookup.IsConstant()) { | 5426 if (lookup.IsConstant()) { |
5422 AddCheckMap(object, map); | 5427 AddCheckMap(object, map); |
5423 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5428 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
5424 return new(zone()) HConstant(constant); | 5429 return New<HConstant>(constant); |
5425 } | 5430 } |
5426 | 5431 |
5427 // Handle a load from a known field somewhere in the prototype chain. | 5432 // Handle a load from a known field somewhere in the prototype chain. |
5428 LookupInPrototypes(map, name, &lookup); | 5433 LookupInPrototypes(map, name, &lookup); |
5429 if (lookup.IsField()) { | 5434 if (lookup.IsField()) { |
5430 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5435 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5431 Handle<JSObject> holder(lookup.holder()); | 5436 Handle<JSObject> holder(lookup.holder()); |
5432 Handle<Map> holder_map(holder->map()); | 5437 Handle<Map> holder_map(holder->map()); |
5433 AddCheckMap(object, map); | 5438 AddCheckMap(object, map); |
5434 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5439 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5435 HValue* holder_value = Add<HConstant>(holder); | 5440 HValue* holder_value = Add<HConstant>(holder); |
5436 return BuildLoadNamedField(holder_value, | 5441 return BuildLoadNamedField(holder_value, |
5437 HObjectAccess::ForField(holder_map, &lookup, name)); | 5442 HObjectAccess::ForField(holder_map, &lookup, name)); |
5438 } | 5443 } |
5439 | 5444 |
5440 // Handle a load of a constant function somewhere in the prototype chain. | 5445 // Handle a load of a constant function somewhere in the prototype chain. |
5441 if (lookup.IsConstant()) { | 5446 if (lookup.IsConstant()) { |
5442 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5447 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5443 Handle<JSObject> holder(lookup.holder()); | 5448 Handle<JSObject> holder(lookup.holder()); |
5444 Handle<Map> holder_map(holder->map()); | 5449 Handle<Map> holder_map(holder->map()); |
5445 AddCheckMap(object, map); | 5450 AddCheckMap(object, map); |
5446 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5451 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5447 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5452 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
5448 return new(zone()) HConstant(constant); | 5453 return New<HConstant>(constant); |
5449 } | 5454 } |
5450 | 5455 |
5451 // No luck, do a generic load. | 5456 // No luck, do a generic load. |
5452 return BuildLoadNamedGeneric(object, name, expr); | 5457 return BuildLoadNamedGeneric(object, name, expr); |
5453 } | 5458 } |
5454 | 5459 |
5455 | 5460 |
5456 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5461 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
5457 HValue* key) { | 5462 HValue* key) { |
5458 HValue* context = environment()->LookupContext(); | 5463 HValue* context = environment()->context(); |
5459 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5464 return new(zone()) HLoadKeyedGeneric(context, object, key); |
5460 } | 5465 } |
5461 | 5466 |
5462 | 5467 |
5463 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 5468 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
5464 HValue* object, | 5469 HValue* object, |
5465 HValue* key, | 5470 HValue* key, |
5466 HValue* val, | 5471 HValue* val, |
5467 HValue* dependency, | 5472 HValue* dependency, |
5468 Handle<Map> map, | 5473 Handle<Map> map, |
5469 bool is_store, | 5474 bool is_store, |
5470 KeyedAccessStoreMode store_mode) { | 5475 KeyedAccessStoreMode store_mode) { |
5471 HCheckMaps* mapcheck = HCheckMaps::New( | 5476 HCheckMaps* mapcheck = HCheckMaps::New( |
5472 object, map, zone(), top_info(), dependency); | 5477 object, map, zone(), top_info(), dependency); |
5473 AddInstruction(mapcheck); | 5478 AddInstruction(mapcheck); |
5474 if (dependency) { | 5479 if (dependency) { |
5475 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5480 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
5476 } | 5481 } |
5477 | 5482 |
5478 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5483 // Loads from a "stock" fast holey double arrays can elide the hole check. |
5479 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5484 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
5480 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5485 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
5481 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5486 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
5482 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5487 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
5483 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 5488 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
5484 Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info()); | 5489 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info()); |
5485 load_mode = ALLOW_RETURN_HOLE; | 5490 load_mode = ALLOW_RETURN_HOLE; |
5486 graph()->MarkDependsOnEmptyArrayProtoElements(); | 5491 graph()->MarkDependsOnEmptyArrayProtoElements(); |
5487 } | 5492 } |
5488 | 5493 |
5489 return BuildUncheckedMonomorphicElementAccess( | 5494 return BuildUncheckedMonomorphicElementAccess( |
5490 object, key, val, | 5495 object, key, val, |
5491 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 5496 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
5492 map->elements_kind(), is_store, load_mode, store_mode); | 5497 map->elements_kind(), is_store, load_mode, store_mode); |
5493 } | 5498 } |
5494 | 5499 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5597 | 5602 |
5598 MapHandleList untransitionable_maps(maps->length()); | 5603 MapHandleList untransitionable_maps(maps->length()); |
5599 HTransitionElementsKind* transition = NULL; | 5604 HTransitionElementsKind* transition = NULL; |
5600 for (int i = 0; i < maps->length(); ++i) { | 5605 for (int i = 0; i < maps->length(); ++i) { |
5601 Handle<Map> map = maps->at(i); | 5606 Handle<Map> map = maps->at(i); |
5602 ASSERT(map->IsMap()); | 5607 ASSERT(map->IsMap()); |
5603 if (!transition_target.at(i).is_null()) { | 5608 if (!transition_target.at(i).is_null()) { |
5604 ASSERT(Map::IsValidElementsTransition( | 5609 ASSERT(Map::IsValidElementsTransition( |
5605 map->elements_kind(), | 5610 map->elements_kind(), |
5606 transition_target.at(i)->elements_kind())); | 5611 transition_target.at(i)->elements_kind())); |
5607 HValue* context = environment()->LookupContext(); | 5612 transition = AddAndCast<HTransitionElementsKind>(object, map, |
5608 transition = Add<HTransitionElementsKind>(context, object, map, | 5613 transition_target.at(i)); |
5609 transition_target.at(i)); | |
5610 } else { | 5614 } else { |
5611 untransitionable_maps.Add(map); | 5615 untransitionable_maps.Add(map); |
5612 } | 5616 } |
5613 } | 5617 } |
5614 | 5618 |
5615 // If only one map is left after transitioning, handle this case | 5619 // If only one map is left after transitioning, handle this case |
5616 // monomorphically. | 5620 // monomorphically. |
5617 ASSERT(untransitionable_maps.length() >= 1); | 5621 ASSERT(untransitionable_maps.length() >= 1); |
5618 if (untransitionable_maps.length() == 1) { | 5622 if (untransitionable_maps.length() == 1) { |
5619 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 5623 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
(...skipping 29 matching lines...) Expand all Loading... |
5649 set_current_block(this_map); | 5653 set_current_block(this_map); |
5650 HInstruction* checked_key = NULL; | 5654 HInstruction* checked_key = NULL; |
5651 HInstruction* access = NULL; | 5655 HInstruction* access = NULL; |
5652 if (IsFastElementsKind(elements_kind)) { | 5656 if (IsFastElementsKind(elements_kind)) { |
5653 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | 5657 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
5654 AddInstruction(HCheckMaps::New( | 5658 AddInstruction(HCheckMaps::New( |
5655 elements, isolate()->factory()->fixed_array_map(), | 5659 elements, isolate()->factory()->fixed_array_map(), |
5656 zone(), top_info(), mapcompare)); | 5660 zone(), top_info(), mapcompare)); |
5657 } | 5661 } |
5658 if (map->instance_type() == JS_ARRAY_TYPE) { | 5662 if (map->instance_type() == JS_ARRAY_TYPE) { |
5659 HInstruction* length = AddLoad( | 5663 HInstruction* length = Add<HLoadNamedField>( |
5660 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); | 5664 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); |
5661 checked_key = Add<HBoundsCheck>(key, length); | 5665 checked_key = Add<HBoundsCheck>(key, length); |
5662 } else { | 5666 } else { |
5663 HInstruction* length = AddLoadFixedArrayLength(elements); | 5667 HInstruction* length = AddLoadFixedArrayLength(elements); |
5664 checked_key = Add<HBoundsCheck>(key, length); | 5668 checked_key = Add<HBoundsCheck>(key, length); |
5665 } | 5669 } |
5666 access = AddFastElementAccess( | 5670 access = AddFastElementAccess( |
5667 elements, checked_key, val, mapcompare, | 5671 elements, checked_key, val, mapcompare, |
5668 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); | 5672 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); |
5669 } else if (IsDictionaryElementsKind(elements_kind)) { | 5673 } else if (IsDictionaryElementsKind(elements_kind)) { |
5670 if (is_store) { | 5674 if (is_store) { |
5671 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 5675 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
5672 } else { | 5676 } else { |
5673 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 5677 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
5674 } | 5678 } |
5675 } else { | 5679 } else { |
5676 ASSERT(IsExternalArrayElementsKind(elements_kind)); | 5680 ASSERT(IsExternalArrayElementsKind(elements_kind)); |
5677 HInstruction* length = AddLoadFixedArrayLength(elements); | 5681 HInstruction* length = AddLoadFixedArrayLength(elements); |
5678 checked_key = Add<HBoundsCheck>(key, length); | 5682 checked_key = Add<HBoundsCheck>(key, length); |
5679 HLoadExternalArrayPointer* external_elements = | 5683 HLoadExternalArrayPointer* external_elements = |
5680 Add<HLoadExternalArrayPointer>(elements); | 5684 AddAndCast<HLoadExternalArrayPointer>(elements); |
5681 access = AddExternalArrayElementAccess( | 5685 access = AddExternalArrayElementAccess( |
5682 external_elements, checked_key, val, | 5686 external_elements, checked_key, val, |
5683 mapcompare, elements_kind, is_store); | 5687 mapcompare, elements_kind, is_store); |
5684 } | 5688 } |
5685 *has_side_effects |= access->HasObservableSideEffects(); | 5689 *has_side_effects |= access->HasObservableSideEffects(); |
5686 // The caller will use has_side_effects and add a correct Simulate. | 5690 // The caller will use has_side_effects and add a correct Simulate. |
5687 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5691 access->SetFlag(HValue::kHasNoObservableSideEffects); |
5688 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5692 if (position != RelocInfo::kNoPosition) access->set_position(position); |
5689 if (!is_store) { | 5693 if (!is_store) { |
5690 Push(access); | 5694 Push(access); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5745 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5749 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
5746 *has_side_effects = instr->HasObservableSideEffects(); | 5750 *has_side_effects = instr->HasObservableSideEffects(); |
5747 return instr; | 5751 return instr; |
5748 } | 5752 } |
5749 | 5753 |
5750 | 5754 |
5751 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 5755 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
5752 HValue* object, | 5756 HValue* object, |
5753 HValue* key, | 5757 HValue* key, |
5754 HValue* value) { | 5758 HValue* value) { |
5755 HValue* context = environment()->LookupContext(); | 5759 HValue* context = environment()->context(); |
5756 return new(zone()) HStoreKeyedGeneric( | 5760 return new(zone()) HStoreKeyedGeneric( |
5757 context, | 5761 context, |
5758 object, | 5762 object, |
5759 key, | 5763 key, |
5760 value, | 5764 value, |
5761 function_strict_mode_flag()); | 5765 function_strict_mode_flag()); |
5762 } | 5766 } |
5763 | 5767 |
5764 | 5768 |
5765 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 5769 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
5766 // Outermost function already has arguments on the stack. | 5770 // Outermost function already has arguments on the stack. |
5767 if (function_state()->outer() == NULL) return; | 5771 if (function_state()->outer() == NULL) return; |
5768 | 5772 |
5769 if (function_state()->arguments_pushed()) return; | 5773 if (function_state()->arguments_pushed()) return; |
5770 | 5774 |
5771 // Push arguments when entering inlined function. | 5775 // Push arguments when entering inlined function. |
5772 HEnterInlined* entry = function_state()->entry(); | 5776 HEnterInlined* entry = function_state()->entry(); |
5773 entry->set_arguments_pushed(); | 5777 entry->set_arguments_pushed(); |
5774 | 5778 |
5775 HArgumentsObject* arguments = entry->arguments_object(); | 5779 HArgumentsObject* arguments = entry->arguments_object(); |
5776 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); | 5780 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); |
5777 | 5781 |
5778 HInstruction* insert_after = entry; | 5782 HInstruction* insert_after = entry; |
5779 for (int i = 0; i < arguments_values->length(); i++) { | 5783 for (int i = 0; i < arguments_values->length(); i++) { |
5780 HValue* argument = arguments_values->at(i); | 5784 HValue* argument = arguments_values->at(i); |
5781 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 5785 HInstruction* push_argument = New<HPushArgument>(argument); |
5782 push_argument->InsertAfter(insert_after); | 5786 push_argument->InsertAfter(insert_after); |
5783 insert_after = push_argument; | 5787 insert_after = push_argument; |
5784 } | 5788 } |
5785 | 5789 |
5786 HArgumentsElements* arguments_elements = | 5790 HArgumentsElements* arguments_elements = NewAndCast<HArgumentsElements>(true); |
5787 new(zone()) HArgumentsElements(true); | |
5788 arguments_elements->ClearFlag(HValue::kUseGVN); | 5791 arguments_elements->ClearFlag(HValue::kUseGVN); |
5789 arguments_elements->InsertAfter(insert_after); | 5792 arguments_elements->InsertAfter(insert_after); |
5790 function_state()->set_arguments_elements(arguments_elements); | 5793 function_state()->set_arguments_elements(arguments_elements); |
5791 } | 5794 } |
5792 | 5795 |
5793 | 5796 |
5794 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { | 5797 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { |
5795 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 5798 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
5796 if (proxy == NULL) return false; | 5799 if (proxy == NULL) return false; |
5797 if (!proxy->var()->IsStackAllocated()) return false; | 5800 if (!proxy->var()->IsStackAllocated()) return false; |
5798 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 5801 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
5799 return false; | 5802 return false; |
5800 } | 5803 } |
5801 | 5804 |
5802 HInstruction* result = NULL; | 5805 HInstruction* result = NULL; |
5803 if (expr->key()->IsPropertyName()) { | 5806 if (expr->key()->IsPropertyName()) { |
5804 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5807 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
5805 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; | 5808 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; |
5806 | 5809 |
5807 if (function_state()->outer() == NULL) { | 5810 if (function_state()->outer() == NULL) { |
5808 HInstruction* elements = Add<HArgumentsElements>(false); | 5811 HInstruction* elements = Add<HArgumentsElements>(false); |
5809 result = new(zone()) HArgumentsLength(elements); | 5812 result = New<HArgumentsLength>(elements); |
5810 } else { | 5813 } else { |
5811 // Number of arguments without receiver. | 5814 // Number of arguments without receiver. |
5812 int argument_count = environment()-> | 5815 int argument_count = environment()-> |
5813 arguments_environment()->parameter_count() - 1; | 5816 arguments_environment()->parameter_count() - 1; |
5814 result = new(zone()) HConstant(argument_count); | 5817 result = New<HConstant>(argument_count); |
5815 } | 5818 } |
5816 } else { | 5819 } else { |
5817 Push(graph()->GetArgumentsObject()); | 5820 Push(graph()->GetArgumentsObject()); |
5818 VisitForValue(expr->key()); | 5821 VisitForValue(expr->key()); |
5819 if (HasStackOverflow() || current_block() == NULL) return true; | 5822 if (HasStackOverflow() || current_block() == NULL) return true; |
5820 HValue* key = Pop(); | 5823 HValue* key = Pop(); |
5821 Drop(1); // Arguments object. | 5824 Drop(1); // Arguments object. |
5822 if (function_state()->outer() == NULL) { | 5825 if (function_state()->outer() == NULL) { |
5823 HInstruction* elements = Add<HArgumentsElements>(false); | 5826 HInstruction* elements = Add<HArgumentsElements>(false); |
5824 HInstruction* length = Add<HArgumentsLength>(elements); | 5827 HInstruction* length = Add<HArgumentsLength>(elements); |
(...skipping 23 matching lines...) Expand all Loading... |
5848 | 5851 |
5849 if (TryArgumentsAccess(expr)) return; | 5852 if (TryArgumentsAccess(expr)) return; |
5850 | 5853 |
5851 CHECK_ALIVE(VisitForValue(expr->obj())); | 5854 CHECK_ALIVE(VisitForValue(expr->obj())); |
5852 | 5855 |
5853 HInstruction* instr = NULL; | 5856 HInstruction* instr = NULL; |
5854 if (expr->IsStringLength()) { | 5857 if (expr->IsStringLength()) { |
5855 HValue* string = Pop(); | 5858 HValue* string = Pop(); |
5856 BuildCheckHeapObject(string); | 5859 BuildCheckHeapObject(string); |
5857 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 5860 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
5858 instr = HStringLength::New(zone(), string); | 5861 instr = HStringLength::New(zone(), context(), string); |
5859 } else if (expr->IsStringAccess()) { | 5862 } else if (expr->IsStringAccess()) { |
5860 CHECK_ALIVE(VisitForValue(expr->key())); | 5863 CHECK_ALIVE(VisitForValue(expr->key())); |
5861 HValue* index = Pop(); | 5864 HValue* index = Pop(); |
5862 HValue* string = Pop(); | 5865 HValue* string = Pop(); |
5863 HValue* context = environment()->LookupContext(); | 5866 HValue* context = environment()->context(); |
5864 HInstruction* char_code = | 5867 HInstruction* char_code = |
5865 BuildStringCharCodeAt(context, string, index); | 5868 BuildStringCharCodeAt(string, index); |
5866 AddInstruction(char_code); | 5869 AddInstruction(char_code); |
5867 instr = HStringCharFromCode::New(zone(), context, char_code); | 5870 instr = HStringCharFromCode::New(zone(), context, char_code); |
5868 | 5871 |
5869 } else if (expr->IsFunctionPrototype()) { | 5872 } else if (expr->IsFunctionPrototype()) { |
5870 HValue* function = Pop(); | 5873 HValue* function = Pop(); |
5871 BuildCheckHeapObject(function); | 5874 BuildCheckHeapObject(function); |
5872 instr = new(zone()) HLoadFunctionPrototype(function); | 5875 instr = new(zone()) HLoadFunctionPrototype(function); |
5873 | 5876 |
5874 } else if (expr->key()->IsPropertyName()) { | 5877 } else if (expr->key()->IsPropertyName()) { |
5875 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5878 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5926 } | 5929 } |
5927 instr->set_position(expr->position()); | 5930 instr->set_position(expr->position()); |
5928 return ast_context()->ReturnInstruction(instr, expr->id()); | 5931 return ast_context()->ReturnInstruction(instr, expr->id()); |
5929 } | 5932 } |
5930 | 5933 |
5931 | 5934 |
5932 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 5935 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
5933 Handle<Map> receiver_map) { | 5936 Handle<Map> receiver_map) { |
5934 if (!holder.is_null()) { | 5937 if (!holder.is_null()) { |
5935 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 5938 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
5936 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5939 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5937 } | 5940 } |
5938 } | 5941 } |
5939 | 5942 |
5940 | 5943 |
5941 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 5944 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
5942 Handle<JSObject> holder, | 5945 Handle<JSObject> holder, |
5943 HValue* receiver, | 5946 HValue* receiver, |
5944 Handle<Map> receiver_map) { | 5947 Handle<Map> receiver_map) { |
5945 // Constant functions have the nice property that the map will change if they | 5948 // Constant functions have the nice property that the map will change if they |
5946 // are overwritten. Therefore it is enough to check the map of the holder and | 5949 // are overwritten. Therefore it is enough to check the map of the holder and |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6151 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6154 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6152 // know about and do not want to handle ones we've never seen. Otherwise | 6155 // know about and do not want to handle ones we've never seen. Otherwise |
6153 // use a generic IC. | 6156 // use a generic IC. |
6154 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6157 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6155 // Because the deopt may be the only path in the polymorphic call, make sure | 6158 // Because the deopt may be the only path in the polymorphic call, make sure |
6156 // that the environment stack matches the depth on deopt that it otherwise | 6159 // that the environment stack matches the depth on deopt that it otherwise |
6157 // would have had after a successful call. | 6160 // would have had after a successful call. |
6158 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); | 6161 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); |
6159 FinishExitWithHardDeoptimization(join); | 6162 FinishExitWithHardDeoptimization(join); |
6160 } else { | 6163 } else { |
6161 HValue* context = environment()->LookupContext(); | 6164 HValue* context = environment()->context(); |
6162 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6165 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
6163 call->set_position(expr->position()); | 6166 call->set_position(expr->position()); |
6164 PreProcessCall(call); | 6167 PreProcessCall(call); |
6165 | 6168 |
6166 if (join != NULL) { | 6169 if (join != NULL) { |
6167 AddInstruction(call); | 6170 AddInstruction(call); |
6168 if (!ast_context()->IsEffect()) Push(call); | 6171 if (!ast_context()->IsEffect()) Push(call); |
6169 current_block()->Goto(join); | 6172 current_block()->Goto(join); |
6170 } else { | 6173 } else { |
6171 return ast_context()->ReturnInstruction(call, expr->id()); | 6174 return ast_context()->ReturnInstruction(call, expr->id()); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6403 function, | 6406 function, |
6404 undefined, | 6407 undefined, |
6405 function_state()->inlining_kind(), | 6408 function_state()->inlining_kind(), |
6406 undefined_receiver); | 6409 undefined_receiver); |
6407 #if V8_TARGET_ARCH_IA32 | 6410 #if V8_TARGET_ARCH_IA32 |
6408 // IA32 only, overwrite the caller's context in the deoptimization | 6411 // IA32 only, overwrite the caller's context in the deoptimization |
6409 // environment with the correct one. | 6412 // environment with the correct one. |
6410 // | 6413 // |
6411 // TODO(kmillikin): implement the same inlining on other platforms so we | 6414 // TODO(kmillikin): implement the same inlining on other platforms so we |
6412 // can remove the unsightly ifdefs in this function. | 6415 // can remove the unsightly ifdefs in this function. |
6413 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 6416 HConstant* context = |
| 6417 AddAndCast<HConstant>(Handle<Context>(target->context())); |
6414 inner_env->BindContext(context); | 6418 inner_env->BindContext(context); |
6415 #endif | 6419 #endif |
6416 | 6420 |
6417 Add<HSimulate>(return_id); | 6421 Add<HSimulate>(return_id); |
6418 current_block()->UpdateEnvironment(inner_env); | 6422 current_block()->UpdateEnvironment(inner_env); |
6419 HArgumentsObject* arguments_object = NULL; | 6423 HArgumentsObject* arguments_object = NULL; |
6420 | 6424 |
6421 // If the function uses arguments object create and bind one, also copy | 6425 // If the function uses arguments object create and bind one, also copy |
6422 // current arguments values to use them for materialization. | 6426 // current arguments values to use them for materialization. |
6423 if (function->scope()->arguments() != NULL) { | 6427 if (function->scope()->arguments() != NULL) { |
6424 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6428 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
6425 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6429 HEnvironment* arguments_env = inner_env->arguments_environment(); |
6426 int arguments_count = arguments_env->parameter_count(); | 6430 int arguments_count = arguments_env->parameter_count(); |
6427 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6431 arguments_object = AddAndCast<HArgumentsObject>(arguments_count); |
6428 inner_env->Bind(function->scope()->arguments(), arguments_object); | 6432 inner_env->Bind(function->scope()->arguments(), arguments_object); |
6429 for (int i = 0; i < arguments_count; i++) { | 6433 for (int i = 0; i < arguments_count; i++) { |
6430 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); | 6434 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
6431 } | 6435 } |
6432 } | 6436 } |
6433 | 6437 |
6434 HEnterInlined* enter_inlined = | 6438 HEnterInlined* enter_inlined = |
6435 Add<HEnterInlined>(target, arguments_count, function, | 6439 AddAndCast<HEnterInlined>(target, arguments_count, function, |
6436 function_state()->inlining_kind(), | 6440 function_state()->inlining_kind(), |
6437 function->scope()->arguments(), | 6441 function->scope()->arguments(), |
6438 arguments_object, undefined_receiver, zone()); | 6442 arguments_object, undefined_receiver, zone()); |
6439 function_state()->set_entry(enter_inlined); | 6443 function_state()->set_entry(enter_inlined); |
6440 | 6444 |
6441 VisitDeclarations(target_info.scope()->declarations()); | 6445 VisitDeclarations(target_info.scope()->declarations()); |
6442 VisitStatements(function->body()); | 6446 VisitStatements(function->body()); |
6443 if (HasStackOverflow()) { | 6447 if (HasStackOverflow()) { |
6444 // Bail out if the inline function did, as we cannot residualize a call | 6448 // Bail out if the inline function did, as we cannot residualize a call |
6445 // instead. | 6449 // instead. |
6446 TraceInline(target, caller, "inline graph construction failed"); | 6450 TraceInline(target, caller, "inline graph construction failed"); |
6447 target_shared->DisableOptimization("inlining bailed out"); | 6451 target_shared->DisableOptimization("inlining bailed out"); |
6448 inline_bailout_ = true; | 6452 inline_bailout_ = true; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6619 case kMathRound: | 6623 case kMathRound: |
6620 case kMathFloor: | 6624 case kMathFloor: |
6621 case kMathAbs: | 6625 case kMathAbs: |
6622 case kMathSqrt: | 6626 case kMathSqrt: |
6623 case kMathLog: | 6627 case kMathLog: |
6624 case kMathSin: | 6628 case kMathSin: |
6625 case kMathCos: | 6629 case kMathCos: |
6626 case kMathTan: | 6630 case kMathTan: |
6627 if (expr->arguments()->length() == 1) { | 6631 if (expr->arguments()->length() == 1) { |
6628 HValue* argument = Pop(); | 6632 HValue* argument = Pop(); |
6629 HValue* context = environment()->LookupContext(); | 6633 HValue* context = environment()->context(); |
6630 Drop(1); // Receiver. | 6634 Drop(1); // Receiver. |
6631 HInstruction* op = | 6635 HInstruction* op = |
6632 HUnaryMathOperation::New(zone(), context, argument, id); | 6636 HUnaryMathOperation::New(zone(), context, argument, id); |
6633 op->set_position(expr->position()); | 6637 op->set_position(expr->position()); |
6634 if (drop_extra) Drop(1); // Optionally drop the function. | 6638 if (drop_extra) Drop(1); // Optionally drop the function. |
6635 ast_context()->ReturnInstruction(op, expr->id()); | 6639 ast_context()->ReturnInstruction(op, expr->id()); |
6636 return true; | 6640 return true; |
6637 } | 6641 } |
6638 break; | 6642 break; |
6639 case kMathImul: | 6643 case kMathImul: |
6640 if (expr->arguments()->length() == 2) { | 6644 if (expr->arguments()->length() == 2) { |
6641 HValue* right = Pop(); | 6645 HValue* right = Pop(); |
6642 HValue* left = Pop(); | 6646 HValue* left = Pop(); |
6643 Drop(1); // Receiver. | 6647 Drop(1); // Receiver. |
6644 HValue* context = environment()->LookupContext(); | 6648 HValue* context = environment()->context(); |
6645 HInstruction* op = HMul::NewImul(zone(), context, left, right); | 6649 HInstruction* op = HMul::NewImul(zone(), context, left, right); |
6646 if (drop_extra) Drop(1); // Optionally drop the function. | 6650 if (drop_extra) Drop(1); // Optionally drop the function. |
6647 ast_context()->ReturnInstruction(op, expr->id()); | 6651 ast_context()->ReturnInstruction(op, expr->id()); |
6648 return true; | 6652 return true; |
6649 } | 6653 } |
6650 break; | 6654 break; |
6651 default: | 6655 default: |
6652 // Not supported for inlining yet. | 6656 // Not supported for inlining yet. |
6653 break; | 6657 break; |
6654 } | 6658 } |
(...skipping 10 matching lines...) Expand all Loading... |
6665 // Try to inline calls like Math.* as operations in the calling function. | 6669 // Try to inline calls like Math.* as operations in the calling function. |
6666 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 6670 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
6667 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 6671 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
6668 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 6672 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
6669 switch (id) { | 6673 switch (id) { |
6670 case kStringCharCodeAt: | 6674 case kStringCharCodeAt: |
6671 case kStringCharAt: | 6675 case kStringCharAt: |
6672 if (argument_count == 2 && check_type == STRING_CHECK) { | 6676 if (argument_count == 2 && check_type == STRING_CHECK) { |
6673 HValue* index = Pop(); | 6677 HValue* index = Pop(); |
6674 HValue* string = Pop(); | 6678 HValue* string = Pop(); |
6675 HValue* context = environment()->LookupContext(); | 6679 HValue* context = environment()->context(); |
6676 ASSERT(!expr->holder().is_null()); | 6680 ASSERT(!expr->holder().is_null()); |
6677 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( | 6681 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( |
6678 STRING_CHECK, expr->holder()->GetIsolate()), | 6682 STRING_CHECK, expr->holder()->GetIsolate()), |
6679 expr->holder(), zone(), top_info()); | 6683 expr->holder(), top_info()); |
6680 HInstruction* char_code = | 6684 HInstruction* char_code = |
6681 BuildStringCharCodeAt(context, string, index); | 6685 BuildStringCharCodeAt(string, index); |
6682 if (id == kStringCharCodeAt) { | 6686 if (id == kStringCharCodeAt) { |
6683 ast_context()->ReturnInstruction(char_code, expr->id()); | 6687 ast_context()->ReturnInstruction(char_code, expr->id()); |
6684 return true; | 6688 return true; |
6685 } | 6689 } |
6686 AddInstruction(char_code); | 6690 AddInstruction(char_code); |
6687 HInstruction* result = | 6691 HInstruction* result = |
6688 HStringCharFromCode::New(zone(), context, char_code); | 6692 HStringCharFromCode::New(zone(), context, char_code); |
6689 ast_context()->ReturnInstruction(result, expr->id()); | 6693 ast_context()->ReturnInstruction(result, expr->id()); |
6690 return true; | 6694 return true; |
6691 } | 6695 } |
6692 break; | 6696 break; |
6693 case kStringFromCharCode: | 6697 case kStringFromCharCode: |
6694 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6698 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6695 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6699 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6696 HValue* argument = Pop(); | 6700 HValue* argument = Pop(); |
6697 HValue* context = environment()->LookupContext(); | 6701 HValue* context = environment()->context(); |
6698 Drop(1); // Receiver. | 6702 Drop(1); // Receiver. |
6699 HInstruction* result = | 6703 HInstruction* result = |
6700 HStringCharFromCode::New(zone(), context, argument); | 6704 HStringCharFromCode::New(zone(), context, argument); |
6701 ast_context()->ReturnInstruction(result, expr->id()); | 6705 ast_context()->ReturnInstruction(result, expr->id()); |
6702 return true; | 6706 return true; |
6703 } | 6707 } |
6704 break; | 6708 break; |
6705 case kMathExp: | 6709 case kMathExp: |
6706 if (!FLAG_fast_math) break; | 6710 if (!FLAG_fast_math) break; |
6707 // Fall through if FLAG_fast_math. | 6711 // Fall through if FLAG_fast_math. |
6708 case kMathRound: | 6712 case kMathRound: |
6709 case kMathFloor: | 6713 case kMathFloor: |
6710 case kMathAbs: | 6714 case kMathAbs: |
6711 case kMathSqrt: | 6715 case kMathSqrt: |
6712 case kMathLog: | 6716 case kMathLog: |
6713 case kMathSin: | 6717 case kMathSin: |
6714 case kMathCos: | 6718 case kMathCos: |
6715 case kMathTan: | 6719 case kMathTan: |
6716 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6720 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6717 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6721 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6718 HValue* argument = Pop(); | 6722 HValue* argument = Pop(); |
6719 HValue* context = environment()->LookupContext(); | 6723 HValue* context = environment()->context(); |
6720 Drop(1); // Receiver. | 6724 Drop(1); // Receiver. |
6721 HInstruction* op = | 6725 HInstruction* op = |
6722 HUnaryMathOperation::New(zone(), context, argument, id); | 6726 HUnaryMathOperation::New(zone(), context, argument, id); |
6723 op->set_position(expr->position()); | 6727 op->set_position(expr->position()); |
6724 ast_context()->ReturnInstruction(op, expr->id()); | 6728 ast_context()->ReturnInstruction(op, expr->id()); |
6725 return true; | 6729 return true; |
6726 } | 6730 } |
6727 break; | 6731 break; |
6728 case kMathPow: | 6732 case kMathPow: |
6729 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6733 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6730 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6734 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6731 HValue* right = Pop(); | 6735 HValue* right = Pop(); |
6732 HValue* left = Pop(); | 6736 HValue* left = Pop(); |
6733 Pop(); // Pop receiver. | 6737 Pop(); // Pop receiver. |
6734 HValue* context = environment()->LookupContext(); | 6738 HValue* context = environment()->context(); |
6735 HInstruction* result = NULL; | 6739 HInstruction* result = NULL; |
6736 // Use sqrt() if exponent is 0.5 or -0.5. | 6740 // Use sqrt() if exponent is 0.5 or -0.5. |
6737 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 6741 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
6738 double exponent = HConstant::cast(right)->DoubleValue(); | 6742 double exponent = HConstant::cast(right)->DoubleValue(); |
6739 if (exponent == 0.5) { | 6743 if (exponent == 0.5) { |
6740 result = | 6744 result = |
6741 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 6745 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
6742 } else if (exponent == -0.5) { | 6746 } else if (exponent == -0.5) { |
6743 HValue* one = graph()->GetConstant1(); | 6747 HValue* one = graph()->GetConstant1(); |
6744 HInstruction* sqrt = | 6748 HInstruction* sqrt = |
6745 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 6749 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
6746 AddInstruction(sqrt); | 6750 AddInstruction(sqrt); |
6747 // MathPowHalf doesn't have side effects so there's no need for | 6751 // MathPowHalf doesn't have side effects so there's no need for |
6748 // an environment simulation here. | 6752 // an environment simulation here. |
6749 ASSERT(!sqrt->HasObservableSideEffects()); | 6753 ASSERT(!sqrt->HasObservableSideEffects()); |
6750 result = HDiv::New(zone(), context, one, sqrt); | 6754 result = HDiv::New(zone(), context, one, sqrt); |
6751 } else if (exponent == 2.0) { | 6755 } else if (exponent == 2.0) { |
6752 result = HMul::New(zone(), context, left, left); | 6756 result = HMul::New(zone(), context, left, left); |
6753 } | 6757 } |
6754 } else if (right->EqualsInteger32Constant(2)) { | 6758 } else if (right->EqualsInteger32Constant(2)) { |
6755 result = HMul::New(zone(), context, left, left); | 6759 result = HMul::New(zone(), context, left, left); |
6756 } | 6760 } |
6757 | 6761 |
6758 if (result == NULL) { | 6762 if (result == NULL) { |
6759 result = HPower::New(zone(), left, right); | 6763 result = HPower::New(zone(), context, left, right); |
6760 } | 6764 } |
6761 ast_context()->ReturnInstruction(result, expr->id()); | 6765 ast_context()->ReturnInstruction(result, expr->id()); |
6762 return true; | 6766 return true; |
6763 } | 6767 } |
6764 break; | 6768 break; |
6765 case kMathRandom: | 6769 case kMathRandom: |
6766 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 6770 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
6767 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6771 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6768 Drop(1); // Receiver. | 6772 Drop(1); // Receiver. |
6769 HValue* context = environment()->LookupContext(); | 6773 HGlobalObject* global_object = AddAndCast<HGlobalObject>(); |
6770 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
6771 HRandom* result = new(zone()) HRandom(global_object); | 6774 HRandom* result = new(zone()) HRandom(global_object); |
6772 ast_context()->ReturnInstruction(result, expr->id()); | 6775 ast_context()->ReturnInstruction(result, expr->id()); |
6773 return true; | 6776 return true; |
6774 } | 6777 } |
6775 break; | 6778 break; |
6776 case kMathMax: | 6779 case kMathMax: |
6777 case kMathMin: | 6780 case kMathMin: |
6778 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6781 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6779 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6782 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6780 HValue* right = Pop(); | 6783 HValue* right = Pop(); |
6781 HValue* left = Pop(); | 6784 HValue* left = Pop(); |
6782 Drop(1); // Receiver. | 6785 Drop(1); // Receiver. |
6783 HValue* context = environment()->LookupContext(); | 6786 HValue* context = environment()->context(); |
6784 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin | 6787 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
6785 : HMathMinMax::kMathMax; | 6788 : HMathMinMax::kMathMax; |
6786 HInstruction* result = | 6789 HInstruction* result = |
6787 HMathMinMax::New(zone(), context, left, right, op); | 6790 HMathMinMax::New(zone(), context, left, right, op); |
6788 ast_context()->ReturnInstruction(result, expr->id()); | 6791 ast_context()->ReturnInstruction(result, expr->id()); |
6789 return true; | 6792 return true; |
6790 } | 6793 } |
6791 break; | 6794 break; |
6792 case kMathImul: | 6795 case kMathImul: |
6793 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6796 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6794 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6797 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6795 HValue* right = Pop(); | 6798 HValue* right = Pop(); |
6796 HValue* left = Pop(); | 6799 HValue* left = Pop(); |
6797 Drop(1); // Receiver. | 6800 Drop(1); // Receiver. |
6798 HValue* context = environment()->LookupContext(); | 6801 HValue* context = environment()->context(); |
6799 HInstruction* result = HMul::NewImul(zone(), context, left, right); | 6802 HInstruction* result = HMul::NewImul(zone(), context, left, right); |
6800 ast_context()->ReturnInstruction(result, expr->id()); | 6803 ast_context()->ReturnInstruction(result, expr->id()); |
6801 return true; | 6804 return true; |
6802 } | 6805 } |
6803 break; | 6806 break; |
6804 default: | 6807 default: |
6805 // Not yet supported for inlining. | 6808 // Not yet supported for inlining. |
6806 break; | 6809 break; |
6807 } | 6810 } |
6808 return false; | 6811 return false; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6872 | 6875 |
6873 Handle<JSFunction> known_function; | 6876 Handle<JSFunction> known_function; |
6874 if (function->IsConstant()) { | 6877 if (function->IsConstant()) { |
6875 HConstant* constant_function = HConstant::cast(function); | 6878 HConstant* constant_function = HConstant::cast(function); |
6876 known_function = Handle<JSFunction>::cast(constant_function->handle()); | 6879 known_function = Handle<JSFunction>::cast(constant_function->handle()); |
6877 int args_count = arguments_count - 1; // Excluding receiver. | 6880 int args_count = arguments_count - 1; // Excluding receiver. |
6878 if (TryInlineApply(known_function, expr, args_count)) return true; | 6881 if (TryInlineApply(known_function, expr, args_count)) return true; |
6879 } | 6882 } |
6880 | 6883 |
6881 Drop(arguments_count - 1); | 6884 Drop(arguments_count - 1); |
6882 PushAndAdd(new(zone()) HPushArgument(Pop())); | 6885 PushAndAdd(New<HPushArgument>(Pop())); |
6883 for (int i = 1; i < arguments_count; i++) { | 6886 for (int i = 1; i < arguments_count; i++) { |
6884 PushAndAdd(new(zone()) HPushArgument(arguments_values->at(i))); | 6887 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); |
6885 } | 6888 } |
6886 | 6889 |
6887 HValue* context = environment()->LookupContext(); | 6890 HValue* context = environment()->context(); |
6888 HInvokeFunction* call = new(zone()) HInvokeFunction( | 6891 HInvokeFunction* call = new(zone()) HInvokeFunction( |
6889 context, | 6892 context, |
6890 function, | 6893 function, |
6891 known_function, | 6894 known_function, |
6892 arguments_count); | 6895 arguments_count); |
6893 Drop(arguments_count); | 6896 Drop(arguments_count); |
6894 call->set_position(expr->position()); | 6897 call->set_position(expr->position()); |
6895 ast_context()->ReturnInstruction(call, expr->id()); | 6898 ast_context()->ReturnInstruction(call, expr->id()); |
6896 return true; | 6899 return true; |
6897 } | 6900 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6963 | 6966 |
6964 CHECK_ALIVE(VisitForValue(prop->key())); | 6967 CHECK_ALIVE(VisitForValue(prop->key())); |
6965 // Push receiver and key like the non-optimized code generator expects it. | 6968 // Push receiver and key like the non-optimized code generator expects it. |
6966 HValue* key = Pop(); | 6969 HValue* key = Pop(); |
6967 HValue* receiver = Pop(); | 6970 HValue* receiver = Pop(); |
6968 Push(key); | 6971 Push(key); |
6969 Push(receiver); | 6972 Push(receiver); |
6970 | 6973 |
6971 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 6974 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
6972 | 6975 |
6973 HValue* context = environment()->LookupContext(); | 6976 HValue* context = environment()->context(); |
6974 call = new(zone()) HCallKeyed(context, key, argument_count); | 6977 call = new(zone()) HCallKeyed(context, key, argument_count); |
6975 call->set_position(expr->position()); | 6978 call->set_position(expr->position()); |
6976 Drop(argument_count + 1); // 1 is the key. | 6979 Drop(argument_count + 1); // 1 is the key. |
6977 return ast_context()->ReturnInstruction(call, expr->id()); | 6980 return ast_context()->ReturnInstruction(call, expr->id()); |
6978 } | 6981 } |
6979 | 6982 |
6980 // Named function call. | 6983 // Named function call. |
6981 if (TryCallApply(expr)) return; | 6984 if (TryCallApply(expr)) return; |
6982 | 6985 |
6983 CHECK_ALIVE(VisitForValue(prop->obj())); | 6986 CHECK_ALIVE(VisitForValue(prop->obj())); |
(...skipping 29 matching lines...) Expand all Loading... |
7013 PrintF("\n"); | 7016 PrintF("\n"); |
7014 } | 7017 } |
7015 return; | 7018 return; |
7016 } | 7019 } |
7017 | 7020 |
7018 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 7021 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
7019 expr->check_type() != RECEIVER_MAP_CHECK) { | 7022 expr->check_type() != RECEIVER_MAP_CHECK) { |
7020 // When the target has a custom call IC generator, use the IC, | 7023 // When the target has a custom call IC generator, use the IC, |
7021 // because it is likely to generate better code. Also use the IC | 7024 // because it is likely to generate better code. Also use the IC |
7022 // when a primitive receiver check is required. | 7025 // when a primitive receiver check is required. |
7023 HValue* context = environment()->LookupContext(); | 7026 HValue* context = environment()->context(); |
7024 call = PreProcessCall( | 7027 call = PreProcessCall( |
7025 new(zone()) HCallNamed(context, name, argument_count)); | 7028 new(zone()) HCallNamed(context, name, argument_count)); |
7026 } else { | 7029 } else { |
7027 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7030 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7028 | 7031 |
7029 if (TryInlineCall(expr)) return; | 7032 if (TryInlineCall(expr)) return; |
7030 call = PreProcessCall( | 7033 call = PreProcessCall( |
7031 new(zone()) HCallConstantFunction(expr->target(), | 7034 new(zone()) HCallConstantFunction(expr->target(), |
7032 argument_count)); | 7035 argument_count)); |
7033 } | 7036 } |
7034 } else if (types != NULL && types->length() > 1) { | 7037 } else if (types != NULL && types->length() > 1) { |
7035 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7038 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
7036 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7039 HandlePolymorphicCallNamed(expr, receiver, types, name); |
7037 return; | 7040 return; |
7038 | 7041 |
7039 } else { | 7042 } else { |
7040 HValue* context = environment()->LookupContext(); | 7043 HValue* context = environment()->context(); |
7041 call = PreProcessCall( | 7044 call = PreProcessCall( |
7042 new(zone()) HCallNamed(context, name, argument_count)); | 7045 new(zone()) HCallNamed(context, name, argument_count)); |
7043 } | 7046 } |
7044 | 7047 |
7045 } else { | 7048 } else { |
7046 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7049 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7047 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 7050 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
7048 return Bailout("possible direct call to eval"); | 7051 return Bailout("possible direct call to eval"); |
7049 } | 7052 } |
7050 | 7053 |
7051 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 7054 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
7052 if (global_call) { | 7055 if (global_call) { |
7053 Variable* var = proxy->var(); | 7056 Variable* var = proxy->var(); |
7054 bool known_global_function = false; | 7057 bool known_global_function = false; |
7055 // If there is a global property cell for the name at compile time and | 7058 // If there is a global property cell for the name at compile time and |
7056 // access check is not enabled we assume that the function will not change | 7059 // access check is not enabled we assume that the function will not change |
7057 // and generate optimized code for calling the function. | 7060 // and generate optimized code for calling the function. |
7058 LookupResult lookup(isolate()); | 7061 LookupResult lookup(isolate()); |
7059 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 7062 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
7060 if (type == kUseCell && | 7063 if (type == kUseCell && |
7061 !current_info()->global_object()->IsAccessCheckNeeded()) { | 7064 !current_info()->global_object()->IsAccessCheckNeeded()) { |
7062 Handle<GlobalObject> global(current_info()->global_object()); | 7065 Handle<GlobalObject> global(current_info()->global_object()); |
7063 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 7066 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
7064 } | 7067 } |
7065 if (known_global_function) { | 7068 if (known_global_function) { |
7066 // Push the global object instead of the global receiver because | 7069 // Push the global object instead of the global receiver because |
7067 // code generated by the full code generator expects it. | 7070 // code generated by the full code generator expects it. |
7068 HValue* context = environment()->LookupContext(); | 7071 HValue* context = environment()->context(); |
7069 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 7072 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
7070 PushAndAdd(global_object); | 7073 PushAndAdd(global_object); |
7071 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7074 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7072 | 7075 |
7073 CHECK_ALIVE(VisitForValue(expr->expression())); | 7076 CHECK_ALIVE(VisitForValue(expr->expression())); |
7074 HValue* function = Pop(); | 7077 HValue* function = Pop(); |
7075 Add<HCheckFunction>(function, expr->target()); | 7078 Add<HCheckFunction>(function, expr->target()); |
7076 | 7079 |
7077 // Replace the global object with the global receiver. | 7080 // Replace the global object with the global receiver. |
7078 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); | 7081 HGlobalReceiver* global_receiver = |
| 7082 AddAndCast<HGlobalReceiver>(global_object); |
7079 // Index of the receiver from the top of the expression stack. | 7083 // Index of the receiver from the top of the expression stack. |
7080 const int receiver_index = argument_count - 1; | 7084 const int receiver_index = argument_count - 1; |
7081 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 7085 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
7082 IsGlobalObject()); | 7086 IsGlobalObject()); |
7083 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 7087 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
7084 | 7088 |
7085 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 7089 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
7086 if (FLAG_trace_inlining) { | 7090 if (FLAG_trace_inlining) { |
7087 PrintF("Inlining builtin "); | 7091 PrintF("Inlining builtin "); |
7088 expr->target()->ShortPrint(); | 7092 expr->target()->ShortPrint(); |
7089 PrintF("\n"); | 7093 PrintF("\n"); |
7090 } | 7094 } |
7091 return; | 7095 return; |
7092 } | 7096 } |
7093 if (TryInlineCall(expr)) return; | 7097 if (TryInlineCall(expr)) return; |
7094 | 7098 |
7095 if (expr->target().is_identical_to(current_info()->closure())) { | 7099 if (expr->target().is_identical_to(current_info()->closure())) { |
7096 graph()->MarkRecursive(); | 7100 graph()->MarkRecursive(); |
7097 } | 7101 } |
7098 | 7102 |
7099 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { | 7103 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
7100 // When the target has a custom call IC generator, use the IC, | 7104 // When the target has a custom call IC generator, use the IC, |
7101 // because it is likely to generate better code. | 7105 // because it is likely to generate better code. |
7102 HValue* context = environment()->LookupContext(); | 7106 HValue* context = environment()->context(); |
7103 call = PreProcessCall( | 7107 call = PreProcessCall( |
7104 new(zone()) HCallNamed(context, var->name(), argument_count)); | 7108 new(zone()) HCallNamed(context, var->name(), argument_count)); |
7105 } else { | 7109 } else { |
7106 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 7110 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
7107 argument_count)); | 7111 argument_count)); |
7108 } | 7112 } |
7109 } else { | 7113 } else { |
7110 HValue* context = environment()->LookupContext(); | 7114 HGlobalObject* receiver = AddAndCast<HGlobalObject>(); |
7111 HGlobalObject* receiver = Add<HGlobalObject>(context); | 7115 PushAndAdd(New<HPushArgument>(receiver)); |
7112 PushAndAdd(new(zone()) HPushArgument(receiver)); | |
7113 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7116 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7114 | 7117 |
7115 call = new(zone()) HCallGlobal(context, var->name(), argument_count); | 7118 call = New<HCallGlobal>(var->name(), argument_count); |
7116 Drop(argument_count); | 7119 Drop(argument_count); |
7117 } | 7120 } |
7118 | 7121 |
7119 } else if (expr->IsMonomorphic()) { | 7122 } else if (expr->IsMonomorphic()) { |
7120 // The function is on the stack in the unoptimized code during | 7123 // The function is on the stack in the unoptimized code during |
7121 // evaluation of the arguments. | 7124 // evaluation of the arguments. |
7122 CHECK_ALIVE(VisitForValue(expr->expression())); | 7125 CHECK_ALIVE(VisitForValue(expr->expression())); |
7123 HValue* function = Top(); | 7126 HValue* function = Top(); |
7124 HValue* context = environment()->LookupContext(); | 7127 HGlobalObject* global = AddAndCast<HGlobalObject>(); |
7125 HGlobalObject* global = Add<HGlobalObject>(context); | 7128 HGlobalReceiver* receiver = NewAndCast<HGlobalReceiver>(global); |
7126 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); | |
7127 PushAndAdd(receiver); | 7129 PushAndAdd(receiver); |
7128 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7130 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7129 Add<HCheckFunction>(function, expr->target()); | 7131 Add<HCheckFunction>(function, expr->target()); |
7130 | 7132 |
7131 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. | 7133 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. |
7132 if (FLAG_trace_inlining) { | 7134 if (FLAG_trace_inlining) { |
7133 PrintF("Inlining builtin "); | 7135 PrintF("Inlining builtin "); |
7134 expr->target()->ShortPrint(); | 7136 expr->target()->ShortPrint(); |
7135 PrintF("\n"); | 7137 PrintF("\n"); |
7136 } | 7138 } |
7137 return; | 7139 return; |
7138 } | 7140 } |
7139 | 7141 |
7140 if (TryInlineCall(expr, true)) { // Drop function from environment. | 7142 if (TryInlineCall(expr, true)) { // Drop function from environment. |
7141 return; | 7143 return; |
7142 } else { | 7144 } else { |
7143 call = PreProcessCall( | 7145 call = PreProcessCall( |
7144 new(zone()) HInvokeFunction(context, | 7146 NewAndCast<HInvokeFunction>(function, expr->target(), |
7145 function, | 7147 argument_count)); |
7146 expr->target(), | |
7147 argument_count)); | |
7148 Drop(1); // The function. | 7148 Drop(1); // The function. |
7149 } | 7149 } |
7150 | 7150 |
7151 } else { | 7151 } else { |
7152 CHECK_ALIVE(VisitForValue(expr->expression())); | 7152 CHECK_ALIVE(VisitForValue(expr->expression())); |
7153 HValue* function = Top(); | 7153 HValue* function = Top(); |
7154 HValue* context = environment()->LookupContext(); | 7154 HGlobalObject* global_object = AddAndCast<HGlobalObject>(); |
7155 HGlobalObject* global_object = Add<HGlobalObject>(context); | 7155 HGlobalReceiver* receiver = AddAndCast<HGlobalReceiver>(global_object); |
7156 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); | 7156 PushAndAdd(New<HPushArgument>(receiver)); |
7157 PushAndAdd(new(zone()) HPushArgument(receiver)); | |
7158 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7157 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7159 | 7158 |
7160 call = new(zone()) HCallFunction(context, function, argument_count); | 7159 call = New<HCallFunction>(function, argument_count); |
7161 Drop(argument_count + 1); | 7160 Drop(argument_count + 1); |
7162 } | 7161 } |
7163 } | 7162 } |
7164 | 7163 |
7165 call->set_position(expr->position()); | 7164 call->set_position(expr->position()); |
7166 return ast_context()->ReturnInstruction(call, expr->id()); | 7165 return ast_context()->ReturnInstruction(call, expr->id()); |
7167 } | 7166 } |
7168 | 7167 |
7169 | 7168 |
7170 // Checks whether allocation using the given constructor can be inlined. | 7169 // Checks whether allocation using the given constructor can be inlined. |
7171 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7170 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7172 return constructor->has_initial_map() && | 7171 return constructor->has_initial_map() && |
7173 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7172 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7174 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7173 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
7175 constructor->initial_map()->InitialPropertiesLength() == 0; | 7174 constructor->initial_map()->InitialPropertiesLength() == 0; |
7176 } | 7175 } |
7177 | 7176 |
7178 | 7177 |
7179 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7178 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
7180 ASSERT(!HasStackOverflow()); | 7179 ASSERT(!HasStackOverflow()); |
7181 ASSERT(current_block() != NULL); | 7180 ASSERT(current_block() != NULL); |
7182 ASSERT(current_block()->HasPredecessor()); | 7181 ASSERT(current_block()->HasPredecessor()); |
7183 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7182 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7184 HValue* context = environment()->LookupContext(); | 7183 HValue* context = environment()->context(); |
7185 Factory* factory = isolate()->factory(); | 7184 Factory* factory = isolate()->factory(); |
7186 | 7185 |
7187 if (FLAG_inline_construct && | 7186 if (FLAG_inline_construct && |
7188 expr->IsMonomorphic() && | 7187 expr->IsMonomorphic() && |
7189 IsAllocationInlineable(expr->target())) { | 7188 IsAllocationInlineable(expr->target())) { |
7190 // The constructor function is on the stack in the unoptimized code | 7189 // The constructor function is on the stack in the unoptimized code |
7191 // during evaluation of the arguments. | 7190 // during evaluation of the arguments. |
7192 CHECK_ALIVE(VisitForValue(expr->expression())); | 7191 CHECK_ALIVE(VisitForValue(expr->expression())); |
7193 HValue* function = Top(); | 7192 HValue* function = Top(); |
7194 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7193 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
(...skipping 14 matching lines...) Expand all Loading... |
7209 | 7208 |
7210 // Allocate an instance of the implicit receiver object. | 7209 // Allocate an instance of the implicit receiver object. |
7211 HValue* size_in_bytes = Add<HConstant>(instance_size); | 7210 HValue* size_in_bytes = Add<HConstant>(instance_size); |
7212 HAllocate::Flags flags = HAllocate::DefaultFlags(); | 7211 HAllocate::Flags flags = HAllocate::DefaultFlags(); |
7213 if (FLAG_pretenuring_call_new && | 7212 if (FLAG_pretenuring_call_new && |
7214 isolate()->heap()->ShouldGloballyPretenure()) { | 7213 isolate()->heap()->ShouldGloballyPretenure()) { |
7215 flags = static_cast<HAllocate::Flags>( | 7214 flags = static_cast<HAllocate::Flags>( |
7216 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 7215 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
7217 } | 7216 } |
7218 HAllocate* receiver = | 7217 HAllocate* receiver = |
7219 Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); | 7218 AddAndCast<HAllocate>(size_in_bytes, HType::JSObject(), flags); |
7220 receiver->set_known_initial_map(initial_map); | 7219 receiver->set_known_initial_map(initial_map); |
7221 | 7220 |
7222 // Load the initial map from the constructor. | 7221 // Load the initial map from the constructor. |
7223 HValue* constructor_value = Add<HConstant>(constructor); | 7222 HValue* constructor_value = Add<HConstant>(constructor); |
7224 HValue* initial_map_value = | 7223 HValue* initial_map_value = |
7225 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | 7224 Add<HLoadNamedField>(constructor_value, HObjectAccess::ForJSObjectOffset( |
7226 JSFunction::kPrototypeOrInitialMapOffset)); | 7225 JSFunction::kPrototypeOrInitialMapOffset)); |
7227 | 7226 |
7228 // Initialize map and fields of the newly allocated object. | 7227 // Initialize map and fields of the newly allocated object. |
7229 { NoObservableSideEffectsScope no_effects(this); | 7228 { NoObservableSideEffectsScope no_effects(this); |
7230 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 7229 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
7231 AddStore(receiver, | 7230 Add<HStoreNamedField>(receiver, |
7232 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | 7231 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), |
7233 initial_map_value); | 7232 initial_map_value); |
7234 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); | 7233 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); |
7235 AddStore(receiver, | 7234 Add<HStoreNamedField>(receiver, |
7236 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | 7235 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), |
7237 empty_fixed_array); | 7236 empty_fixed_array); |
7238 AddStore(receiver, | 7237 Add<HStoreNamedField>(receiver, |
7239 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | 7238 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), |
7240 empty_fixed_array); | 7239 empty_fixed_array); |
7241 if (initial_map->inobject_properties() != 0) { | 7240 if (initial_map->inobject_properties() != 0) { |
7242 HConstant* undefined = graph()->GetConstantUndefined(); | 7241 HConstant* undefined = graph()->GetConstantUndefined(); |
7243 for (int i = 0; i < initial_map->inobject_properties(); i++) { | 7242 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
7244 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | 7243 int property_offset = JSObject::kHeaderSize + i * kPointerSize; |
7245 AddStore(receiver, | 7244 Add<HStoreNamedField>(receiver, |
7246 HObjectAccess::ForJSObjectOffset(property_offset), | 7245 HObjectAccess::ForJSObjectOffset(property_offset), |
7247 undefined); | 7246 undefined); |
7248 } | 7247 } |
7249 } | 7248 } |
7250 } | 7249 } |
7251 | 7250 |
7252 // Replace the constructor function with a newly allocated receiver using | 7251 // Replace the constructor function with a newly allocated receiver using |
7253 // the index of the receiver from the top of the expression stack. | 7252 // the index of the receiver from the top of the expression stack. |
7254 const int receiver_index = argument_count - 1; | 7253 const int receiver_index = argument_count - 1; |
7255 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 7254 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
7256 environment()->SetExpressionStackAt(receiver_index, receiver); | 7255 environment()->SetExpressionStackAt(receiver_index, receiver); |
7257 | 7256 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7335 ASSERT(static_cast<size_t>(lookup_index) < | 7334 ASSERT(static_cast<size_t>(lookup_index) < |
7336 ARRAY_SIZE(kInlineFunctionGenerators)); | 7335 ARRAY_SIZE(kInlineFunctionGenerators)); |
7337 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 7336 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
7338 | 7337 |
7339 // Call the inline code generator using the pointer-to-member. | 7338 // Call the inline code generator using the pointer-to-member. |
7340 (this->*generator)(expr); | 7339 (this->*generator)(expr); |
7341 } else { | 7340 } else { |
7342 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 7341 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
7343 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7342 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7344 | 7343 |
7345 HValue* context = environment()->LookupContext(); | |
7346 Handle<String> name = expr->name(); | 7344 Handle<String> name = expr->name(); |
7347 int argument_count = expr->arguments()->length(); | 7345 int argument_count = expr->arguments()->length(); |
7348 HCallRuntime* call = | 7346 HCallRuntime* call = NewAndCast<HCallRuntime>(name, function, |
7349 new(zone()) HCallRuntime(context, name, function, argument_count); | 7347 argument_count); |
7350 Drop(argument_count); | 7348 Drop(argument_count); |
7351 return ast_context()->ReturnInstruction(call, expr->id()); | 7349 return ast_context()->ReturnInstruction(call, expr->id()); |
7352 } | 7350 } |
7353 } | 7351 } |
7354 | 7352 |
7355 | 7353 |
7356 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7354 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
7357 ASSERT(!HasStackOverflow()); | 7355 ASSERT(!HasStackOverflow()); |
7358 ASSERT(current_block() != NULL); | 7356 ASSERT(current_block() != NULL); |
7359 ASSERT(current_block()->HasPredecessor()); | 7357 ASSERT(current_block()->HasPredecessor()); |
(...skipping 10 matching lines...) Expand all Loading... |
7370 | 7368 |
7371 | 7369 |
7372 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7370 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
7373 Property* prop = expr->expression()->AsProperty(); | 7371 Property* prop = expr->expression()->AsProperty(); |
7374 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7372 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7375 if (prop != NULL) { | 7373 if (prop != NULL) { |
7376 CHECK_ALIVE(VisitForValue(prop->obj())); | 7374 CHECK_ALIVE(VisitForValue(prop->obj())); |
7377 CHECK_ALIVE(VisitForValue(prop->key())); | 7375 CHECK_ALIVE(VisitForValue(prop->key())); |
7378 HValue* key = Pop(); | 7376 HValue* key = Pop(); |
7379 HValue* obj = Pop(); | 7377 HValue* obj = Pop(); |
7380 HValue* context = environment()->LookupContext(); | 7378 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); |
7381 HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context); | |
7382 Add<HPushArgument>(obj); | 7379 Add<HPushArgument>(obj); |
7383 Add<HPushArgument>(key); | 7380 Add<HPushArgument>(key); |
7384 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); | 7381 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); |
7385 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 7382 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
7386 // even though we are certain to pass the correct number of arguments here. | 7383 // even though we are certain to pass the correct number of arguments here. |
7387 HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3); | 7384 HInstruction* instr = New<HInvokeFunction>(function, 3); |
7388 return ast_context()->ReturnInstruction(instr, expr->id()); | 7385 return ast_context()->ReturnInstruction(instr, expr->id()); |
7389 } else if (proxy != NULL) { | 7386 } else if (proxy != NULL) { |
7390 Variable* var = proxy->var(); | 7387 Variable* var = proxy->var(); |
7391 if (var->IsUnallocated()) { | 7388 if (var->IsUnallocated()) { |
7392 Bailout("delete with global variable"); | 7389 Bailout("delete with global variable"); |
7393 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 7390 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
7394 // Result of deleting non-global variables is false. 'this' is not | 7391 // Result of deleting non-global variables is false. 'this' is not |
7395 // really a variable, though we implement it as one. The | 7392 // really a variable, though we implement it as one. The |
7396 // subexpression does not have side effects. | 7393 // subexpression does not have side effects. |
7397 HValue* value = var->is_this() | 7394 HValue* value = var->is_this() |
(...skipping 14 matching lines...) Expand all Loading... |
7412 | 7409 |
7413 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7410 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { |
7414 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7411 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7415 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7412 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
7416 } | 7413 } |
7417 | 7414 |
7418 | 7415 |
7419 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7416 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
7420 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7417 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7421 HValue* value = Pop(); | 7418 HValue* value = Pop(); |
7422 HValue* context = environment()->LookupContext(); | 7419 HValue* context = environment()->context(); |
7423 HInstruction* instr = new(zone()) HTypeof(context, value); | 7420 HInstruction* instr = new(zone()) HTypeof(context, value); |
7424 return ast_context()->ReturnInstruction(instr, expr->id()); | 7421 return ast_context()->ReturnInstruction(instr, expr->id()); |
7425 } | 7422 } |
7426 | 7423 |
7427 | 7424 |
7428 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 7425 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
7429 CHECK_ALIVE(VisitForValue(expr->expression())); | 7426 CHECK_ALIVE(VisitForValue(expr->expression())); |
7430 Handle<Type> operand_type = expr->expression()->bounds().lower; | 7427 Handle<Type> operand_type = expr->expression()->bounds().lower; |
7431 HValue* value = TruncateToNumber(Pop(), &operand_type); | 7428 HValue* value = TruncateToNumber(Pop(), &operand_type); |
7432 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); | 7429 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7509 } | 7506 } |
7510 Push(number_input); | 7507 Push(number_input); |
7511 } | 7508 } |
7512 | 7509 |
7513 // The addition has no side effects, so we do not need | 7510 // The addition has no side effects, so we do not need |
7514 // to simulate the expression stack after this instruction. | 7511 // to simulate the expression stack after this instruction. |
7515 // Any later failures deopt to the load of the input or earlier. | 7512 // Any later failures deopt to the load of the input or earlier. |
7516 HConstant* delta = (expr->op() == Token::INC) | 7513 HConstant* delta = (expr->op() == Token::INC) |
7517 ? graph()->GetConstant1() | 7514 ? graph()->GetConstant1() |
7518 : graph()->GetConstantMinus1(); | 7515 : graph()->GetConstantMinus1(); |
7519 HValue* context = environment()->LookupContext(); | 7516 HInstruction* instr = Add<HAdd>(Top(), delta); |
7520 HInstruction* instr = HAdd::New(zone(), context, Top(), delta); | |
7521 instr->SetFlag(HInstruction::kCannotBeTagged); | 7517 instr->SetFlag(HInstruction::kCannotBeTagged); |
7522 instr->ClearAllSideEffects(); | 7518 instr->ClearAllSideEffects(); |
7523 AddInstruction(instr); | |
7524 return instr; | 7519 return instr; |
7525 } | 7520 } |
7526 | 7521 |
7527 | 7522 |
7528 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7523 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7529 ASSERT(!HasStackOverflow()); | 7524 ASSERT(!HasStackOverflow()); |
7530 ASSERT(current_block() != NULL); | 7525 ASSERT(current_block() != NULL); |
7531 ASSERT(current_block()->HasPredecessor()); | 7526 ASSERT(current_block()->HasPredecessor()); |
7532 Expression* target = expr->expression(); | 7527 Expression* target = expr->expression(); |
7533 VariableProxy* proxy = target->AsVariableProxy(); | 7528 VariableProxy* proxy = target->AsVariableProxy(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7582 for (int i = 0; i < count; ++i) { | 7577 for (int i = 0; i < count; ++i) { |
7583 if (var == current_info()->scope()->parameter(i)) { | 7578 if (var == current_info()->scope()->parameter(i)) { |
7584 return Bailout("assignment to parameter in arguments object"); | 7579 return Bailout("assignment to parameter in arguments object"); |
7585 } | 7580 } |
7586 } | 7581 } |
7587 } | 7582 } |
7588 | 7583 |
7589 HValue* context = BuildContextChainWalk(var); | 7584 HValue* context = BuildContextChainWalk(var); |
7590 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) | 7585 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) |
7591 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; | 7586 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; |
7592 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 7587 HStoreContextSlot* instr = |
7593 mode, after); | 7588 AddAndCast<HStoreContextSlot>(context, var->index(), |
| 7589 mode, after); |
7594 if (instr->HasObservableSideEffects()) { | 7590 if (instr->HasObservableSideEffects()) { |
7595 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7591 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7596 } | 7592 } |
7597 break; | 7593 break; |
7598 } | 7594 } |
7599 | 7595 |
7600 case Variable::LOOKUP: | 7596 case Variable::LOOKUP: |
7601 return Bailout("lookup variable in count operation"); | 7597 return Bailout("lookup variable in count operation"); |
7602 } | 7598 } |
7603 | 7599 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7678 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7674 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7679 } | 7675 } |
7680 } | 7676 } |
7681 | 7677 |
7682 Drop(returns_original_input ? 2 : 1); | 7678 Drop(returns_original_input ? 2 : 1); |
7683 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7679 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
7684 } | 7680 } |
7685 | 7681 |
7686 | 7682 |
7687 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7683 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
7688 HValue* context, | |
7689 HValue* string, | 7684 HValue* string, |
7690 HValue* index) { | 7685 HValue* index) { |
7691 if (string->IsConstant() && index->IsConstant()) { | 7686 if (string->IsConstant() && index->IsConstant()) { |
7692 HConstant* c_string = HConstant::cast(string); | 7687 HConstant* c_string = HConstant::cast(string); |
7693 HConstant* c_index = HConstant::cast(index); | 7688 HConstant* c_index = HConstant::cast(index); |
7694 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 7689 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
7695 int32_t i = c_index->NumberValueAsInteger32(); | 7690 int32_t i = c_index->NumberValueAsInteger32(); |
7696 Handle<String> s = c_string->StringValue(); | 7691 Handle<String> s = c_string->StringValue(); |
7697 if (i < 0 || i >= s->length()) { | 7692 if (i < 0 || i >= s->length()) { |
7698 return new(zone()) HConstant(OS::nan_value()); | 7693 return New<HConstant>(OS::nan_value()); |
7699 } | 7694 } |
7700 return new(zone()) HConstant(s->Get(i)); | 7695 return New<HConstant>(s->Get(i)); |
7701 } | 7696 } |
7702 } | 7697 } |
7703 BuildCheckHeapObject(string); | 7698 BuildCheckHeapObject(string); |
7704 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 7699 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
7705 HInstruction* length = HStringLength::New(zone(), string); | 7700 HInstruction* length = Add<HStringLength>(string); |
7706 AddInstruction(length); | |
7707 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | 7701 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
7708 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 7702 return New<HStringCharCodeAt>(string, checked_index); |
7709 } | 7703 } |
7710 | 7704 |
7711 | 7705 |
7712 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 7706 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
7713 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 7707 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
7714 HValue* const32_minus_sa) { | 7708 HValue* const32_minus_sa) { |
7715 if (!const32_minus_sa->IsSub()) return false; | 7709 if (!const32_minus_sa->IsSub()) return false; |
7716 HSub* sub = HSub::cast(const32_minus_sa); | 7710 HSub* sub = HSub::cast(const32_minus_sa); |
7717 if (sa != sub->right()) return false; | 7711 if (sa != sub->right()) return false; |
7718 HValue* const32 = sub->left(); | 7712 HValue* const32 = sub->left(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7787 // tagged representation later on. | 7781 // tagged representation later on. |
7788 if (expected_type->Is(Type::Oddball())) { | 7782 if (expected_type->Is(Type::Oddball())) { |
7789 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to | 7783 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to |
7790 // also record booleans and convert them to 0/1 here. | 7784 // also record booleans and convert them to 0/1 here. |
7791 IfBuilder if_nan(this); | 7785 IfBuilder if_nan(this); |
7792 if_nan.If<HCompareObjectEqAndBranch>(value, | 7786 if_nan.If<HCompareObjectEqAndBranch>(value, |
7793 graph()->GetConstantUndefined()); | 7787 graph()->GetConstantUndefined()); |
7794 if_nan.Then(); | 7788 if_nan.Then(); |
7795 if_nan.ElseDeopt(); | 7789 if_nan.ElseDeopt(); |
7796 if_nan.End(); | 7790 if_nan.End(); |
7797 return Add<HConstant>(OS::nan_value(), Representation::Double()); | 7791 return Add<HConstant>(OS::nan_value()); |
7798 } | 7792 } |
7799 | 7793 |
7800 return value; | 7794 return value; |
7801 } | 7795 } |
7802 | 7796 |
7803 | 7797 |
7804 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7798 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7805 BinaryOperation* expr, | 7799 BinaryOperation* expr, |
7806 HValue* left, | 7800 HValue* left, |
7807 HValue* right) { | 7801 HValue* right) { |
7808 HValue* context = environment()->LookupContext(); | 7802 HValue* context = environment()->context(); |
7809 Handle<Type> left_type = expr->left()->bounds().lower; | 7803 Handle<Type> left_type = expr->left()->bounds().lower; |
7810 Handle<Type> right_type = expr->right()->bounds().lower; | 7804 Handle<Type> right_type = expr->right()->bounds().lower; |
7811 Handle<Type> result_type = expr->bounds().lower; | 7805 Handle<Type> result_type = expr->bounds().lower; |
7812 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7806 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7813 Representation left_rep = Representation::FromType(left_type); | 7807 Representation left_rep = Representation::FromType(left_type); |
7814 Representation right_rep = Representation::FromType(right_type); | 7808 Representation right_rep = Representation::FromType(right_type); |
7815 Representation result_rep = Representation::FromType(result_type); | 7809 Representation result_rep = Representation::FromType(result_type); |
7816 | 7810 |
7817 if (expr->op() != Token::ADD || | 7811 if (expr->op() != Token::ADD || |
7818 (left->type().IsNonString() && right->type().IsNonString())) { | 7812 (left->type().IsNonString() && right->type().IsNonString())) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7851 instr = HMul::New(zone(), context, left, right); | 7845 instr = HMul::New(zone(), context, left, right); |
7852 break; | 7846 break; |
7853 case Token::MOD: | 7847 case Token::MOD: |
7854 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7848 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
7855 break; | 7849 break; |
7856 case Token::DIV: | 7850 case Token::DIV: |
7857 instr = HDiv::New(zone(), context, left, right); | 7851 instr = HDiv::New(zone(), context, left, right); |
7858 break; | 7852 break; |
7859 case Token::BIT_XOR: | 7853 case Token::BIT_XOR: |
7860 case Token::BIT_AND: | 7854 case Token::BIT_AND: |
7861 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 7855 instr = New<HBitwise>(expr->op(), left, right); |
7862 break; | 7856 break; |
7863 case Token::BIT_OR: { | 7857 case Token::BIT_OR: { |
7864 HValue* operand, *shift_amount; | 7858 HValue* operand, *shift_amount; |
7865 if (left_type->Is(Type::Signed32()) && | 7859 if (left_type->Is(Type::Signed32()) && |
7866 right_type->Is(Type::Signed32()) && | 7860 right_type->Is(Type::Signed32()) && |
7867 MatchRotateRight(left, right, &operand, &shift_amount)) { | 7861 MatchRotateRight(left, right, &operand, &shift_amount)) { |
7868 instr = new(zone()) HRor(context, operand, shift_amount); | 7862 instr = new(zone()) HRor(context, operand, shift_amount); |
7869 } else { | 7863 } else { |
7870 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 7864 instr = New<HBitwise>(expr->op(), left, right); |
7871 } | 7865 } |
7872 break; | 7866 break; |
7873 } | 7867 } |
7874 case Token::SAR: | 7868 case Token::SAR: |
7875 instr = HSar::New(zone(), context, left, right); | 7869 instr = HSar::New(zone(), context, left, right); |
7876 break; | 7870 break; |
7877 case Token::SHR: | 7871 case Token::SHR: |
7878 instr = HShr::New(zone(), context, left, right); | 7872 instr = HShr::New(zone(), context, left, right); |
7879 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 7873 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7880 CanBeZero(right)) { | 7874 CanBeZero(right)) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8105 Handle<Type> left_type = expr->left()->bounds().lower; | 8099 Handle<Type> left_type = expr->left()->bounds().lower; |
8106 Handle<Type> right_type = expr->right()->bounds().lower; | 8100 Handle<Type> right_type = expr->right()->bounds().lower; |
8107 Handle<Type> combined_type = expr->combined_type(); | 8101 Handle<Type> combined_type = expr->combined_type(); |
8108 Representation combined_rep = Representation::FromType(combined_type); | 8102 Representation combined_rep = Representation::FromType(combined_type); |
8109 Representation left_rep = Representation::FromType(left_type); | 8103 Representation left_rep = Representation::FromType(left_type); |
8110 Representation right_rep = Representation::FromType(right_type); | 8104 Representation right_rep = Representation::FromType(right_type); |
8111 | 8105 |
8112 CHECK_ALIVE(VisitForValue(expr->left())); | 8106 CHECK_ALIVE(VisitForValue(expr->left())); |
8113 CHECK_ALIVE(VisitForValue(expr->right())); | 8107 CHECK_ALIVE(VisitForValue(expr->right())); |
8114 | 8108 |
8115 HValue* context = environment()->LookupContext(); | 8109 HValue* context = environment()->context(); |
8116 HValue* right = Pop(); | 8110 HValue* right = Pop(); |
8117 HValue* left = Pop(); | 8111 HValue* left = Pop(); |
8118 Token::Value op = expr->op(); | 8112 Token::Value op = expr->op(); |
8119 | 8113 |
8120 if (IsLiteralCompareBool(left, op, right)) { | 8114 if (IsLiteralCompareBool(left, op, right)) { |
8121 HCompareObjectEqAndBranch* result = | 8115 HCompareObjectEqAndBranch* result = |
8122 new(zone()) HCompareObjectEqAndBranch(left, right); | 8116 NewAndCast<HCompareObjectEqAndBranch>(left, right); |
8123 result->set_position(expr->position()); | 8117 result->set_position(expr->position()); |
8124 return ast_context()->ReturnControl(result, expr->id()); | 8118 return ast_context()->ReturnControl(result, expr->id()); |
8125 } | 8119 } |
8126 | 8120 |
8127 if (op == Token::INSTANCEOF) { | 8121 if (op == Token::INSTANCEOF) { |
8128 // Check to see if the rhs of the instanceof is a global function not | 8122 // Check to see if the rhs of the instanceof is a global function not |
8129 // residing in new space. If it is we assume that the function will stay the | 8123 // residing in new space. If it is we assume that the function will stay the |
8130 // same. | 8124 // same. |
8131 Handle<JSFunction> target = Handle<JSFunction>::null(); | 8125 Handle<JSFunction> target = Handle<JSFunction>::null(); |
8132 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 8126 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
(...skipping 25 matching lines...) Expand all Loading... |
8158 Add<HCheckFunction>(right, target); | 8152 Add<HCheckFunction>(right, target); |
8159 HInstanceOfKnownGlobal* result = | 8153 HInstanceOfKnownGlobal* result = |
8160 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8154 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
8161 result->set_position(expr->position()); | 8155 result->set_position(expr->position()); |
8162 return ast_context()->ReturnInstruction(result, expr->id()); | 8156 return ast_context()->ReturnInstruction(result, expr->id()); |
8163 } | 8157 } |
8164 | 8158 |
8165 // Code below assumes that we don't fall through. | 8159 // Code below assumes that we don't fall through. |
8166 UNREACHABLE(); | 8160 UNREACHABLE(); |
8167 } else if (op == Token::IN) { | 8161 } else if (op == Token::IN) { |
8168 HValue* function = AddLoadJSBuiltin(Builtins::IN, context); | 8162 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
8169 Add<HPushArgument>(left); | 8163 Add<HPushArgument>(left); |
8170 Add<HPushArgument>(right); | 8164 Add<HPushArgument>(right); |
8171 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8165 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
8172 // even though we are certain to pass the correct number of arguments here. | 8166 // even though we are certain to pass the correct number of arguments here. |
8173 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8167 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
8174 result->set_position(expr->position()); | 8168 result->set_position(expr->position()); |
8175 return ast_context()->ReturnInstruction(result, expr->id()); | 8169 return ast_context()->ReturnInstruction(result, expr->id()); |
8176 } | 8170 } |
8177 | 8171 |
8178 // Cases handled below depend on collected type feedback. They should | 8172 // Cases handled below depend on collected type feedback. They should |
8179 // soft deoptimize when there is no type feedback. | 8173 // soft deoptimize when there is no type feedback. |
8180 if (combined_type->Is(Type::None())) { | 8174 if (combined_type->Is(Type::None())) { |
8181 Add<HDeoptimize>(Deoptimizer::SOFT); | 8175 Add<HDeoptimize>(Deoptimizer::SOFT); |
8182 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8176 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
8183 } | 8177 } |
8184 | 8178 |
8185 if (combined_type->Is(Type::Receiver())) { | 8179 if (combined_type->Is(Type::Receiver())) { |
8186 switch (op) { | 8180 switch (op) { |
8187 case Token::EQ: | 8181 case Token::EQ: |
8188 case Token::EQ_STRICT: { | 8182 case Token::EQ_STRICT: { |
8189 // Can we get away with map check and not instance type check? | 8183 // Can we get away with map check and not instance type check? |
8190 if (combined_type->IsClass()) { | 8184 if (combined_type->IsClass()) { |
8191 Handle<Map> map = combined_type->AsClass(); | 8185 Handle<Map> map = combined_type->AsClass(); |
8192 AddCheckMapsWithTransitions(left, map); | 8186 AddCheckMapsWithTransitions(left, map); |
8193 AddCheckMapsWithTransitions(right, map); | 8187 AddCheckMapsWithTransitions(right, map); |
8194 HCompareObjectEqAndBranch* result = | 8188 HCompareObjectEqAndBranch* result = |
8195 new(zone()) HCompareObjectEqAndBranch(left, right); | 8189 NewAndCast<HCompareObjectEqAndBranch>(left, right); |
8196 result->set_position(expr->position()); | 8190 result->set_position(expr->position()); |
8197 return ast_context()->ReturnControl(result, expr->id()); | 8191 return ast_context()->ReturnControl(result, expr->id()); |
8198 } else { | 8192 } else { |
8199 BuildCheckHeapObject(left); | 8193 BuildCheckHeapObject(left); |
8200 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8194 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8201 BuildCheckHeapObject(right); | 8195 BuildCheckHeapObject(right); |
8202 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8196 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8203 HCompareObjectEqAndBranch* result = | 8197 HCompareObjectEqAndBranch* result = |
8204 new(zone()) HCompareObjectEqAndBranch(left, right); | 8198 new(zone()) HCompareObjectEqAndBranch(left, right); |
8205 result->set_position(expr->position()); | 8199 result->set_position(expr->position()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8266 ? handle(Type::Any(), isolate_) : expr->combined_type(); | 8260 ? handle(Type::Any(), isolate_) : expr->combined_type(); |
8267 BuildCompareNil(value, type, expr->position(), &continuation); | 8261 BuildCompareNil(value, type, expr->position(), &continuation); |
8268 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8262 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
8269 } | 8263 } |
8270 | 8264 |
8271 | 8265 |
8272 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8266 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
8273 // If we share optimized code between different closures, the | 8267 // If we share optimized code between different closures, the |
8274 // this-function is not a constant, except inside an inlined body. | 8268 // this-function is not a constant, except inside an inlined body. |
8275 if (function_state()->outer() != NULL) { | 8269 if (function_state()->outer() != NULL) { |
8276 return new(zone()) HConstant( | 8270 return New<HConstant>( |
8277 function_state()->compilation_info()->closure()); | 8271 function_state()->compilation_info()->closure()); |
8278 } else { | 8272 } else { |
8279 return new(zone()) HThisFunction; | 8273 return new(zone()) HThisFunction; |
8280 } | 8274 } |
8281 } | 8275 } |
8282 | 8276 |
8283 | 8277 |
8284 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 8278 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
8285 HValue* context, | 8279 HValue* context, |
8286 Handle<JSObject> boilerplate_object, | 8280 Handle<JSObject> boilerplate_object, |
8287 Handle<JSObject> original_boilerplate_object, | 8281 Handle<JSObject> original_boilerplate_object, |
8288 Handle<Object> allocation_site, | 8282 Handle<Object> allocation_site, |
8289 int data_size, | 8283 int data_size, |
8290 int pointer_size, | 8284 int pointer_size, |
8291 AllocationSiteMode mode) { | 8285 AllocationSiteMode mode) { |
8292 NoObservableSideEffectsScope no_effects(this); | 8286 NoObservableSideEffectsScope no_effects(this); |
8293 | 8287 |
8294 HInstruction* target = NULL; | 8288 HInstruction* target = NULL; |
8295 HInstruction* data_target = NULL; | 8289 HInstruction* data_target = NULL; |
8296 | 8290 |
8297 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8291 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
8298 | 8292 |
8299 if (isolate()->heap()->ShouldGloballyPretenure()) { | 8293 if (isolate()->heap()->ShouldGloballyPretenure()) { |
8300 if (data_size != 0) { | 8294 if (data_size != 0) { |
8301 HAllocate::Flags data_flags = | 8295 HAllocate::Flags data_flags = |
8302 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags(kind) | | 8296 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags(kind) | |
8303 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); | 8297 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
8304 HValue* size_in_bytes = Add<HConstant>(data_size); | 8298 HValue* size_in_bytes = Add<HConstant>(data_size); |
8305 data_target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), | 8299 data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
8306 data_flags); | 8300 data_flags); |
8307 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | 8301 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); |
8308 AddStoreMapConstant(data_target, free_space_map); | 8302 AddStoreMapConstant(data_target, free_space_map); |
8309 HObjectAccess access = | 8303 HObjectAccess access = |
8310 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | 8304 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
8311 AddStore(data_target, access, size_in_bytes); | 8305 Add<HStoreNamedField>(data_target, access, size_in_bytes); |
8312 } | 8306 } |
8313 if (pointer_size != 0) { | 8307 if (pointer_size != 0) { |
8314 HAllocate::Flags pointer_flags = | 8308 HAllocate::Flags pointer_flags = |
8315 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | | 8309 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | |
8316 HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 8310 HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
8317 HValue* size_in_bytes = Add<HConstant>(pointer_size); | 8311 HValue* size_in_bytes = Add<HConstant>(pointer_size); |
8318 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), | 8312 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
8319 pointer_flags); | 8313 pointer_flags); |
8320 } | 8314 } |
8321 } else { | 8315 } else { |
8322 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); | 8316 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); |
8323 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); | 8317 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); |
8324 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); | 8318 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), flags); |
8325 } | 8319 } |
8326 | 8320 |
8327 int offset = 0; | 8321 int offset = 0; |
8328 int data_offset = 0; | 8322 int data_offset = 0; |
8329 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, | 8323 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, |
8330 allocation_site, target, &offset, data_target, | 8324 allocation_site, target, &offset, data_target, |
8331 &data_offset, mode); | 8325 &data_offset, mode); |
8332 return target; | 8326 return target; |
8333 } | 8327 } |
8334 | 8328 |
8335 | 8329 |
8336 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 8330 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
8337 Handle<JSObject> boilerplate_object, | 8331 Handle<JSObject> boilerplate_object, |
8338 Handle<JSObject> original_boilerplate_object, | 8332 Handle<JSObject> original_boilerplate_object, |
8339 Handle<Object> allocation_site_object, | 8333 Handle<Object> allocation_site_object, |
8340 HInstruction* target, | 8334 HInstruction* target, |
8341 int* offset, | 8335 int* offset, |
8342 HInstruction* data_target, | 8336 HInstruction* data_target, |
8343 int* data_offset, | 8337 int* data_offset, |
8344 AllocationSiteMode mode) { | 8338 AllocationSiteMode mode) { |
8345 Zone* zone = this->zone(); | |
8346 | |
8347 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 8339 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
8348 boilerplate_object->map()->CanTrackAllocationSite(); | 8340 boilerplate_object->map()->CanTrackAllocationSite(); |
8349 | 8341 |
8350 // If using allocation sites, then the payload on the site should already | 8342 // If using allocation sites, then the payload on the site should already |
8351 // be filled in as a valid (boilerplate) array. | 8343 // be filled in as a valid (boilerplate) array. |
8352 ASSERT(!create_allocation_site_info || | 8344 ASSERT(!create_allocation_site_info || |
8353 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); | 8345 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); |
8354 | 8346 |
8355 HInstruction* allocation_site = NULL; | 8347 HInstruction* allocation_site = NULL; |
8356 | 8348 |
8357 if (create_allocation_site_info) { | 8349 if (create_allocation_site_info) { |
8358 allocation_site = AddInstruction(new(zone) HConstant( | 8350 allocation_site = Add<HConstant>(allocation_site_object); |
8359 allocation_site_object, Representation::Tagged())); | |
8360 } | 8351 } |
8361 | 8352 |
8362 // Only elements backing stores for non-COW arrays need to be copied. | 8353 // Only elements backing stores for non-COW arrays need to be copied. |
8363 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 8354 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
8364 Handle<FixedArrayBase> original_elements( | 8355 Handle<FixedArrayBase> original_elements( |
8365 original_boilerplate_object->elements()); | 8356 original_boilerplate_object->elements()); |
8366 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8357 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
8367 | 8358 |
8368 int object_offset = *offset; | 8359 int object_offset = *offset; |
8369 int object_size = boilerplate_object->map()->instance_size(); | 8360 int object_size = boilerplate_object->map()->instance_size(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8430 Handle<Object>(boilerplate_object->elements(), isolate()); | 8421 Handle<Object>(boilerplate_object->elements(), isolate()); |
8431 elements = Add<HConstant>(elements_field); | 8422 elements = Add<HConstant>(elements_field); |
8432 } else { | 8423 } else { |
8433 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | 8424 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { |
8434 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); | 8425 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); |
8435 } else { | 8426 } else { |
8436 elements = Add<HInnerAllocatedObject>(target, elements_offset); | 8427 elements = Add<HInnerAllocatedObject>(target, elements_offset); |
8437 } | 8428 } |
8438 result = elements; | 8429 result = elements; |
8439 } | 8430 } |
8440 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); | 8431 Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(), |
| 8432 elements); |
8441 | 8433 |
8442 Handle<Object> properties_field = | 8434 Handle<Object> properties_field = |
8443 Handle<Object>(boilerplate_object->properties(), isolate()); | 8435 Handle<Object>(boilerplate_object->properties(), isolate()); |
8444 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 8436 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
8445 HInstruction* properties = Add<HConstant>(properties_field); | 8437 HInstruction* properties = Add<HConstant>(properties_field); |
8446 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 8438 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
8447 AddStore(object_header, access, properties); | 8439 Add<HStoreNamedField>(object_header, access, properties); |
8448 | 8440 |
8449 if (boilerplate_object->IsJSArray()) { | 8441 if (boilerplate_object->IsJSArray()) { |
8450 Handle<JSArray> boilerplate_array = | 8442 Handle<JSArray> boilerplate_array = |
8451 Handle<JSArray>::cast(boilerplate_object); | 8443 Handle<JSArray>::cast(boilerplate_object); |
8452 Handle<Object> length_field = | 8444 Handle<Object> length_field = |
8453 Handle<Object>(boilerplate_array->length(), isolate()); | 8445 Handle<Object>(boilerplate_array->length(), isolate()); |
8454 HInstruction* length = Add<HConstant>(length_field); | 8446 HInstruction* length = Add<HConstant>(length_field); |
8455 | 8447 |
8456 ASSERT(boilerplate_array->length()->IsSmi()); | 8448 ASSERT(boilerplate_array->length()->IsSmi()); |
8457 AddStore(object_header, HObjectAccess::ForArrayLength( | 8449 Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength( |
8458 boilerplate_array->GetElementsKind()), length); | 8450 boilerplate_array->GetElementsKind()), length); |
8459 } | 8451 } |
8460 | 8452 |
8461 return result; | 8453 return result; |
8462 } | 8454 } |
8463 | 8455 |
8464 | 8456 |
8465 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8457 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
8466 Handle<JSObject> boilerplate_object, | 8458 Handle<JSObject> boilerplate_object, |
8467 Handle<JSObject> original_boilerplate_object, | 8459 Handle<JSObject> original_boilerplate_object, |
(...skipping 24 matching lines...) Expand all Loading... |
8492 HObjectAccess::ForJSObjectOffset(property_offset); | 8484 HObjectAccess::ForJSObjectOffset(property_offset); |
8493 | 8485 |
8494 if (value->IsJSObject()) { | 8486 if (value->IsJSObject()) { |
8495 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8487 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
8496 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8488 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
8497 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 8489 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
8498 isolate())); | 8490 isolate())); |
8499 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8491 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, |
8500 *offset); | 8492 *offset); |
8501 | 8493 |
8502 AddStore(object_properties, access, value_instruction); | 8494 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8503 BuildEmitDeepCopy(value_object, original_value_object, | 8495 BuildEmitDeepCopy(value_object, original_value_object, |
8504 Handle<Object>::null(), target, | 8496 Handle<Object>::null(), target, |
8505 offset, data_target, data_offset, | 8497 offset, data_target, data_offset, |
8506 DONT_TRACK_ALLOCATION_SITE); | 8498 DONT_TRACK_ALLOCATION_SITE); |
8507 } else { | 8499 } else { |
8508 Representation representation = details.representation(); | 8500 Representation representation = details.representation(); |
8509 HInstruction* value_instruction = Add<HConstant>(value); | 8501 HInstruction* value_instruction = Add<HConstant>(value); |
8510 | 8502 |
8511 if (representation.IsDouble()) { | 8503 if (representation.IsDouble()) { |
8512 // Allocate a HeapNumber box and store the value into it. | 8504 // Allocate a HeapNumber box and store the value into it. |
8513 HInstruction* double_box; | 8505 HInstruction* double_box; |
8514 if (data_target != NULL) { | 8506 if (data_target != NULL) { |
8515 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8507 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
8516 *data_offset += HeapNumber::kSize; | 8508 *data_offset += HeapNumber::kSize; |
8517 } else { | 8509 } else { |
8518 double_box = Add<HInnerAllocatedObject>(target, *offset); | 8510 double_box = Add<HInnerAllocatedObject>(target, *offset); |
8519 *offset += HeapNumber::kSize; | 8511 *offset += HeapNumber::kSize; |
8520 } | 8512 } |
8521 AddStoreMapConstant(double_box, | 8513 AddStoreMapConstant(double_box, |
8522 isolate()->factory()->heap_number_map()); | 8514 isolate()->factory()->heap_number_map()); |
8523 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 8515 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
8524 value_instruction); | 8516 value_instruction); |
8525 value_instruction = double_box; | 8517 value_instruction = double_box; |
8526 } | 8518 } |
8527 | 8519 |
8528 AddStore(object_properties, access, value_instruction); | 8520 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8529 } | 8521 } |
8530 } | 8522 } |
8531 | 8523 |
8532 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8524 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
8533 HInstruction* value_instruction = | 8525 HInstruction* value_instruction = |
8534 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8526 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
8535 for (int i = copied_fields; i < inobject_properties; i++) { | 8527 for (int i = copied_fields; i < inobject_properties; i++) { |
8536 ASSERT(boilerplate_object->IsJSObject()); | 8528 ASSERT(boilerplate_object->IsJSObject()); |
8537 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 8529 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
8538 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 8530 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
8539 AddStore(object_properties, access, value_instruction); | 8531 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8540 } | 8532 } |
8541 } | 8533 } |
8542 | 8534 |
8543 | 8535 |
8544 void HOptimizedGraphBuilder::BuildEmitElements( | 8536 void HOptimizedGraphBuilder::BuildEmitElements( |
8545 Handle<FixedArrayBase> elements, | 8537 Handle<FixedArrayBase> elements, |
8546 Handle<FixedArrayBase> original_elements, | 8538 Handle<FixedArrayBase> original_elements, |
8547 ElementsKind kind, | 8539 ElementsKind kind, |
8548 HValue* object_elements, | 8540 HValue* object_elements, |
8549 HInstruction* target, | 8541 HInstruction* target, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8638 ZoneList<Declaration*>* declarations) { | 8630 ZoneList<Declaration*>* declarations) { |
8639 ASSERT(globals_.is_empty()); | 8631 ASSERT(globals_.is_empty()); |
8640 AstVisitor::VisitDeclarations(declarations); | 8632 AstVisitor::VisitDeclarations(declarations); |
8641 if (!globals_.is_empty()) { | 8633 if (!globals_.is_empty()) { |
8642 Handle<FixedArray> array = | 8634 Handle<FixedArray> array = |
8643 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8635 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
8644 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8636 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
8645 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 8637 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
8646 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 8638 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
8647 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); | 8639 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); |
8648 Add<HDeclareGlobals>(environment()->LookupContext(), array, flags); | 8640 Add<HDeclareGlobals>(array, flags); |
8649 globals_.Clear(); | 8641 globals_.Clear(); |
8650 } | 8642 } |
8651 } | 8643 } |
8652 | 8644 |
8653 | 8645 |
8654 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8646 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
8655 VariableDeclaration* declaration) { | 8647 VariableDeclaration* declaration) { |
8656 VariableProxy* proxy = declaration->proxy(); | 8648 VariableProxy* proxy = declaration->proxy(); |
8657 VariableMode mode = declaration->mode(); | 8649 VariableMode mode = declaration->mode(); |
8658 Variable* variable = proxy->var(); | 8650 Variable* variable = proxy->var(); |
8659 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8651 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
8660 switch (variable->location()) { | 8652 switch (variable->location()) { |
8661 case Variable::UNALLOCATED: | 8653 case Variable::UNALLOCATED: |
8662 globals_.Add(variable->name(), zone()); | 8654 globals_.Add(variable->name(), zone()); |
8663 globals_.Add(variable->binding_needs_init() | 8655 globals_.Add(variable->binding_needs_init() |
8664 ? isolate()->factory()->the_hole_value() | 8656 ? isolate()->factory()->the_hole_value() |
8665 : isolate()->factory()->undefined_value(), zone()); | 8657 : isolate()->factory()->undefined_value(), zone()); |
8666 return; | 8658 return; |
8667 case Variable::PARAMETER: | 8659 case Variable::PARAMETER: |
8668 case Variable::LOCAL: | 8660 case Variable::LOCAL: |
8669 if (hole_init) { | 8661 if (hole_init) { |
8670 HValue* value = graph()->GetConstantHole(); | 8662 HValue* value = graph()->GetConstantHole(); |
8671 environment()->Bind(variable, value); | 8663 environment()->Bind(variable, value); |
8672 } | 8664 } |
8673 break; | 8665 break; |
8674 case Variable::CONTEXT: | 8666 case Variable::CONTEXT: |
8675 if (hole_init) { | 8667 if (hole_init) { |
8676 HValue* value = graph()->GetConstantHole(); | 8668 HValue* value = graph()->GetConstantHole(); |
8677 HValue* context = environment()->LookupContext(); | 8669 HValue* context = environment()->context(); |
8678 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8670 HStoreContextSlot* store = AddAndCast<HStoreContextSlot>( |
8679 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8671 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8680 if (store->HasObservableSideEffects()) { | 8672 if (store->HasObservableSideEffects()) { |
8681 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8673 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8682 } | 8674 } |
8683 } | 8675 } |
8684 break; | 8676 break; |
8685 case Variable::LOOKUP: | 8677 case Variable::LOOKUP: |
8686 return Bailout("unsupported lookup slot in declaration"); | 8678 return Bailout("unsupported lookup slot in declaration"); |
8687 } | 8679 } |
8688 } | 8680 } |
(...skipping 16 matching lines...) Expand all Loading... |
8705 case Variable::PARAMETER: | 8697 case Variable::PARAMETER: |
8706 case Variable::LOCAL: { | 8698 case Variable::LOCAL: { |
8707 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8699 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8708 HValue* value = Pop(); | 8700 HValue* value = Pop(); |
8709 BindIfLive(variable, value); | 8701 BindIfLive(variable, value); |
8710 break; | 8702 break; |
8711 } | 8703 } |
8712 case Variable::CONTEXT: { | 8704 case Variable::CONTEXT: { |
8713 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8705 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8714 HValue* value = Pop(); | 8706 HValue* value = Pop(); |
8715 HValue* context = environment()->LookupContext(); | 8707 HValue* context = environment()->context(); |
8716 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8708 HStoreContextSlot* store = AddAndCast<HStoreContextSlot>( |
8717 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8709 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8718 if (store->HasObservableSideEffects()) { | 8710 if (store->HasObservableSideEffects()) { |
8719 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8711 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8720 } | 8712 } |
8721 break; | 8713 break; |
8722 } | 8714 } |
8723 case Variable::LOOKUP: | 8715 case Variable::LOOKUP: |
8724 return Bailout("unsupported lookup slot in declaration"); | 8716 return Bailout("unsupported lookup slot in declaration"); |
8725 } | 8717 } |
8726 } | 8718 } |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8880 | 8872 |
8881 | 8873 |
8882 // Support for arguments.length and arguments[?]. | 8874 // Support for arguments.length and arguments[?]. |
8883 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 8875 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
8884 // Our implementation of arguments (based on this stack frame or an | 8876 // Our implementation of arguments (based on this stack frame or an |
8885 // adapter below it) does not work for inlined functions. This runtime | 8877 // adapter below it) does not work for inlined functions. This runtime |
8886 // function is blacklisted by AstNode::IsInlineable. | 8878 // function is blacklisted by AstNode::IsInlineable. |
8887 ASSERT(function_state()->outer() == NULL); | 8879 ASSERT(function_state()->outer() == NULL); |
8888 ASSERT(call->arguments()->length() == 0); | 8880 ASSERT(call->arguments()->length() == 0); |
8889 HInstruction* elements = Add<HArgumentsElements>(false); | 8881 HInstruction* elements = Add<HArgumentsElements>(false); |
8890 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 8882 HArgumentsLength* result = NewAndCast<HArgumentsLength>(elements); |
8891 return ast_context()->ReturnInstruction(result, call->id()); | 8883 return ast_context()->ReturnInstruction(result, call->id()); |
8892 } | 8884 } |
8893 | 8885 |
8894 | 8886 |
8895 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 8887 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { |
8896 // Our implementation of arguments (based on this stack frame or an | 8888 // Our implementation of arguments (based on this stack frame or an |
8897 // adapter below it) does not work for inlined functions. This runtime | 8889 // adapter below it) does not work for inlined functions. This runtime |
8898 // function is blacklisted by AstNode::IsInlineable. | 8890 // function is blacklisted by AstNode::IsInlineable. |
8899 ASSERT(function_state()->outer() == NULL); | 8891 ASSERT(function_state()->outer() == NULL); |
8900 ASSERT(call->arguments()->length() == 1); | 8892 ASSERT(call->arguments()->length() == 1); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8989 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); | 8981 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); |
8990 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 8982 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
8991 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 8983 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
8992 typecheck->SetSuccessorAt(0, if_js_value); | 8984 typecheck->SetSuccessorAt(0, if_js_value); |
8993 typecheck->SetSuccessorAt(1, not_js_value); | 8985 typecheck->SetSuccessorAt(1, not_js_value); |
8994 current_block()->Finish(typecheck); | 8986 current_block()->Finish(typecheck); |
8995 not_js_value->Goto(join); | 8987 not_js_value->Goto(join); |
8996 | 8988 |
8997 // Create in-object property store to kValueOffset. | 8989 // Create in-object property store to kValueOffset. |
8998 set_current_block(if_js_value); | 8990 set_current_block(if_js_value); |
8999 AddStore(object, | 8991 Add<HStoreNamedField>(object, |
9000 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); | 8992 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); |
9001 if_js_value->Goto(join); | 8993 if_js_value->Goto(join); |
9002 join->SetJoinId(call->id()); | 8994 join->SetJoinId(call->id()); |
9003 set_current_block(join); | 8995 set_current_block(join); |
9004 return ast_context()->ReturnValue(value); | 8996 return ast_context()->ReturnValue(value); |
9005 } | 8997 } |
9006 | 8998 |
9007 | 8999 |
9008 // Fast support for charCodeAt(n). | 9000 // Fast support for charCodeAt(n). |
9009 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 9001 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
9010 ASSERT(call->arguments()->length() == 2); | 9002 ASSERT(call->arguments()->length() == 2); |
9011 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9003 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9012 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9004 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9013 HValue* index = Pop(); | 9005 HValue* index = Pop(); |
9014 HValue* string = Pop(); | 9006 HValue* string = Pop(); |
9015 HValue* context = environment()->LookupContext(); | 9007 HInstruction* result = BuildStringCharCodeAt(string, index); |
9016 HInstruction* result = BuildStringCharCodeAt(context, string, index); | |
9017 return ast_context()->ReturnInstruction(result, call->id()); | 9008 return ast_context()->ReturnInstruction(result, call->id()); |
9018 } | 9009 } |
9019 | 9010 |
9020 | 9011 |
9021 // Fast support for string.charAt(n) and string[n]. | 9012 // Fast support for string.charAt(n) and string[n]. |
9022 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 9013 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
9023 ASSERT(call->arguments()->length() == 1); | 9014 ASSERT(call->arguments()->length() == 1); |
9024 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9015 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9025 HValue* char_code = Pop(); | 9016 HValue* char_code = Pop(); |
9026 HValue* context = environment()->LookupContext(); | 9017 HInstruction* result = New<HStringCharFromCode>(char_code); |
9027 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code); | |
9028 return ast_context()->ReturnInstruction(result, call->id()); | 9018 return ast_context()->ReturnInstruction(result, call->id()); |
9029 } | 9019 } |
9030 | 9020 |
9031 | 9021 |
9032 // Fast support for string.charAt(n) and string[n]. | 9022 // Fast support for string.charAt(n) and string[n]. |
9033 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 9023 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
9034 ASSERT(call->arguments()->length() == 2); | 9024 ASSERT(call->arguments()->length() == 2); |
9035 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9025 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9036 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9026 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9037 HValue* index = Pop(); | 9027 HValue* index = Pop(); |
9038 HValue* string = Pop(); | 9028 HValue* string = Pop(); |
9039 HValue* context = environment()->LookupContext(); | 9029 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
9040 HInstruction* char_code = BuildStringCharCodeAt(context, string, index); | |
9041 AddInstruction(char_code); | 9030 AddInstruction(char_code); |
9042 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code); | 9031 HInstruction* result = New<HStringCharFromCode>(char_code); |
9043 return ast_context()->ReturnInstruction(result, call->id()); | 9032 return ast_context()->ReturnInstruction(result, call->id()); |
9044 } | 9033 } |
9045 | 9034 |
9046 | 9035 |
9047 // Fast support for object equality testing. | 9036 // Fast support for object equality testing. |
9048 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 9037 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
9049 ASSERT(call->arguments()->length() == 2); | 9038 ASSERT(call->arguments()->length() == 2); |
9050 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9039 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9051 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9040 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9052 HValue* right = Pop(); | 9041 HValue* right = Pop(); |
9053 HValue* left = Pop(); | 9042 HValue* left = Pop(); |
9054 HCompareObjectEqAndBranch* result = | 9043 HCompareObjectEqAndBranch* result = |
9055 new(zone()) HCompareObjectEqAndBranch(left, right); | 9044 NewAndCast<HCompareObjectEqAndBranch>(left, right); |
9056 return ast_context()->ReturnControl(result, call->id()); | 9045 return ast_context()->ReturnControl(result, call->id()); |
9057 } | 9046 } |
9058 | 9047 |
9059 | 9048 |
9060 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 9049 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { |
9061 // %_Log is ignored in optimized code. | 9050 // %_Log is ignored in optimized code. |
9062 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 9051 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
9063 } | 9052 } |
9064 | 9053 |
9065 | 9054 |
9066 // Fast support for Math.random(). | 9055 // Fast support for Math.random(). |
9067 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 9056 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
9068 HValue* context = environment()->LookupContext(); | 9057 HGlobalObject* global_object = AddAndCast<HGlobalObject>(); |
9069 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
9070 HRandom* result = new(zone()) HRandom(global_object); | 9058 HRandom* result = new(zone()) HRandom(global_object); |
9071 return ast_context()->ReturnInstruction(result, call->id()); | 9059 return ast_context()->ReturnInstruction(result, call->id()); |
9072 } | 9060 } |
9073 | 9061 |
9074 | 9062 |
9075 // Fast support for StringAdd. | 9063 // Fast support for StringAdd. |
9076 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9064 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
9077 ASSERT_EQ(2, call->arguments()->length()); | 9065 ASSERT_EQ(2, call->arguments()->length()); |
9078 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9066 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9079 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9067 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9080 HValue* right = Pop(); | 9068 HValue* right = Pop(); |
9081 HValue* left = Pop(); | 9069 HValue* left = Pop(); |
9082 HValue* context = environment()->LookupContext(); | 9070 HValue* context = environment()->context(); |
9083 HInstruction* result = HStringAdd::New( | 9071 HInstruction* result = HStringAdd::New( |
9084 zone(), context, left, right, STRING_ADD_CHECK_BOTH); | 9072 zone(), context, left, right, STRING_ADD_CHECK_BOTH); |
9085 return ast_context()->ReturnInstruction(result, call->id()); | 9073 return ast_context()->ReturnInstruction(result, call->id()); |
9086 } | 9074 } |
9087 | 9075 |
9088 | 9076 |
9089 // Fast support for SubString. | 9077 // Fast support for SubString. |
9090 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9078 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
9091 ASSERT_EQ(3, call->arguments()->length()); | 9079 ASSERT_EQ(3, call->arguments()->length()); |
9092 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9080 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9093 HValue* context = environment()->LookupContext(); | 9081 HValue* context = environment()->context(); |
9094 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 9082 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
9095 Drop(3); | 9083 Drop(3); |
9096 return ast_context()->ReturnInstruction(result, call->id()); | 9084 return ast_context()->ReturnInstruction(result, call->id()); |
9097 } | 9085 } |
9098 | 9086 |
9099 | 9087 |
9100 // Fast support for StringCompare. | 9088 // Fast support for StringCompare. |
9101 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9089 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
9102 ASSERT_EQ(2, call->arguments()->length()); | 9090 ASSERT_EQ(2, call->arguments()->length()); |
9103 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9091 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9104 HValue* context = environment()->LookupContext(); | 9092 HValue* context = environment()->context(); |
9105 HCallStub* result = | 9093 HCallStub* result = |
9106 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 9094 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
9107 Drop(2); | 9095 Drop(2); |
9108 return ast_context()->ReturnInstruction(result, call->id()); | 9096 return ast_context()->ReturnInstruction(result, call->id()); |
9109 } | 9097 } |
9110 | 9098 |
9111 | 9099 |
9112 // Support for direct calls from JavaScript to native RegExp code. | 9100 // Support for direct calls from JavaScript to native RegExp code. |
9113 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9101 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
9114 ASSERT_EQ(4, call->arguments()->length()); | 9102 ASSERT_EQ(4, call->arguments()->length()); |
9115 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9103 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9116 HValue* context = environment()->LookupContext(); | 9104 HValue* context = environment()->context(); |
9117 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 9105 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
9118 Drop(4); | 9106 Drop(4); |
9119 return ast_context()->ReturnInstruction(result, call->id()); | 9107 return ast_context()->ReturnInstruction(result, call->id()); |
9120 } | 9108 } |
9121 | 9109 |
9122 | 9110 |
9123 // Construct a RegExp exec result with two in-object properties. | 9111 // Construct a RegExp exec result with two in-object properties. |
9124 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9112 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
9125 ASSERT_EQ(3, call->arguments()->length()); | 9113 ASSERT_EQ(3, call->arguments()->length()); |
9126 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9114 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9127 HValue* context = environment()->LookupContext(); | 9115 HValue* context = environment()->context(); |
9128 HCallStub* result = | 9116 HCallStub* result = |
9129 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 9117 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
9130 Drop(3); | 9118 Drop(3); |
9131 return ast_context()->ReturnInstruction(result, call->id()); | 9119 return ast_context()->ReturnInstruction(result, call->id()); |
9132 } | 9120 } |
9133 | 9121 |
9134 | 9122 |
9135 // Support for fast native caches. | 9123 // Support for fast native caches. |
9136 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9124 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9137 return Bailout("inlined runtime function: GetFromCache"); | 9125 return Bailout("inlined runtime function: GetFromCache"); |
9138 } | 9126 } |
9139 | 9127 |
9140 | 9128 |
9141 // Fast support for number to string. | 9129 // Fast support for number to string. |
9142 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9130 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9143 ASSERT_EQ(1, call->arguments()->length()); | 9131 ASSERT_EQ(1, call->arguments()->length()); |
9144 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9132 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9145 HValue* context = environment()->LookupContext(); | 9133 HValue* context = environment()->context(); |
9146 HCallStub* result = | 9134 HCallStub* result = |
9147 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9135 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
9148 Drop(1); | 9136 Drop(1); |
9149 return ast_context()->ReturnInstruction(result, call->id()); | 9137 return ast_context()->ReturnInstruction(result, call->id()); |
9150 } | 9138 } |
9151 | 9139 |
9152 | 9140 |
9153 // Fast call for custom callbacks. | 9141 // Fast call for custom callbacks. |
9154 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9142 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9155 // 1 ~ The function to call is not itself an argument to the call. | 9143 // 1 ~ The function to call is not itself an argument to the call. |
9156 int arg_count = call->arguments()->length() - 1; | 9144 int arg_count = call->arguments()->length() - 1; |
9157 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9145 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9158 | 9146 |
9159 for (int i = 0; i < arg_count; ++i) { | 9147 for (int i = 0; i < arg_count; ++i) { |
9160 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9148 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
9161 } | 9149 } |
9162 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9150 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
9163 | 9151 |
9164 HValue* function = Pop(); | 9152 HValue* function = Pop(); |
9165 HValue* context = environment()->LookupContext(); | |
9166 | 9153 |
9167 // Branch for function proxies, or other non-functions. | 9154 // Branch for function proxies, or other non-functions. |
9168 HHasInstanceTypeAndBranch* typecheck = | 9155 HHasInstanceTypeAndBranch* typecheck = |
9169 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); | 9156 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); |
9170 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | 9157 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); |
9171 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | 9158 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); |
9172 HBasicBlock* join = graph()->CreateBasicBlock(); | 9159 HBasicBlock* join = graph()->CreateBasicBlock(); |
9173 typecheck->SetSuccessorAt(0, if_jsfunction); | 9160 typecheck->SetSuccessorAt(0, if_jsfunction); |
9174 typecheck->SetSuccessorAt(1, if_nonfunction); | 9161 typecheck->SetSuccessorAt(1, if_nonfunction); |
9175 current_block()->Finish(typecheck); | 9162 current_block()->Finish(typecheck); |
9176 | 9163 |
9177 set_current_block(if_jsfunction); | 9164 set_current_block(if_jsfunction); |
9178 HInstruction* invoke_result = | 9165 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); |
9179 Add<HInvokeFunction>(context, function, arg_count); | |
9180 Drop(arg_count); | 9166 Drop(arg_count); |
9181 Push(invoke_result); | 9167 Push(invoke_result); |
9182 if_jsfunction->Goto(join); | 9168 if_jsfunction->Goto(join); |
9183 | 9169 |
9184 set_current_block(if_nonfunction); | 9170 set_current_block(if_nonfunction); |
9185 HInstruction* call_result = Add<HCallFunction>(context, function, arg_count); | 9171 HInstruction* call_result = Add<HCallFunction>(function, arg_count); |
9186 Drop(arg_count); | 9172 Drop(arg_count); |
9187 Push(call_result); | 9173 Push(call_result); |
9188 if_nonfunction->Goto(join); | 9174 if_nonfunction->Goto(join); |
9189 | 9175 |
9190 set_current_block(join); | 9176 set_current_block(join); |
9191 join->SetJoinId(call->id()); | 9177 join->SetJoinId(call->id()); |
9192 return ast_context()->ReturnValue(Pop()); | 9178 return ast_context()->ReturnValue(Pop()); |
9193 } | 9179 } |
9194 | 9180 |
9195 | 9181 |
9196 // Fast call to math functions. | 9182 // Fast call to math functions. |
9197 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9183 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
9198 ASSERT_EQ(2, call->arguments()->length()); | 9184 ASSERT_EQ(2, call->arguments()->length()); |
9199 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9185 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9200 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9186 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9201 HValue* right = Pop(); | 9187 HValue* right = Pop(); |
9202 HValue* left = Pop(); | 9188 HValue* left = Pop(); |
9203 HInstruction* result = HPower::New(zone(), left, right); | 9189 HInstruction* result = HPower::New(zone(), context(), left, right); |
9204 return ast_context()->ReturnInstruction(result, call->id()); | 9190 return ast_context()->ReturnInstruction(result, call->id()); |
9205 } | 9191 } |
9206 | 9192 |
9207 | 9193 |
9208 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9194 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { |
9209 ASSERT_EQ(1, call->arguments()->length()); | 9195 ASSERT_EQ(1, call->arguments()->length()); |
9210 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9196 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9211 HValue* context = environment()->LookupContext(); | 9197 HValue* context = environment()->context(); |
9212 HCallStub* result = | 9198 HCallStub* result = |
9213 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9199 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9214 result->set_transcendental_type(TranscendentalCache::SIN); | 9200 result->set_transcendental_type(TranscendentalCache::SIN); |
9215 Drop(1); | 9201 Drop(1); |
9216 return ast_context()->ReturnInstruction(result, call->id()); | 9202 return ast_context()->ReturnInstruction(result, call->id()); |
9217 } | 9203 } |
9218 | 9204 |
9219 | 9205 |
9220 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9206 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { |
9221 ASSERT_EQ(1, call->arguments()->length()); | 9207 ASSERT_EQ(1, call->arguments()->length()); |
9222 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9208 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9223 HValue* context = environment()->LookupContext(); | 9209 HValue* context = environment()->context(); |
9224 HCallStub* result = | 9210 HCallStub* result = |
9225 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9211 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9226 result->set_transcendental_type(TranscendentalCache::COS); | 9212 result->set_transcendental_type(TranscendentalCache::COS); |
9227 Drop(1); | 9213 Drop(1); |
9228 return ast_context()->ReturnInstruction(result, call->id()); | 9214 return ast_context()->ReturnInstruction(result, call->id()); |
9229 } | 9215 } |
9230 | 9216 |
9231 | 9217 |
9232 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9218 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { |
9233 ASSERT_EQ(1, call->arguments()->length()); | 9219 ASSERT_EQ(1, call->arguments()->length()); |
9234 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9220 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9235 HValue* context = environment()->LookupContext(); | 9221 HValue* context = environment()->context(); |
9236 HCallStub* result = | 9222 HCallStub* result = |
9237 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9223 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9238 result->set_transcendental_type(TranscendentalCache::TAN); | 9224 result->set_transcendental_type(TranscendentalCache::TAN); |
9239 Drop(1); | 9225 Drop(1); |
9240 return ast_context()->ReturnInstruction(result, call->id()); | 9226 return ast_context()->ReturnInstruction(result, call->id()); |
9241 } | 9227 } |
9242 | 9228 |
9243 | 9229 |
9244 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9230 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { |
9245 ASSERT_EQ(1, call->arguments()->length()); | 9231 ASSERT_EQ(1, call->arguments()->length()); |
9246 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9232 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9247 HValue* context = environment()->LookupContext(); | 9233 HValue* context = environment()->context(); |
9248 HCallStub* result = | 9234 HCallStub* result = |
9249 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9235 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9250 result->set_transcendental_type(TranscendentalCache::LOG); | 9236 result->set_transcendental_type(TranscendentalCache::LOG); |
9251 Drop(1); | 9237 Drop(1); |
9252 return ast_context()->ReturnInstruction(result, call->id()); | 9238 return ast_context()->ReturnInstruction(result, call->id()); |
9253 } | 9239 } |
9254 | 9240 |
9255 | 9241 |
9256 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9242 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
9257 ASSERT(call->arguments()->length() == 1); | 9243 ASSERT(call->arguments()->length() == 1); |
9258 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9244 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9259 HValue* value = Pop(); | 9245 HValue* value = Pop(); |
9260 HValue* context = environment()->LookupContext(); | 9246 HValue* context = environment()->context(); |
9261 HInstruction* result = | 9247 HInstruction* result = |
9262 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); | 9248 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); |
9263 return ast_context()->ReturnInstruction(result, call->id()); | 9249 return ast_context()->ReturnInstruction(result, call->id()); |
9264 } | 9250 } |
9265 | 9251 |
9266 | 9252 |
9267 // Check whether two RegExps are equivalent | 9253 // Check whether two RegExps are equivalent |
9268 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9254 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9269 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9255 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
9270 } | 9256 } |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9560 HValue* push = (i <= arguments) ? | 9546 HValue* push = (i <= arguments) ? |
9561 ExpressionStackAt(arguments - i) : undefined; | 9547 ExpressionStackAt(arguments - i) : undefined; |
9562 inner->SetValueAt(i, push); | 9548 inner->SetValueAt(i, push); |
9563 } | 9549 } |
9564 // If the function we are inlining is a strict mode function or a | 9550 // If the function we are inlining is a strict mode function or a |
9565 // builtin function, pass undefined as the receiver for function | 9551 // builtin function, pass undefined as the receiver for function |
9566 // calls (instead of the global receiver). | 9552 // calls (instead of the global receiver). |
9567 if (undefined_receiver) { | 9553 if (undefined_receiver) { |
9568 inner->SetValueAt(0, undefined); | 9554 inner->SetValueAt(0, undefined); |
9569 } | 9555 } |
9570 inner->SetValueAt(arity + 1, LookupContext()); | 9556 inner->SetValueAt(arity + 1, context()); |
9571 for (int i = arity + 2; i < inner->length(); ++i) { | 9557 for (int i = arity + 2; i < inner->length(); ++i) { |
9572 inner->SetValueAt(i, undefined); | 9558 inner->SetValueAt(i, undefined); |
9573 } | 9559 } |
9574 | 9560 |
9575 inner->set_ast_id(BailoutId::FunctionEntry()); | 9561 inner->set_ast_id(BailoutId::FunctionEntry()); |
9576 return inner; | 9562 return inner; |
9577 } | 9563 } |
9578 | 9564 |
9579 | 9565 |
9580 void HEnvironment::PrintTo(StringStream* stream) { | 9566 void HEnvironment::PrintTo(StringStream* stream) { |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9910 if (ShouldProduceTraceOutput()) { | 9896 if (ShouldProduceTraceOutput()) { |
9911 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9897 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9912 } | 9898 } |
9913 | 9899 |
9914 #ifdef DEBUG | 9900 #ifdef DEBUG |
9915 graph_->Verify(false); // No full verify. | 9901 graph_->Verify(false); // No full verify. |
9916 #endif | 9902 #endif |
9917 } | 9903 } |
9918 | 9904 |
9919 } } // namespace v8::internal | 9905 } } // namespace v8::internal |
OLD | NEW |