| 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 |