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 // Can't pass GetInvalidContext() to HConstant::New, because that will |
| 613 // recursively call GetConstant |
| 614 HConstant* constant = HConstant::New(zone(), NULL, value); |
613 constant->InsertAfter(GetConstantUndefined()); | 615 constant->InsertAfter(GetConstantUndefined()); |
614 pointer->set(constant); | 616 pointer->set(constant); |
615 } | 617 } |
616 return pointer->get(); | 618 return pointer->get(); |
617 } | 619 } |
618 | 620 |
619 | 621 |
620 HConstant* HGraph::GetConstant0() { | 622 HConstant* HGraph::GetConstant0() { |
621 return GetConstant(&constant_0_, 0); | 623 return GetConstant(&constant_0_, 0); |
622 } | 624 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 deopt_else_ = true; | 830 deopt_else_ = true; |
829 } else { | 831 } else { |
830 deopt_then_ = true; | 832 deopt_then_ = true; |
831 } | 833 } |
832 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); | 834 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); |
833 } | 835 } |
834 | 836 |
835 | 837 |
836 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 838 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
837 HBasicBlock* block = builder_->current_block(); | 839 HBasicBlock* block = builder_->current_block(); |
838 HValue* context = builder_->environment()->LookupContext(); | |
839 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 840 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
840 block->FinishExit(new(zone()) HReturn(value, context, parameter_count)); | 841 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); |
841 builder_->set_current_block(NULL); | 842 builder_->set_current_block(NULL); |
842 if (did_else_) { | 843 if (did_else_) { |
843 first_false_block_ = NULL; | 844 first_false_block_ = NULL; |
844 } else { | 845 } else { |
845 first_true_block_ = NULL; | 846 first_true_block_ = NULL; |
846 } | 847 } |
847 } | 848 } |
848 | 849 |
849 | 850 |
850 void HGraphBuilder::IfBuilder::End() { | 851 void HGraphBuilder::IfBuilder::End() { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 985 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
985 } | 986 } |
986 return instr; | 987 return instr; |
987 } | 988 } |
988 | 989 |
989 | 990 |
990 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, | 991 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, |
991 HValue* context) { | 992 HValue* context) { |
992 if (FLAG_native_code_counters && counter->Enabled()) { | 993 if (FLAG_native_code_counters && counter->Enabled()) { |
993 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 994 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
994 HValue* old_value = AddLoad(reference, HObjectAccess::ForCounter(), NULL); | 995 HValue* old_value = Add<HLoadNamedField>(reference, |
995 HValue* new_value = AddInstruction( | 996 HObjectAccess::ForCounter()); |
996 HAdd::New(zone(), context, old_value, graph()->GetConstant1())); | 997 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); |
997 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 998 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
998 AddStore(reference, HObjectAccess::ForCounter(), new_value); | 999 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
| 1000 new_value); |
999 } | 1001 } |
1000 } | 1002 } |
1001 | 1003 |
1002 | 1004 |
| 1005 void HGraphBuilder::AddSimulate(BailoutId id, |
| 1006 RemovableSimulate removable) { |
| 1007 ASSERT(current_block() != NULL); |
| 1008 ASSERT(no_side_effects_scope_count_ == 0); |
| 1009 current_block()->AddSimulate(id, removable); |
| 1010 } |
| 1011 |
| 1012 |
1003 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 1013 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
1004 HBasicBlock* b = graph()->CreateBasicBlock(); | 1014 HBasicBlock* b = graph()->CreateBasicBlock(); |
1005 b->SetInitialEnvironment(env); | 1015 b->SetInitialEnvironment(env); |
1006 return b; | 1016 return b; |
1007 } | 1017 } |
1008 | 1018 |
1009 | 1019 |
1010 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1020 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
1011 HBasicBlock* header = graph()->CreateBasicBlock(); | 1021 HBasicBlock* header = graph()->CreateBasicBlock(); |
1012 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1022 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 from->last_environment()->Pop(); | 1059 from->last_environment()->Pop(); |
1050 } | 1060 } |
1051 } | 1061 } |
1052 } else { | 1062 } else { |
1053 ASSERT(continuation->predecessors()->length() == 0); | 1063 ASSERT(continuation->predecessors()->length() == 0); |
1054 } | 1064 } |
1055 } | 1065 } |
1056 | 1066 |
1057 | 1067 |
1058 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { | 1068 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { |
1059 HCheckMaps* check = HCheckMaps::New(obj, map, zone(), top_info()); | 1069 return Add<HCheckMaps>(obj, map, top_info()); |
1060 AddInstruction(check); | |
1061 return check; | |
1062 } | 1070 } |
1063 | 1071 |
1064 | 1072 |
1065 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { | 1073 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { |
1066 if (object->type().IsJSObject()) return object; | 1074 if (object->type().IsJSObject()) return object; |
1067 return Add<HWrapReceiver>(object, function); | 1075 return Add<HWrapReceiver>(object, function); |
1068 } | 1076 } |
1069 | 1077 |
1070 | 1078 |
1071 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1079 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
(...skipping 11 matching lines...) Expand all Loading... |
1083 length_checker.Then(); | 1091 length_checker.Then(); |
1084 | 1092 |
1085 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1093 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
1086 | 1094 |
1087 IfBuilder capacity_checker(this); | 1095 IfBuilder capacity_checker(this); |
1088 | 1096 |
1089 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, | 1097 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity, |
1090 Token::GTE); | 1098 Token::GTE); |
1091 capacity_checker.Then(); | 1099 capacity_checker.Then(); |
1092 | 1100 |
1093 HValue* context = environment()->LookupContext(); | 1101 HValue* context = environment()->context(); |
1094 | 1102 |
1095 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1103 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
1096 HValue* max_capacity = AddInstruction( | 1104 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); |
1097 HAdd::New(zone, context, current_capacity, max_gap)); | |
1098 IfBuilder key_checker(this); | 1105 IfBuilder key_checker(this); |
1099 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); | 1106 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); |
1100 key_checker.Then(); | 1107 key_checker.Then(); |
1101 key_checker.ElseDeopt(); | 1108 key_checker.ElseDeopt(); |
1102 key_checker.End(); | 1109 key_checker.End(); |
1103 | 1110 |
1104 HValue* new_capacity = BuildNewElementsCapacity(context, key); | 1111 HValue* new_capacity = BuildNewElementsCapacity(key); |
1105 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1112 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
1106 kind, kind, length, | 1113 kind, kind, length, |
1107 new_capacity); | 1114 new_capacity); |
1108 | 1115 |
1109 environment()->Push(new_elements); | 1116 environment()->Push(new_elements); |
1110 capacity_checker.Else(); | 1117 capacity_checker.Else(); |
1111 | 1118 |
1112 environment()->Push(elements); | 1119 environment()->Push(elements); |
1113 capacity_checker.End(); | 1120 capacity_checker.End(); |
1114 | 1121 |
1115 if (is_js_array) { | 1122 if (is_js_array) { |
1116 HValue* new_length = AddInstruction( | 1123 HValue* new_length = AddInstruction( |
1117 HAdd::New(zone, context, key, graph_->GetConstant1())); | 1124 HAdd::New(zone, context, key, graph_->GetConstant1())); |
1118 new_length->ClearFlag(HValue::kCanOverflow); | 1125 new_length->ClearFlag(HValue::kCanOverflow); |
1119 | 1126 |
1120 AddStore(object, HObjectAccess::ForArrayLength(kind), new_length); | 1127 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
| 1128 new_length); |
1121 } | 1129 } |
1122 | 1130 |
1123 length_checker.Else(); | 1131 length_checker.Else(); |
1124 Add<HBoundsCheck>(key, length); | 1132 Add<HBoundsCheck>(key, length); |
1125 | 1133 |
1126 environment()->Push(elements); | 1134 environment()->Push(elements); |
1127 length_checker.End(); | 1135 length_checker.End(); |
1128 | 1136 |
1129 return environment()->Pop(); | 1137 return environment()->Pop(); |
1130 } | 1138 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1167 IsFastHoleyElementsKind(to_kind)); | 1175 IsFastHoleyElementsKind(to_kind)); |
1168 | 1176 |
1169 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1177 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
1170 Add<HTrapAllocationMemento>(object); | 1178 Add<HTrapAllocationMemento>(object); |
1171 } | 1179 } |
1172 | 1180 |
1173 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1181 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
1174 HInstruction* elements = AddLoadElements(object); | 1182 HInstruction* elements = AddLoadElements(object); |
1175 | 1183 |
1176 HInstruction* empty_fixed_array = Add<HConstant>( | 1184 HInstruction* empty_fixed_array = Add<HConstant>( |
1177 isolate()->factory()->empty_fixed_array(), Representation::Tagged()); | 1185 isolate()->factory()->empty_fixed_array()); |
1178 | 1186 |
1179 IfBuilder if_builder(this); | 1187 IfBuilder if_builder(this); |
1180 | 1188 |
1181 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1189 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
1182 | 1190 |
1183 if_builder.Then(); | 1191 if_builder.Then(); |
1184 | 1192 |
1185 HInstruction* elements_length = AddLoadFixedArrayLength(elements); | 1193 HInstruction* elements_length = AddLoadFixedArrayLength(elements); |
1186 | 1194 |
1187 HInstruction* array_length = is_jsarray | 1195 HInstruction* array_length = is_jsarray |
1188 ? AddLoad(object, HObjectAccess::ForArrayLength(from_kind), NULL) | 1196 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) |
1189 : elements_length; | 1197 : elements_length; |
1190 | 1198 |
1191 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1199 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1192 array_length, elements_length); | 1200 array_length, elements_length); |
1193 | 1201 |
1194 if_builder.End(); | 1202 if_builder.End(); |
1195 } | 1203 } |
1196 | 1204 |
1197 AddStore(object, HObjectAccess::ForMap(), map); | 1205 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
1198 } | 1206 } |
1199 | 1207 |
1200 | 1208 |
1201 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1209 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1202 HValue* object, | 1210 HValue* object, |
1203 HValue* key, | 1211 HValue* key, |
1204 HValue* val, | 1212 HValue* val, |
1205 HCheckMaps* mapcheck, | 1213 HCheckMaps* mapcheck, |
1206 bool is_js_array, | 1214 bool is_js_array, |
1207 ElementsKind elements_kind, | 1215 ElementsKind elements_kind, |
1208 bool is_store, | 1216 bool is_store, |
1209 LoadKeyedHoleMode load_mode, | 1217 LoadKeyedHoleMode load_mode, |
1210 KeyedAccessStoreMode store_mode) { | 1218 KeyedAccessStoreMode store_mode) { |
1211 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1219 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
1212 Zone* zone = this->zone(); | |
1213 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1220 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
1214 // on a HElementsTransition instruction. The flag can also be removed if the | 1221 // on a HElementsTransition instruction. The flag can also be removed if the |
1215 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1222 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
1216 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1223 // ElementsKind transitions. Finally, the dependency can be removed for stores |
1217 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1224 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
1218 // generated store code. | 1225 // generated store code. |
1219 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 1226 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
1220 (elements_kind == FAST_ELEMENTS && is_store)) { | 1227 (elements_kind == FAST_ELEMENTS && is_store)) { |
1221 if (mapcheck != NULL) { | 1228 if (mapcheck != NULL) { |
1222 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 1229 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
1223 } | 1230 } |
1224 } | 1231 } |
1225 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1232 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
1226 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1233 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
1227 HValue* elements = AddLoadElements(object, mapcheck); | 1234 HValue* elements = AddLoadElements(object, mapcheck); |
1228 if (is_store && (fast_elements || fast_smi_only_elements) && | 1235 if (is_store && (fast_elements || fast_smi_only_elements) && |
1229 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1236 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1230 HCheckMaps* check_cow_map = HCheckMaps::New( | 1237 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
1231 elements, isolate()->factory()->fixed_array_map(), zone, top_info()); | 1238 elements, isolate()->factory()->fixed_array_map(), top_info()); |
1232 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1239 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1233 AddInstruction(check_cow_map); | |
1234 } | 1240 } |
1235 HInstruction* length = NULL; | 1241 HInstruction* length = NULL; |
1236 if (is_js_array) { | 1242 if (is_js_array) { |
1237 length = AddLoad(object, HObjectAccess::ForArrayLength(elements_kind), | 1243 length = Add<HLoadNamedField>(object, |
1238 mapcheck); | 1244 HObjectAccess::ForArrayLength(elements_kind), mapcheck); |
1239 } else { | 1245 } else { |
1240 length = AddLoadFixedArrayLength(elements); | 1246 length = AddLoadFixedArrayLength(elements); |
1241 } | 1247 } |
1242 length->set_type(HType::Smi()); | 1248 length->set_type(HType::Smi()); |
1243 HValue* checked_key = NULL; | 1249 HValue* checked_key = NULL; |
1244 if (IsExternalArrayElementsKind(elements_kind)) { | 1250 if (IsExternalArrayElementsKind(elements_kind)) { |
1245 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1251 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1246 NoObservableSideEffectsScope no_effects(this); | 1252 NoObservableSideEffectsScope no_effects(this); |
1247 HLoadExternalArrayPointer* external_elements = | 1253 HLoadExternalArrayPointer* external_elements = |
1248 Add<HLoadExternalArrayPointer>(elements); | 1254 Add<HLoadExternalArrayPointer>(elements); |
1249 IfBuilder length_checker(this); | 1255 IfBuilder length_checker(this); |
1250 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1256 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
1251 length_checker.Then(); | 1257 length_checker.Then(); |
1252 IfBuilder negative_checker(this); | 1258 IfBuilder negative_checker(this); |
1253 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1259 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
1254 key, graph()->GetConstant0(), Token::GTE); | 1260 key, graph()->GetConstant0(), Token::GTE); |
1255 negative_checker.Then(); | 1261 negative_checker.Then(); |
1256 HInstruction* result = AddExternalArrayElementAccess( | 1262 HInstruction* result = AddExternalArrayElementAccess( |
1257 external_elements, key, val, bounds_check, elements_kind, is_store); | 1263 external_elements, key, val, bounds_check, elements_kind, is_store); |
1258 negative_checker.ElseDeopt(); | 1264 negative_checker.ElseDeopt(); |
(...skipping 29 matching lines...) Expand all Loading... |
1288 } else { | 1294 } else { |
1289 checked_key = Add<HBoundsCheck>(key, length); | 1295 checked_key = Add<HBoundsCheck>(key, length); |
1290 | 1296 |
1291 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1297 if (is_store && (fast_elements || fast_smi_only_elements)) { |
1292 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1298 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
1293 NoObservableSideEffectsScope no_effects(this); | 1299 NoObservableSideEffectsScope no_effects(this); |
1294 | 1300 |
1295 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1301 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
1296 length); | 1302 length); |
1297 } else { | 1303 } else { |
1298 HCheckMaps* check_cow_map = HCheckMaps::New( | 1304 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
1299 elements, isolate()->factory()->fixed_array_map(), | 1305 elements, isolate()->factory()->fixed_array_map(), |
1300 zone, top_info()); | 1306 top_info()); |
1301 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1307 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1302 AddInstruction(check_cow_map); | |
1303 } | 1308 } |
1304 } | 1309 } |
1305 } | 1310 } |
1306 return AddFastElementAccess(elements, checked_key, val, mapcheck, | 1311 return AddFastElementAccess(elements, checked_key, val, mapcheck, |
1307 elements_kind, is_store, load_mode, store_mode); | 1312 elements_kind, is_store, load_mode, store_mode); |
1308 } | 1313 } |
1309 | 1314 |
1310 | 1315 |
1311 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1316 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
1312 ElementsKind kind, | |
1313 HValue* capacity) { | 1317 HValue* capacity) { |
1314 Zone* zone = this->zone(); | |
1315 | |
1316 int elements_size = IsFastDoubleElementsKind(kind) | 1318 int elements_size = IsFastDoubleElementsKind(kind) |
1317 ? kDoubleSize : kPointerSize; | 1319 ? kDoubleSize : kPointerSize; |
1318 HConstant* elements_size_value = Add<HConstant>(elements_size); | 1320 HConstant* elements_size_value = Add<HConstant>(elements_size); |
1319 HValue* mul = AddInstruction( | 1321 HValue* mul = Add<HMul>(capacity, elements_size_value); |
1320 HMul::New(zone, context, capacity, elements_size_value)); | |
1321 mul->ClearFlag(HValue::kCanOverflow); | 1322 mul->ClearFlag(HValue::kCanOverflow); |
1322 | 1323 |
1323 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); | 1324 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize); |
1324 HValue* total_size = AddInstruction( | 1325 HValue* total_size = Add<HAdd>(mul, header_size); |
1325 HAdd::New(zone, context, mul, header_size)); | |
1326 total_size->ClearFlag(HValue::kCanOverflow); | 1326 total_size->ClearFlag(HValue::kCanOverflow); |
1327 | 1327 |
1328 return Add<HAllocate>(context, total_size, HType::JSArray(), | 1328 return Add<HAllocate>(total_size, HType::JSArray(), |
1329 isolate()->heap()->ShouldGloballyPretenure(), kind); | 1329 isolate()->heap()->ShouldGloballyPretenure(), kind); |
1330 } | 1330 } |
1331 | 1331 |
1332 | 1332 |
1333 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, | 1333 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, |
1334 ElementsKind kind, | 1334 ElementsKind kind, |
1335 HValue* capacity) { | 1335 HValue* capacity) { |
1336 Factory* factory = isolate()->factory(); | 1336 Factory* factory = isolate()->factory(); |
1337 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1337 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1338 ? factory->fixed_double_array_map() | 1338 ? factory->fixed_double_array_map() |
1339 : factory->fixed_array_map(); | 1339 : factory->fixed_array_map(); |
1340 | 1340 |
1341 AddStoreMapConstant(elements, map); | 1341 AddStoreMapConstant(elements, map); |
1342 AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity); | 1342 Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(), |
| 1343 capacity); |
1343 } | 1344 } |
1344 | 1345 |
1345 | 1346 |
1346 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( | 1347 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader( |
1347 HValue* context, | |
1348 ElementsKind kind, | 1348 ElementsKind kind, |
1349 HValue* capacity) { | 1349 HValue* capacity) { |
1350 // The HForceRepresentation is to prevent possible deopt on int-smi | 1350 // The HForceRepresentation is to prevent possible deopt on int-smi |
1351 // conversion after allocation but before the new object fields are set. | 1351 // conversion after allocation but before the new object fields are set. |
1352 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); | 1352 capacity = Add<HForceRepresentation>(capacity, Representation::Smi()); |
1353 HValue* new_elements = BuildAllocateElements(context, kind, capacity); | 1353 HValue* new_elements = BuildAllocateElements(kind, capacity); |
1354 BuildInitializeElementsHeader(new_elements, kind, capacity); | 1354 BuildInitializeElementsHeader(new_elements, kind, capacity); |
1355 return new_elements; | 1355 return new_elements; |
1356 } | 1356 } |
1357 | 1357 |
1358 | 1358 |
1359 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, | 1359 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, |
1360 HValue* array_map, | 1360 HValue* array_map, |
1361 AllocationSiteMode mode, | 1361 AllocationSiteMode mode, |
1362 ElementsKind elements_kind, | 1362 ElementsKind elements_kind, |
1363 HValue* allocation_site_payload, | 1363 HValue* allocation_site_payload, |
1364 HValue* length_field) { | 1364 HValue* length_field) { |
1365 | 1365 |
1366 AddStore(array, HObjectAccess::ForMap(), array_map); | 1366 Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map); |
1367 | 1367 |
1368 HConstant* empty_fixed_array = | 1368 HConstant* empty_fixed_array = |
1369 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 1369 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
1370 | 1370 |
1371 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 1371 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
1372 AddStore(array, access, empty_fixed_array); | 1372 Add<HStoreNamedField>(array, access, empty_fixed_array); |
1373 AddStore(array, HObjectAccess::ForArrayLength(elements_kind), length_field); | 1373 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
| 1374 length_field); |
1374 | 1375 |
1375 if (mode == TRACK_ALLOCATION_SITE) { | 1376 if (mode == TRACK_ALLOCATION_SITE) { |
1376 BuildCreateAllocationMemento(array, | 1377 BuildCreateAllocationMemento(array, |
1377 JSArray::kSize, | 1378 JSArray::kSize, |
1378 allocation_site_payload); | 1379 allocation_site_payload); |
1379 } | 1380 } |
1380 | 1381 |
1381 int elements_location = JSArray::kSize; | 1382 int elements_location = JSArray::kSize; |
1382 if (mode == TRACK_ALLOCATION_SITE) { | 1383 if (mode == TRACK_ALLOCATION_SITE) { |
1383 elements_location += AllocationMemento::kSize; | 1384 elements_location += AllocationMemento::kSize; |
1384 } | 1385 } |
1385 | 1386 |
1386 HInnerAllocatedObject* elements = | 1387 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location); |
1387 Add<HInnerAllocatedObject>(array, elements_location); | 1388 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
1388 AddStore(array, HObjectAccess::ForElementsPointer(), elements); | 1389 return static_cast<HInnerAllocatedObject*>(elements); |
1389 return elements; | |
1390 } | 1390 } |
1391 | 1391 |
1392 | 1392 |
1393 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( | 1393 HInstruction* HGraphBuilder::AddExternalArrayElementAccess( |
1394 HValue* external_elements, | 1394 HValue* external_elements, |
1395 HValue* checked_key, | 1395 HValue* checked_key, |
1396 HValue* val, | 1396 HValue* val, |
1397 HValue* dependency, | 1397 HValue* dependency, |
1398 ElementsKind elements_kind, | 1398 ElementsKind elements_kind, |
1399 bool is_store) { | 1399 bool is_store) { |
(...skipping 22 matching lines...) Expand all Loading... |
1422 case FAST_HOLEY_ELEMENTS: | 1422 case FAST_HOLEY_ELEMENTS: |
1423 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1423 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1424 case DICTIONARY_ELEMENTS: | 1424 case DICTIONARY_ELEMENTS: |
1425 case NON_STRICT_ARGUMENTS_ELEMENTS: | 1425 case NON_STRICT_ARGUMENTS_ELEMENTS: |
1426 UNREACHABLE(); | 1426 UNREACHABLE(); |
1427 break; | 1427 break; |
1428 } | 1428 } |
1429 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); | 1429 return Add<HStoreKeyed>(external_elements, checked_key, val, elements_kind); |
1430 } else { | 1430 } else { |
1431 ASSERT(val == NULL); | 1431 ASSERT(val == NULL); |
1432 HLoadKeyed* load = Add<HLoadKeyed>(external_elements, checked_key, | 1432 HLoadKeyed* load = Add<HLoadKeyed>(external_elements, |
1433 dependency, elements_kind); | 1433 checked_key, |
| 1434 dependency, |
| 1435 elements_kind); |
1434 if (FLAG_opt_safe_uint32_operations && | 1436 if (FLAG_opt_safe_uint32_operations && |
1435 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 1437 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
1436 graph()->RecordUint32Instruction(load); | 1438 graph()->RecordUint32Instruction(load); |
1437 } | 1439 } |
1438 return load; | 1440 return load; |
1439 } | 1441 } |
1440 } | 1442 } |
1441 | 1443 |
1442 | 1444 |
1443 HInstruction* HGraphBuilder::AddFastElementAccess( | 1445 HInstruction* HGraphBuilder::AddFastElementAccess( |
(...skipping 21 matching lines...) Expand all Loading... |
1465 } | 1467 } |
1466 } | 1468 } |
1467 // It's an element load (!is_store). | 1469 // It's an element load (!is_store). |
1468 return Add<HLoadKeyed>( | 1470 return Add<HLoadKeyed>( |
1469 elements, checked_key, load_dependency, elements_kind, load_mode); | 1471 elements, checked_key, load_dependency, elements_kind, load_mode); |
1470 } | 1472 } |
1471 | 1473 |
1472 | 1474 |
1473 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1475 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, |
1474 HValue* typecheck) { | 1476 HValue* typecheck) { |
1475 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); | 1477 return Add<HLoadNamedField>(object, |
| 1478 HObjectAccess::ForElementsPointer(), |
| 1479 typecheck); |
1476 } | 1480 } |
1477 | 1481 |
1478 | 1482 |
1479 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1483 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
1480 return AddLoad(object, HObjectAccess::ForFixedArrayLength()); | 1484 return Add<HLoadNamedField>(object, |
| 1485 HObjectAccess::ForFixedArrayLength()); |
1481 } | 1486 } |
1482 | 1487 |
1483 | 1488 |
1484 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, | 1489 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
1485 HValue* old_capacity) { | 1490 HValue* half_old_capacity = Add<HShr>(old_capacity, graph_->GetConstant1()); |
1486 Zone* zone = this->zone(); | |
1487 HValue* half_old_capacity = | |
1488 AddInstruction(HShr::New(zone, context, old_capacity, | |
1489 graph_->GetConstant1())); | |
1490 | 1491 |
1491 HValue* new_capacity = AddInstruction( | 1492 HValue* new_capacity = Add<HAdd>(half_old_capacity, old_capacity); |
1492 HAdd::New(zone, context, half_old_capacity, old_capacity)); | |
1493 new_capacity->ClearFlag(HValue::kCanOverflow); | 1493 new_capacity->ClearFlag(HValue::kCanOverflow); |
1494 | 1494 |
1495 HValue* min_growth = Add<HConstant>(16); | 1495 HValue* min_growth = Add<HConstant>(16); |
1496 | 1496 |
1497 new_capacity = AddInstruction( | 1497 new_capacity = Add<HAdd>(new_capacity, min_growth); |
1498 HAdd::New(zone, context, new_capacity, min_growth)); | |
1499 new_capacity->ClearFlag(HValue::kCanOverflow); | 1498 new_capacity->ClearFlag(HValue::kCanOverflow); |
1500 | 1499 |
1501 return new_capacity; | 1500 return new_capacity; |
1502 } | 1501 } |
1503 | 1502 |
1504 | 1503 |
1505 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { | 1504 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
1506 Heap* heap = isolate()->heap(); | 1505 Heap* heap = isolate()->heap(); |
1507 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize | 1506 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
1508 : kPointerSize; | 1507 : kPointerSize; |
1509 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; | 1508 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; |
1510 max_size -= JSArray::kSize / element_size; | 1509 max_size -= JSArray::kSize / element_size; |
1511 HConstant* max_size_constant = Add<HConstant>(max_size); | 1510 HConstant* max_size_constant = Add<HConstant>(max_size); |
1512 Add<HBoundsCheck>(length, max_size_constant); | 1511 Add<HBoundsCheck>(length, max_size_constant); |
1513 } | 1512 } |
1514 | 1513 |
1515 | 1514 |
1516 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1515 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
1517 HValue* elements, | 1516 HValue* elements, |
1518 ElementsKind kind, | 1517 ElementsKind kind, |
1519 ElementsKind new_kind, | 1518 ElementsKind new_kind, |
1520 HValue* length, | 1519 HValue* length, |
1521 HValue* new_capacity) { | 1520 HValue* new_capacity) { |
1522 HValue* context = environment()->LookupContext(); | |
1523 | |
1524 BuildNewSpaceArrayCheck(new_capacity, new_kind); | 1521 BuildNewSpaceArrayCheck(new_capacity, new_kind); |
1525 | 1522 |
1526 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( | 1523 HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader( |
1527 context, new_kind, new_capacity); | 1524 new_kind, new_capacity); |
1528 | 1525 |
1529 BuildCopyElements(context, elements, kind, | 1526 BuildCopyElements(elements, kind, |
1530 new_elements, new_kind, | 1527 new_elements, new_kind, |
1531 length, new_capacity); | 1528 length, new_capacity); |
1532 | 1529 |
1533 AddStore(object, HObjectAccess::ForElementsPointer(), new_elements); | 1530 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1531 new_elements); |
1534 | 1532 |
1535 return new_elements; | 1533 return new_elements; |
1536 } | 1534 } |
1537 | 1535 |
1538 | 1536 |
1539 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1537 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements, |
1540 HValue* elements, | |
1541 ElementsKind elements_kind, | 1538 ElementsKind elements_kind, |
1542 HValue* from, | 1539 HValue* from, |
1543 HValue* to) { | 1540 HValue* to) { |
1544 // Fast elements kinds need to be initialized in case statements below cause | 1541 // Fast elements kinds need to be initialized in case statements below cause |
1545 // a garbage collection. | 1542 // a garbage collection. |
1546 Factory* factory = isolate()->factory(); | 1543 Factory* factory = isolate()->factory(); |
1547 | 1544 |
1548 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 1545 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
1549 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 1546 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
1550 ? Add<HConstant>(factory->the_hole_value()) | 1547 ? Add<HConstant>(factory->the_hole_value()) |
(...skipping 21 matching lines...) Expand all Loading... |
1572 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 1569 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
1573 elements_kind = FAST_HOLEY_ELEMENTS; | 1570 elements_kind = FAST_HOLEY_ELEMENTS; |
1574 } | 1571 } |
1575 | 1572 |
1576 if (unfold_loop) { | 1573 if (unfold_loop) { |
1577 for (int i = 0; i < initial_capacity; i++) { | 1574 for (int i = 0; i < initial_capacity; i++) { |
1578 HInstruction* key = Add<HConstant>(i); | 1575 HInstruction* key = Add<HConstant>(i); |
1579 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 1576 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
1580 } | 1577 } |
1581 } else { | 1578 } else { |
1582 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1579 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
1583 | 1580 |
1584 HValue* key = builder.BeginBody(from, to, Token::LT); | 1581 HValue* key = builder.BeginBody(from, to, Token::LT); |
1585 | 1582 |
1586 Add<HStoreKeyed>(elements, key, hole, elements_kind); | 1583 Add<HStoreKeyed>(elements, key, hole, elements_kind); |
1587 | 1584 |
1588 builder.EndBody(); | 1585 builder.EndBody(); |
1589 } | 1586 } |
1590 } | 1587 } |
1591 | 1588 |
1592 | 1589 |
1593 void HGraphBuilder::BuildCopyElements(HValue* context, | 1590 void HGraphBuilder::BuildCopyElements(HValue* from_elements, |
1594 HValue* from_elements, | |
1595 ElementsKind from_elements_kind, | 1591 ElementsKind from_elements_kind, |
1596 HValue* to_elements, | 1592 HValue* to_elements, |
1597 ElementsKind to_elements_kind, | 1593 ElementsKind to_elements_kind, |
1598 HValue* length, | 1594 HValue* length, |
1599 HValue* capacity) { | 1595 HValue* capacity) { |
1600 bool pre_fill_with_holes = | 1596 bool pre_fill_with_holes = |
1601 IsFastDoubleElementsKind(from_elements_kind) && | 1597 IsFastDoubleElementsKind(from_elements_kind) && |
1602 IsFastObjectElementsKind(to_elements_kind); | 1598 IsFastObjectElementsKind(to_elements_kind); |
1603 | 1599 |
1604 if (pre_fill_with_holes) { | 1600 if (pre_fill_with_holes) { |
1605 // If the copy might trigger a GC, make sure that the FixedArray is | 1601 // If the copy might trigger a GC, make sure that the FixedArray is |
1606 // pre-initialized with holes to make sure that it's always in a consistent | 1602 // pre-initialized with holes to make sure that it's always in a consistent |
1607 // state. | 1603 // state. |
1608 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1604 BuildFillElementsWithHole(to_elements, to_elements_kind, |
1609 graph()->GetConstant0(), capacity); | 1605 graph()->GetConstant0(), capacity); |
1610 } | 1606 } |
1611 | 1607 |
1612 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); | 1608 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
1613 | 1609 |
1614 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1610 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1615 | 1611 |
1616 HValue* element = Add<HLoadKeyed>(from_elements, key, | 1612 HValue* element = Add<HLoadKeyed>(from_elements, key, |
1617 static_cast<HValue*>(NULL), | 1613 static_cast<HValue*>(NULL), |
1618 from_elements_kind, | 1614 from_elements_kind, |
1619 ALLOW_RETURN_HOLE); | 1615 ALLOW_RETURN_HOLE); |
1620 | 1616 |
1621 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) | 1617 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) |
1622 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 1618 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
1623 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, | 1619 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, |
1624 element, holey_kind); | 1620 element, holey_kind); |
1625 // Allow NaN hole values to converted to their tagged counterparts. | 1621 // Allow NaN hole values to converted to their tagged counterparts. |
1626 if (IsFastHoleyElementsKind(to_elements_kind)) { | 1622 if (IsFastHoleyElementsKind(to_elements_kind)) { |
1627 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); | 1623 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); |
1628 } | 1624 } |
1629 | 1625 |
1630 builder.EndBody(); | 1626 builder.EndBody(); |
1631 | 1627 |
1632 if (!pre_fill_with_holes && length != capacity) { | 1628 if (!pre_fill_with_holes && length != capacity) { |
1633 // Fill unused capacity with the hole. | 1629 // Fill unused capacity with the hole. |
1634 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1630 BuildFillElementsWithHole(to_elements, to_elements_kind, |
1635 key, capacity); | 1631 key, capacity); |
1636 } | 1632 } |
1637 } | 1633 } |
1638 | 1634 |
1639 | 1635 |
1640 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 1636 HValue* HGraphBuilder::BuildCloneShallowArray(HValue* boilerplate, |
1641 HValue* boilerplate, | |
1642 HValue* allocation_site, | 1637 HValue* allocation_site, |
1643 AllocationSiteMode mode, | 1638 AllocationSiteMode mode, |
1644 ElementsKind kind, | 1639 ElementsKind kind, |
1645 int length) { | 1640 int length) { |
1646 NoObservableSideEffectsScope no_effects(this); | 1641 NoObservableSideEffectsScope no_effects(this); |
1647 | 1642 |
1648 // All sizes here are multiples of kPointerSize. | 1643 // All sizes here are multiples of kPointerSize. |
1649 int size = JSArray::kSize; | 1644 int size = JSArray::kSize; |
1650 if (mode == TRACK_ALLOCATION_SITE) { | 1645 if (mode == TRACK_ALLOCATION_SITE) { |
1651 size += AllocationMemento::kSize; | 1646 size += AllocationMemento::kSize; |
1652 } | 1647 } |
1653 int elems_offset = size; | 1648 int elems_offset = size; |
1654 if (length > 0) { | 1649 if (length > 0) { |
1655 size += IsFastDoubleElementsKind(kind) | 1650 size += IsFastDoubleElementsKind(kind) |
1656 ? FixedDoubleArray::SizeFor(length) | 1651 ? FixedDoubleArray::SizeFor(length) |
1657 : FixedArray::SizeFor(length); | 1652 : FixedArray::SizeFor(length); |
1658 } | 1653 } |
1659 | 1654 |
1660 // Allocate both the JS array and the elements array in one big | 1655 // Allocate both the JS array and the elements array in one big |
1661 // allocation. This avoids multiple limit checks. | 1656 // allocation. This avoids multiple limit checks. |
1662 HValue* size_in_bytes = Add<HConstant>(size); | 1657 HValue* size_in_bytes = Add<HConstant>(size); |
1663 HInstruction* object = Add<HAllocate>(context, | 1658 HInstruction* object = Add<HAllocate>(size_in_bytes, |
1664 size_in_bytes, | |
1665 HType::JSObject(), | 1659 HType::JSObject(), |
1666 false, | 1660 false, |
1667 kind); | 1661 kind); |
1668 | 1662 |
1669 // Copy the JS array part. | 1663 // Copy the JS array part. |
1670 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 1664 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
1671 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 1665 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
1672 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 1666 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
1673 AddStore(object, access, AddLoad(boilerplate, access)); | 1667 Add<HStoreNamedField>(object, access, |
| 1668 Add<HLoadNamedField>(boilerplate, access)); |
1674 } | 1669 } |
1675 } | 1670 } |
1676 | 1671 |
1677 // Create an allocation site info if requested. | 1672 // Create an allocation site info if requested. |
1678 if (mode == TRACK_ALLOCATION_SITE) { | 1673 if (mode == TRACK_ALLOCATION_SITE) { |
1679 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 1674 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
1680 } | 1675 } |
1681 | 1676 |
1682 if (length > 0) { | 1677 if (length > 0) { |
1683 // Get hold of the elements array of the boilerplate and setup the | 1678 // Get hold of the elements array of the boilerplate and setup the |
1684 // elements pointer in the resulting object. | 1679 // elements pointer in the resulting object. |
1685 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 1680 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
1686 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1681 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
1687 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); | 1682 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1683 object_elements); |
1688 | 1684 |
1689 // Copy the elements array header. | 1685 // Copy the elements array header. |
1690 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1686 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
1691 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1687 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
1692 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); | 1688 Add<HStoreNamedField>(object_elements, access, |
| 1689 Add<HLoadNamedField>(boilerplate_elements, access)); |
1693 } | 1690 } |
1694 | 1691 |
1695 // Copy the elements array contents. | 1692 // Copy the elements array contents. |
1696 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold | 1693 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold |
1697 // copying loops with constant length up to a given boundary and use this | 1694 // copying loops with constant length up to a given boundary and use this |
1698 // helper here instead. | 1695 // helper here instead. |
1699 for (int i = 0; i < length; i++) { | 1696 for (int i = 0; i < length; i++) { |
1700 HValue* key_constant = Add<HConstant>(i); | 1697 HValue* key_constant = Add<HConstant>(i); |
1701 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, | 1698 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant, |
1702 static_cast<HValue*>(NULL), kind); | 1699 static_cast<HValue*>(NULL), kind); |
1703 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | 1700 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
1704 } | 1701 } |
1705 } | 1702 } |
1706 | 1703 |
1707 return object; | 1704 return object; |
1708 } | 1705 } |
1709 | 1706 |
1710 | 1707 |
1711 HInstruction* HGraphBuilder::BuildUnaryMathOp( | 1708 HInstruction* HGraphBuilder::BuildUnaryMathOp( |
1712 HValue* input, Handle<Type> type, Token::Value operation) { | 1709 HValue* input, Handle<Type> type, Token::Value operation) { |
1713 // We only handle the numeric cases here | 1710 // We only handle the numeric cases here |
1714 type = handle( | 1711 type = handle( |
1715 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); | 1712 Type::Intersect(type, handle(Type::Number(), isolate())), isolate()); |
1716 | 1713 |
1717 switch (operation) { | 1714 switch (operation) { |
1718 default: | 1715 default: |
1719 UNREACHABLE(); | 1716 UNREACHABLE(); |
1720 case Token::SUB: { | 1717 case Token::SUB: { |
1721 HInstruction* instr = | 1718 HInstruction* instr = |
1722 HMul::New(zone(), environment()->LookupContext(), | 1719 NewUncasted<HMul>(input, graph()->GetConstantMinus1()); |
1723 input, graph()->GetConstantMinus1()); | |
1724 Representation rep = Representation::FromType(type); | 1720 Representation rep = Representation::FromType(type); |
1725 if (type->Is(Type::None())) { | 1721 if (type->Is(Type::None())) { |
1726 Add<HDeoptimize>(Deoptimizer::SOFT); | 1722 Add<HDeoptimize>(Deoptimizer::SOFT); |
1727 } | 1723 } |
1728 if (instr->IsBinaryOperation()) { | 1724 if (instr->IsBinaryOperation()) { |
1729 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 1725 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
1730 binop->set_observed_input_representation(1, rep); | 1726 binop->set_observed_input_representation(1, rep); |
1731 binop->set_observed_input_representation(2, rep); | 1727 binop->set_observed_input_representation(2, rep); |
1732 } | 1728 } |
1733 return instr; | 1729 return instr; |
1734 } | 1730 } |
1735 case Token::BIT_NOT: | 1731 case Token::BIT_NOT: |
1736 if (type->Is(Type::None())) { | 1732 if (type->Is(Type::None())) { |
1737 Add<HDeoptimize>(Deoptimizer::SOFT); | 1733 Add<HDeoptimize>(Deoptimizer::SOFT); |
1738 } | 1734 } |
1739 return new(zone()) HBitNot(input); | 1735 return New<HBitNot>(input); |
1740 } | 1736 } |
1741 } | 1737 } |
1742 | 1738 |
1743 | 1739 |
1744 void HGraphBuilder::BuildCompareNil( | 1740 void HGraphBuilder::BuildCompareNil( |
1745 HValue* value, | 1741 HValue* value, |
1746 Handle<Type> type, | 1742 Handle<Type> type, |
1747 int position, | 1743 int position, |
1748 HIfContinuation* continuation) { | 1744 HIfContinuation* continuation) { |
1749 IfBuilder if_nil(this, position); | 1745 IfBuilder if_nil(this, position); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1784 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 1780 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
1785 int previous_object_size, | 1781 int previous_object_size, |
1786 HValue* alloc_site) { | 1782 HValue* alloc_site) { |
1787 ASSERT(alloc_site != NULL); | 1783 ASSERT(alloc_site != NULL); |
1788 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 1784 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( |
1789 previous_object, previous_object_size); | 1785 previous_object, previous_object_size); |
1790 Handle<Map> alloc_memento_map( | 1786 Handle<Map> alloc_memento_map( |
1791 isolate()->heap()->allocation_memento_map()); | 1787 isolate()->heap()->allocation_memento_map()); |
1792 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 1788 AddStoreMapConstant(alloc_memento, alloc_memento_map); |
1793 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 1789 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
1794 AddStore(alloc_memento, access, alloc_site); | 1790 Add<HStoreNamedField>(alloc_memento, access, alloc_site); |
1795 return alloc_memento; | 1791 return alloc_memento; |
1796 } | 1792 } |
1797 | 1793 |
1798 | 1794 |
1799 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { | 1795 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
1800 // Get the global context, then the native context | 1796 // Get the global context, then the native context |
1801 HInstruction* global_object = Add<HGlobalObject>(context); | 1797 HInstruction* global_object = Add<HGlobalObject>(); |
1802 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1798 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
1803 GlobalObject::kNativeContextOffset); | 1799 GlobalObject::kNativeContextOffset); |
1804 return AddLoad(global_object, access); | 1800 return Add<HLoadNamedField>(global_object, access); |
1805 } | 1801 } |
1806 | 1802 |
1807 | 1803 |
1808 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { | 1804 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
1809 HInstruction* native_context = BuildGetNativeContext(context); | 1805 HInstruction* native_context = BuildGetNativeContext(); |
1810 HInstruction* index = | 1806 HInstruction* index = |
1811 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | 1807 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
1812 return Add<HLoadKeyed>( | 1808 return Add<HLoadKeyed>( |
1813 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1809 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1814 } | 1810 } |
1815 | 1811 |
1816 | 1812 |
1817 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 1813 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
1818 ElementsKind kind, | 1814 ElementsKind kind, |
1819 HValue* allocation_site_payload, | 1815 HValue* allocation_site_payload, |
(...skipping 13 matching lines...) Expand all Loading... |
1833 ElementsKind kind, | 1829 ElementsKind kind, |
1834 HValue* constructor_function) : | 1830 HValue* constructor_function) : |
1835 builder_(builder), | 1831 builder_(builder), |
1836 kind_(kind), | 1832 kind_(kind), |
1837 mode_(DONT_TRACK_ALLOCATION_SITE), | 1833 mode_(DONT_TRACK_ALLOCATION_SITE), |
1838 allocation_site_payload_(NULL), | 1834 allocation_site_payload_(NULL), |
1839 constructor_function_(constructor_function) { | 1835 constructor_function_(constructor_function) { |
1840 } | 1836 } |
1841 | 1837 |
1842 | 1838 |
1843 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { | 1839 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
1844 if (kind_ == GetInitialFastElementsKind()) { | 1840 if (kind_ == GetInitialFastElementsKind()) { |
1845 // No need for a context lookup if the kind_ matches the initial | 1841 // No need for a context lookup if the kind_ matches the initial |
1846 // map, because we can just load the map in that case. | 1842 // map, because we can just load the map in that case. |
1847 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1843 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1848 return builder()->AddInstruction( | 1844 return builder()->AddInstruction( |
1849 builder()->BuildLoadNamedField(constructor_function_, access)); | 1845 builder()->BuildLoadNamedField(constructor_function_, access)); |
1850 } | 1846 } |
1851 | 1847 |
1852 HInstruction* native_context = builder()->BuildGetNativeContext(context); | 1848 HInstruction* native_context = builder()->BuildGetNativeContext(); |
1853 HInstruction* index = builder()->Add<HConstant>( | 1849 HInstruction* index = builder()->Add<HConstant>( |
1854 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1850 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
1855 | 1851 |
1856 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1852 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
1857 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1853 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1858 | 1854 |
1859 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1855 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
1860 | 1856 |
1861 return builder()->Add<HLoadKeyed>( | 1857 return builder()->Add<HLoadKeyed>( |
1862 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1858 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
1863 } | 1859 } |
1864 | 1860 |
1865 | 1861 |
1866 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1862 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
1867 // Find the map near the constructor function | 1863 // Find the map near the constructor function |
1868 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1864 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
1869 return builder()->AddInstruction( | 1865 return builder()->AddInstruction( |
1870 builder()->BuildLoadNamedField(constructor_function_, access)); | 1866 builder()->BuildLoadNamedField(constructor_function_, access)); |
1871 } | 1867 } |
1872 | 1868 |
1873 | 1869 |
1874 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1870 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
1875 HValue* length_node) { | 1871 HValue* length_node) { |
1876 HValue* context = builder()->environment()->LookupContext(); | |
1877 ASSERT(length_node != NULL); | 1872 ASSERT(length_node != NULL); |
1878 | 1873 |
1879 int base_size = JSArray::kSize; | 1874 int base_size = JSArray::kSize; |
1880 if (mode_ == TRACK_ALLOCATION_SITE) { | 1875 if (mode_ == TRACK_ALLOCATION_SITE) { |
1881 base_size += AllocationMemento::kSize; | 1876 base_size += AllocationMemento::kSize; |
1882 } | 1877 } |
1883 | 1878 |
1884 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | 1879 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
1885 base_size += FixedArray::kHeaderSize; | 1880 base_size += FixedArray::kHeaderSize; |
1886 | 1881 |
1887 HInstruction* elements_size_value = | 1882 HInstruction* elements_size_value = |
1888 builder()->Add<HConstant>(elements_size()); | 1883 builder()->Add<HConstant>(elements_size()); |
1889 HInstruction* mul = HMul::New(zone(), context, length_node, | 1884 HInstruction* mul = builder()->Add<HMul>(length_node, elements_size_value); |
1890 elements_size_value); | |
1891 mul->ClearFlag(HValue::kCanOverflow); | 1885 mul->ClearFlag(HValue::kCanOverflow); |
1892 builder()->AddInstruction(mul); | |
1893 | 1886 |
1894 HInstruction* base = builder()->Add<HConstant>(base_size); | 1887 HInstruction* base = builder()->Add<HConstant>(base_size); |
1895 HInstruction* total_size = HAdd::New(zone(), context, base, mul); | 1888 HInstruction* total_size = builder()->Add<HAdd>(base, mul); |
1896 total_size->ClearFlag(HValue::kCanOverflow); | 1889 total_size->ClearFlag(HValue::kCanOverflow); |
1897 builder()->AddInstruction(total_size); | |
1898 return total_size; | 1890 return total_size; |
1899 } | 1891 } |
1900 | 1892 |
1901 | 1893 |
1902 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { | 1894 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { |
1903 int base_size = JSArray::kSize; | 1895 int base_size = JSArray::kSize; |
1904 if (mode_ == TRACK_ALLOCATION_SITE) { | 1896 if (mode_ == TRACK_ALLOCATION_SITE) { |
1905 base_size += AllocationMemento::kSize; | 1897 base_size += AllocationMemento::kSize; |
1906 } | 1898 } |
1907 | 1899 |
(...skipping 20 matching lines...) Expand all Loading... |
1928 bool fill_with_hole) { | 1920 bool fill_with_hole) { |
1929 HValue* size_in_bytes = EstablishAllocationSize(capacity); | 1921 HValue* size_in_bytes = EstablishAllocationSize(capacity); |
1930 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); | 1922 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); |
1931 } | 1923 } |
1932 | 1924 |
1933 | 1925 |
1934 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, | 1926 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, |
1935 HValue* capacity, | 1927 HValue* capacity, |
1936 HValue* length_field, | 1928 HValue* length_field, |
1937 bool fill_with_hole) { | 1929 bool fill_with_hole) { |
1938 HValue* context = builder()->environment()->LookupContext(); | |
1939 | |
1940 // These HForceRepresentations are because we store these as fields in the | 1930 // These HForceRepresentations are because we store these as fields in the |
1941 // objects we construct, and an int32-to-smi HChange could deopt. Accept | 1931 // objects we construct, and an int32-to-smi HChange could deopt. Accept |
1942 // the deopt possibility now, before allocation occurs. | 1932 // the deopt possibility now, before allocation occurs. |
1943 capacity = builder()->Add<HForceRepresentation>(capacity, | 1933 capacity = builder()->Add<HForceRepresentation>(capacity, |
1944 Representation::Smi()); | 1934 Representation::Smi()); |
1945 length_field = builder()->Add<HForceRepresentation>(length_field, | 1935 length_field = builder()->Add<HForceRepresentation>(length_field, |
1946 Representation::Smi()); | 1936 Representation::Smi()); |
1947 | |
1948 // Allocate (dealing with failure appropriately) | 1937 // Allocate (dealing with failure appropriately) |
1949 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes, | 1938 HAllocate* new_object = builder()->Add<HAllocate>(size_in_bytes, |
1950 HType::JSArray(), false, kind_); | 1939 HType::JSArray(), false, kind_); |
1951 | 1940 |
1952 // Fill in the fields: map, properties, length | 1941 // Fill in the fields: map, properties, length |
1953 HValue* map; | 1942 HValue* map; |
1954 if (allocation_site_payload_ == NULL) { | 1943 if (allocation_site_payload_ == NULL) { |
1955 map = EmitInternalMapCode(); | 1944 map = EmitInternalMapCode(); |
1956 } else { | 1945 } else { |
1957 map = EmitMapCode(context); | 1946 map = EmitMapCode(); |
1958 } | 1947 } |
1959 elements_location_ = builder()->BuildJSArrayHeader(new_object, | 1948 elements_location_ = builder()->BuildJSArrayHeader(new_object, |
1960 map, | 1949 map, |
1961 mode_, | 1950 mode_, |
1962 kind_, | 1951 kind_, |
1963 allocation_site_payload_, | 1952 allocation_site_payload_, |
1964 length_field); | 1953 length_field); |
1965 | 1954 |
1966 // Initialize the elements | 1955 // Initialize the elements |
1967 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); | 1956 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); |
1968 | 1957 |
1969 if (fill_with_hole) { | 1958 if (fill_with_hole) { |
1970 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, | 1959 builder()->BuildFillElementsWithHole(elements_location_, kind_, |
1971 graph()->GetConstant0(), capacity); | 1960 graph()->GetConstant0(), capacity); |
1972 } | 1961 } |
1973 | 1962 |
1974 return new_object; | 1963 return new_object; |
1975 } | 1964 } |
1976 | 1965 |
1977 | 1966 |
1978 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, | |
1979 HObjectAccess access, | |
1980 HValue *val) { | |
1981 return Add<HStoreNamedField>(object, access, val); | |
1982 } | |
1983 | |
1984 | |
1985 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, | |
1986 HObjectAccess access, | |
1987 HValue *typecheck) { | |
1988 return Add<HLoadNamedField>(object, access, typecheck); | |
1989 } | |
1990 | |
1991 | |
1992 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, | 1967 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, |
1993 Handle<Map> map) { | 1968 Handle<Map> map) { |
1994 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), | 1969 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(), |
1995 Add<HConstant>(map)); | 1970 Add<HConstant>(map)); |
1996 } | 1971 } |
1997 | 1972 |
1998 | 1973 |
1999 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin, | 1974 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) { |
2000 HValue* context) { | 1975 HGlobalObject* global_object = Add<HGlobalObject>(); |
2001 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
2002 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 1976 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
2003 GlobalObject::kBuiltinsOffset); | 1977 GlobalObject::kBuiltinsOffset); |
2004 HValue* builtins = AddLoad(global_object, access); | 1978 HValue* builtins = Add<HLoadNamedField>(global_object, access); |
2005 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( | 1979 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset( |
2006 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); | 1980 JSBuiltinsObject::OffsetOfFunctionWithId(builtin)); |
2007 return AddLoad(builtins, function_access); | 1981 return Add<HLoadNamedField>(builtins, function_access); |
2008 } | 1982 } |
2009 | 1983 |
2010 | 1984 |
2011 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 1985 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
2012 : HGraphBuilder(info), | 1986 : HGraphBuilder(info), |
2013 function_state_(NULL), | 1987 function_state_(NULL), |
2014 initial_function_state_(this, info, NORMAL_RETURN), | 1988 initial_function_state_(this, info, NORMAL_RETURN), |
2015 ast_context_(NULL), | 1989 ast_context_(NULL), |
2016 break_scope_(NULL), | 1990 break_scope_(NULL), |
2017 inlined_count_(0), | 1991 inlined_count_(0), |
(...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2889 set_current_block(body_entry); | 2863 set_current_block(body_entry); |
2890 | 2864 |
2891 // Handle implicit declaration of the function name in named function | 2865 // Handle implicit declaration of the function name in named function |
2892 // expressions before other declarations. | 2866 // expressions before other declarations. |
2893 if (scope->is_function_scope() && scope->function() != NULL) { | 2867 if (scope->is_function_scope() && scope->function() != NULL) { |
2894 VisitVariableDeclaration(scope->function()); | 2868 VisitVariableDeclaration(scope->function()); |
2895 } | 2869 } |
2896 VisitDeclarations(scope->declarations()); | 2870 VisitDeclarations(scope->declarations()); |
2897 Add<HSimulate>(BailoutId::Declarations()); | 2871 Add<HSimulate>(BailoutId::Declarations()); |
2898 | 2872 |
2899 HValue* context = environment()->LookupContext(); | 2873 HValue* context = environment()->context(); |
2900 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | 2874 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); |
2901 | 2875 |
2902 VisitStatements(current_info()->function()->body()); | 2876 VisitStatements(current_info()->function()->body()); |
2903 if (HasStackOverflow()) return false; | 2877 if (HasStackOverflow()) return false; |
2904 | 2878 |
2905 if (current_block() != NULL) { | 2879 if (current_block() != NULL) { |
2906 Add<HReturn>(graph()->GetConstantUndefined()); | 2880 Add<HReturn>(graph()->GetConstantUndefined()); |
2907 set_current_block(NULL); | 2881 set_current_block(NULL); |
2908 } | 2882 } |
2909 | 2883 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3100 } | 3074 } |
3101 | 3075 |
3102 while (!arguments.is_empty()) { | 3076 while (!arguments.is_empty()) { |
3103 Add<HPushArgument>(arguments.RemoveLast()); | 3077 Add<HPushArgument>(arguments.RemoveLast()); |
3104 } | 3078 } |
3105 return call; | 3079 return call; |
3106 } | 3080 } |
3107 | 3081 |
3108 | 3082 |
3109 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3083 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
3110 HConstant* undefined_constant = Add<HConstant>( | 3084 // First special is HContext. |
3111 isolate()->factory()->undefined_value()); | 3085 HInstruction* context = Add<HContext>(); |
| 3086 environment()->BindContext(context); |
| 3087 |
| 3088 HConstant* undefined_constant = HConstant::cast(Add<HConstant>( |
| 3089 isolate()->factory()->undefined_value())); |
3112 graph()->set_undefined_constant(undefined_constant); | 3090 graph()->set_undefined_constant(undefined_constant); |
3113 | 3091 |
3114 // Create an arguments object containing the initial parameters. Set the | 3092 // Create an arguments object containing the initial parameters. Set the |
3115 // initial values of parameters including "this" having parameter index 0. | 3093 // initial values of parameters including "this" having parameter index 0. |
3116 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 3094 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
3117 HArgumentsObject* arguments_object = | 3095 HArgumentsObject* arguments_object = |
3118 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); | 3096 New<HArgumentsObject>(environment()->parameter_count()); |
3119 for (int i = 0; i < environment()->parameter_count(); ++i) { | 3097 for (int i = 0; i < environment()->parameter_count(); ++i) { |
3120 HInstruction* parameter = Add<HParameter>(i); | 3098 HInstruction* parameter = Add<HParameter>(i); |
3121 arguments_object->AddArgument(parameter, zone()); | 3099 arguments_object->AddArgument(parameter, zone()); |
3122 environment()->Bind(i, parameter); | 3100 environment()->Bind(i, parameter); |
3123 } | 3101 } |
3124 AddInstruction(arguments_object); | 3102 AddInstruction(arguments_object); |
3125 graph()->SetArgumentsObject(arguments_object); | 3103 graph()->SetArgumentsObject(arguments_object); |
3126 | 3104 |
3127 // First special is HContext. | |
3128 HInstruction* context = Add<HContext>(); | |
3129 environment()->BindContext(context); | |
3130 | |
3131 // Initialize specials and locals to undefined. | 3105 // Initialize specials and locals to undefined. |
3132 for (int i = environment()->parameter_count() + 1; | 3106 for (int i = environment()->parameter_count() + 1; |
3133 i < environment()->length(); | 3107 i < environment()->length(); |
3134 ++i) { | 3108 ++i) { |
3135 environment()->Bind(i, undefined_constant); | 3109 environment()->Bind(i, undefined_constant); |
3136 } | 3110 } |
3137 | 3111 |
3138 // Handle the arguments and arguments shadow variables specially (they do | 3112 // Handle the arguments and arguments shadow variables specially (they do |
3139 // not have declarations). | 3113 // not have declarations). |
3140 if (scope->arguments() != NULL) { | 3114 if (scope->arguments() != NULL) { |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3388 int clause_count = clauses->length(); | 3362 int clause_count = clauses->length(); |
3389 if (clause_count > kCaseClauseLimit) { | 3363 if (clause_count > kCaseClauseLimit) { |
3390 return Bailout("SwitchStatement: too many clauses"); | 3364 return Bailout("SwitchStatement: too many clauses"); |
3391 } | 3365 } |
3392 | 3366 |
3393 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3367 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
3394 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3368 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
3395 return Bailout("SwitchStatement: mixed or non-literal switch labels"); | 3369 return Bailout("SwitchStatement: mixed or non-literal switch labels"); |
3396 } | 3370 } |
3397 | 3371 |
3398 HValue* context = environment()->LookupContext(); | 3372 HValue* context = environment()->context(); |
3399 | 3373 |
3400 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3374 CHECK_ALIVE(VisitForValue(stmt->tag())); |
3401 Add<HSimulate>(stmt->EntryId()); | 3375 Add<HSimulate>(stmt->EntryId()); |
3402 HValue* tag_value = Pop(); | 3376 HValue* tag_value = Pop(); |
3403 HBasicBlock* first_test_block = current_block(); | 3377 HBasicBlock* first_test_block = current_block(); |
3404 | 3378 |
3405 HUnaryControlInstruction* string_check = NULL; | 3379 HUnaryControlInstruction* string_check = NULL; |
3406 HBasicBlock* not_string_block = NULL; | 3380 HBasicBlock* not_string_block = NULL; |
3407 | 3381 |
3408 // Test switch's tag value if all clauses are string literals | 3382 // Test switch's tag value if all clauses are string literals |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3536 set_current_block(break_block); | 3510 set_current_block(break_block); |
3537 } | 3511 } |
3538 } | 3512 } |
3539 | 3513 |
3540 | 3514 |
3541 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3515 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
3542 HBasicBlock* loop_entry, | 3516 HBasicBlock* loop_entry, |
3543 BreakAndContinueInfo* break_info) { | 3517 BreakAndContinueInfo* break_info) { |
3544 BreakAndContinueScope push(break_info, this); | 3518 BreakAndContinueScope push(break_info, this); |
3545 Add<HSimulate>(stmt->StackCheckId()); | 3519 Add<HSimulate>(stmt->StackCheckId()); |
3546 HValue* context = environment()->LookupContext(); | 3520 HValue* context = environment()->context(); |
3547 HStackCheck* stack_check = Add<HStackCheck>( | 3521 HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>( |
3548 context, HStackCheck::kBackwardsBranch); | 3522 context, HStackCheck::kBackwardsBranch)); |
3549 ASSERT(loop_entry->IsLoopHeader()); | 3523 ASSERT(loop_entry->IsLoopHeader()); |
3550 loop_entry->loop_information()->set_stack_check(stack_check); | 3524 loop_entry->loop_information()->set_stack_check(stack_check); |
3551 CHECK_BAILOUT(Visit(stmt->body())); | 3525 CHECK_BAILOUT(Visit(stmt->body())); |
3552 } | 3526 } |
3553 | 3527 |
3554 | 3528 |
3555 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3529 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
3556 ASSERT(!HasStackOverflow()); | 3530 ASSERT(!HasStackOverflow()); |
3557 ASSERT(current_block() != NULL); | 3531 ASSERT(current_block() != NULL); |
3558 ASSERT(current_block()->HasPredecessor()); | 3532 ASSERT(current_block()->HasPredecessor()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3694 if (!stmt->each()->IsVariableProxy() || | 3668 if (!stmt->each()->IsVariableProxy() || |
3695 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { | 3669 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { |
3696 return Bailout("ForInStatement with non-local each variable"); | 3670 return Bailout("ForInStatement with non-local each variable"); |
3697 } | 3671 } |
3698 | 3672 |
3699 Variable* each_var = stmt->each()->AsVariableProxy()->var(); | 3673 Variable* each_var = stmt->each()->AsVariableProxy()->var(); |
3700 | 3674 |
3701 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 3675 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
3702 HValue* enumerable = Top(); // Leave enumerable at the top. | 3676 HValue* enumerable = Top(); // Leave enumerable at the top. |
3703 | 3677 |
3704 HInstruction* map = Add<HForInPrepareMap>( | 3678 HInstruction* map = Add<HForInPrepareMap>(enumerable); |
3705 environment()->LookupContext(), enumerable); | |
3706 Add<HSimulate>(stmt->PrepareId()); | 3679 Add<HSimulate>(stmt->PrepareId()); |
3707 | 3680 |
3708 HInstruction* array = Add<HForInCacheArray>( | 3681 HInstruction* array = Add<HForInCacheArray>( |
3709 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); | 3682 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex); |
3710 | 3683 |
3711 HInstruction* enum_length = Add<HMapEnumLength>(map); | 3684 HInstruction* enum_length = Add<HMapEnumLength>(map); |
3712 | 3685 |
3713 HInstruction* start_index = Add<HConstant>(0); | 3686 HInstruction* start_index = Add<HConstant>(0); |
3714 | 3687 |
3715 Push(map); | 3688 Push(map); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3761 BreakAndContinueInfo break_info(stmt, 5); | 3734 BreakAndContinueInfo break_info(stmt, 5); |
3762 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 3735 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
3763 | 3736 |
3764 HBasicBlock* body_exit = | 3737 HBasicBlock* body_exit = |
3765 JoinContinue(stmt, current_block(), break_info.continue_block()); | 3738 JoinContinue(stmt, current_block(), break_info.continue_block()); |
3766 | 3739 |
3767 if (body_exit != NULL) { | 3740 if (body_exit != NULL) { |
3768 set_current_block(body_exit); | 3741 set_current_block(body_exit); |
3769 | 3742 |
3770 HValue* current_index = Pop(); | 3743 HValue* current_index = Pop(); |
3771 HInstruction* new_index = HAdd::New(zone(), | 3744 HInstruction* new_index = New<HAdd>(current_index, |
3772 environment()->LookupContext(), | |
3773 current_index, | |
3774 graph()->GetConstant1()); | 3745 graph()->GetConstant1()); |
3775 PushAndAdd(new_index); | 3746 PushAndAdd(new_index); |
3776 body_exit = current_block(); | 3747 body_exit = current_block(); |
3777 } | 3748 } |
3778 | 3749 |
3779 HBasicBlock* loop_exit = CreateLoop(stmt, | 3750 HBasicBlock* loop_exit = CreateLoop(stmt, |
3780 loop_entry, | 3751 loop_entry, |
3781 body_exit, | 3752 body_exit, |
3782 loop_successor, | 3753 loop_successor, |
3783 break_info.break_block()); | 3754 break_info.break_block()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3842 ASSERT(!HasStackOverflow()); | 3813 ASSERT(!HasStackOverflow()); |
3843 ASSERT(current_block() != NULL); | 3814 ASSERT(current_block() != NULL); |
3844 ASSERT(current_block()->HasPredecessor()); | 3815 ASSERT(current_block()->HasPredecessor()); |
3845 Handle<SharedFunctionInfo> shared_info = | 3816 Handle<SharedFunctionInfo> shared_info = |
3846 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); | 3817 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); |
3847 if (shared_info.is_null()) { | 3818 if (shared_info.is_null()) { |
3848 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); | 3819 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
3849 } | 3820 } |
3850 // We also have a stack overflow if the recursive compilation did. | 3821 // We also have a stack overflow if the recursive compilation did. |
3851 if (HasStackOverflow()) return; | 3822 if (HasStackOverflow()) return; |
3852 HValue* context = environment()->LookupContext(); | 3823 HValue* context = environment()->context(); |
3853 HFunctionLiteral* instr = | 3824 HFunctionLiteral* instr = |
3854 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 3825 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); |
3855 return ast_context()->ReturnInstruction(instr, expr->id()); | 3826 return ast_context()->ReturnInstruction(instr, expr->id()); |
3856 } | 3827 } |
3857 | 3828 |
3858 | 3829 |
3859 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 3830 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
3860 SharedFunctionInfoLiteral* expr) { | 3831 SharedFunctionInfoLiteral* expr) { |
3861 ASSERT(!HasStackOverflow()); | 3832 ASSERT(!HasStackOverflow()); |
3862 ASSERT(current_block() != NULL); | 3833 ASSERT(current_block() != NULL); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3916 lookup->holder() != *global) { | 3887 lookup->holder() != *global) { |
3917 return kUseGeneric; | 3888 return kUseGeneric; |
3918 } | 3889 } |
3919 | 3890 |
3920 return kUseCell; | 3891 return kUseCell; |
3921 } | 3892 } |
3922 | 3893 |
3923 | 3894 |
3924 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 3895 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
3925 ASSERT(var->IsContextSlot()); | 3896 ASSERT(var->IsContextSlot()); |
3926 HValue* context = environment()->LookupContext(); | 3897 HValue* context = environment()->context(); |
3927 int length = current_info()->scope()->ContextChainLength(var->scope()); | 3898 int length = current_info()->scope()->ContextChainLength(var->scope()); |
3928 while (length-- > 0) { | 3899 while (length-- > 0) { |
3929 context = Add<HOuterContext>(context); | 3900 context = Add<HOuterContext>(context); |
3930 } | 3901 } |
3931 return context; | 3902 return context; |
3932 } | 3903 } |
3933 | 3904 |
3934 | 3905 |
3935 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 3906 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
3936 ASSERT(!HasStackOverflow()); | 3907 ASSERT(!HasStackOverflow()); |
3937 ASSERT(current_block() != NULL); | 3908 ASSERT(current_block() != NULL); |
3938 ASSERT(current_block()->HasPredecessor()); | 3909 ASSERT(current_block()->HasPredecessor()); |
3939 Variable* variable = expr->var(); | 3910 Variable* variable = expr->var(); |
3940 switch (variable->location()) { | 3911 switch (variable->location()) { |
3941 case Variable::UNALLOCATED: { | 3912 case Variable::UNALLOCATED: { |
3942 if (IsLexicalVariableMode(variable->mode())) { | 3913 if (IsLexicalVariableMode(variable->mode())) { |
3943 // TODO(rossberg): should this be an ASSERT? | 3914 // TODO(rossberg): should this be an ASSERT? |
3944 return Bailout("reference to global lexical variable"); | 3915 return Bailout("reference to global lexical variable"); |
3945 } | 3916 } |
3946 // Handle known global constants like 'undefined' specially to avoid a | 3917 // Handle known global constants like 'undefined' specially to avoid a |
3947 // load from a global cell for them. | 3918 // load from a global cell for them. |
3948 Handle<Object> constant_value = | 3919 Handle<Object> constant_value = |
3949 isolate()->factory()->GlobalConstantFor(variable->name()); | 3920 isolate()->factory()->GlobalConstantFor(variable->name()); |
3950 if (!constant_value.is_null()) { | 3921 if (!constant_value.is_null()) { |
3951 HConstant* instr = new(zone()) HConstant(constant_value); | 3922 HConstant* instr = New<HConstant>(constant_value); |
3952 return ast_context()->ReturnInstruction(instr, expr->id()); | 3923 return ast_context()->ReturnInstruction(instr, expr->id()); |
3953 } | 3924 } |
3954 | 3925 |
3955 LookupResult lookup(isolate()); | 3926 LookupResult lookup(isolate()); |
3956 GlobalPropertyAccess type = | 3927 GlobalPropertyAccess type = |
3957 LookupGlobalProperty(variable, &lookup, false); | 3928 LookupGlobalProperty(variable, &lookup, false); |
3958 | 3929 |
3959 if (type == kUseCell && | 3930 if (type == kUseCell && |
3960 current_info()->global_object()->IsAccessCheckNeeded()) { | 3931 current_info()->global_object()->IsAccessCheckNeeded()) { |
3961 type = kUseGeneric; | 3932 type = kUseGeneric; |
3962 } | 3933 } |
3963 | 3934 |
3964 if (type == kUseCell) { | 3935 if (type == kUseCell) { |
3965 Handle<GlobalObject> global(current_info()->global_object()); | 3936 Handle<GlobalObject> global(current_info()->global_object()); |
3966 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 3937 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
3967 if (cell->type()->IsConstant()) { | 3938 if (cell->type()->IsConstant()) { |
3968 cell->AddDependentCompilationInfo(top_info()); | 3939 cell->AddDependentCompilationInfo(top_info()); |
3969 Handle<Object> constant_object = cell->type()->AsConstant(); | 3940 Handle<Object> constant_object = cell->type()->AsConstant(); |
3970 if (constant_object->IsConsString()) { | 3941 if (constant_object->IsConsString()) { |
3971 constant_object = | 3942 constant_object = |
3972 FlattenGetString(Handle<String>::cast(constant_object)); | 3943 FlattenGetString(Handle<String>::cast(constant_object)); |
3973 } | 3944 } |
3974 HConstant* constant = new(zone()) HConstant(constant_object); | 3945 HConstant* constant = New<HConstant>(constant_object); |
3975 return ast_context()->ReturnInstruction(constant, expr->id()); | 3946 return ast_context()->ReturnInstruction(constant, expr->id()); |
3976 } else { | 3947 } else { |
3977 HLoadGlobalCell* instr = | 3948 HLoadGlobalCell* instr = |
3978 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); | 3949 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); |
3979 return ast_context()->ReturnInstruction(instr, expr->id()); | 3950 return ast_context()->ReturnInstruction(instr, expr->id()); |
3980 } | 3951 } |
3981 } else { | 3952 } else { |
3982 HValue* context = environment()->LookupContext(); | 3953 HValue* context = environment()->context(); |
3983 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 3954 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
3984 AddInstruction(global_object); | 3955 AddInstruction(global_object); |
3985 HLoadGlobalGeneric* instr = | 3956 HLoadGlobalGeneric* instr = |
3986 new(zone()) HLoadGlobalGeneric(context, | 3957 new(zone()) HLoadGlobalGeneric(context, |
3987 global_object, | 3958 global_object, |
3988 variable->name(), | 3959 variable->name(), |
3989 ast_context()->is_for_typeof()); | 3960 ast_context()->is_for_typeof()); |
3990 instr->set_position(expr->position()); | 3961 instr->set_position(expr->position()); |
3991 return ast_context()->ReturnInstruction(instr, expr->id()); | 3962 return ast_context()->ReturnInstruction(instr, expr->id()); |
3992 } | 3963 } |
(...skipping 19 matching lines...) Expand all Loading... |
4012 case Variable::LOOKUP: | 3983 case Variable::LOOKUP: |
4013 return Bailout("reference to a variable which requires dynamic lookup"); | 3984 return Bailout("reference to a variable which requires dynamic lookup"); |
4014 } | 3985 } |
4015 } | 3986 } |
4016 | 3987 |
4017 | 3988 |
4018 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 3989 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
4019 ASSERT(!HasStackOverflow()); | 3990 ASSERT(!HasStackOverflow()); |
4020 ASSERT(current_block() != NULL); | 3991 ASSERT(current_block() != NULL); |
4021 ASSERT(current_block()->HasPredecessor()); | 3992 ASSERT(current_block()->HasPredecessor()); |
4022 HConstant* instr = new(zone()) HConstant(expr->value()); | 3993 HConstant* instr = New<HConstant>(expr->value()); |
4023 return ast_context()->ReturnInstruction(instr, expr->id()); | 3994 return ast_context()->ReturnInstruction(instr, expr->id()); |
4024 } | 3995 } |
4025 | 3996 |
4026 | 3997 |
4027 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 3998 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
4028 ASSERT(!HasStackOverflow()); | 3999 ASSERT(!HasStackOverflow()); |
4029 ASSERT(current_block() != NULL); | 4000 ASSERT(current_block() != NULL); |
4030 ASSERT(current_block()->HasPredecessor()); | 4001 ASSERT(current_block()->HasPredecessor()); |
4031 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4002 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4032 Handle<FixedArray> literals(closure->literals()); | 4003 Handle<FixedArray> literals(closure->literals()); |
4033 HValue* context = environment()->LookupContext(); | 4004 HValue* context = environment()->context(); |
4034 | 4005 |
4035 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4006 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
4036 literals, | 4007 literals, |
4037 expr->pattern(), | 4008 expr->pattern(), |
4038 expr->flags(), | 4009 expr->flags(), |
4039 expr->literal_index()); | 4010 expr->literal_index()); |
4040 return ast_context()->ReturnInstruction(instr, expr->id()); | 4011 return ast_context()->ReturnInstruction(instr, expr->id()); |
4041 } | 4012 } |
4042 | 4013 |
4043 | 4014 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4200 *pointer_size += boilerplate->map()->instance_size(); | 4171 *pointer_size += boilerplate->map()->instance_size(); |
4201 return true; | 4172 return true; |
4202 } | 4173 } |
4203 | 4174 |
4204 | 4175 |
4205 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4176 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
4206 ASSERT(!HasStackOverflow()); | 4177 ASSERT(!HasStackOverflow()); |
4207 ASSERT(current_block() != NULL); | 4178 ASSERT(current_block() != NULL); |
4208 ASSERT(current_block()->HasPredecessor()); | 4179 ASSERT(current_block()->HasPredecessor()); |
4209 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4180 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4210 HValue* context = environment()->LookupContext(); | 4181 HValue* context = environment()->context(); |
4211 HInstruction* literal; | 4182 HInstruction* literal; |
4212 | 4183 |
4213 // Check whether to use fast or slow deep-copying for boilerplate. | 4184 // Check whether to use fast or slow deep-copying for boilerplate. |
4214 int data_size = 0; | 4185 int data_size = 0; |
4215 int pointer_size = 0; | 4186 int pointer_size = 0; |
4216 int max_properties = kMaxFastLiteralProperties; | 4187 int max_properties = kMaxFastLiteralProperties; |
4217 Handle<Object> original_boilerplate(closure->literals()->get( | 4188 Handle<Object> original_boilerplate(closure->literals()->get( |
4218 expr->literal_index()), isolate()); | 4189 expr->literal_index()), isolate()); |
4219 if (original_boilerplate->IsJSObject() && | 4190 if (original_boilerplate->IsJSObject() && |
4220 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | 4191 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), |
(...skipping 24 matching lines...) Expand all Loading... |
4245 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 4216 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
4246 | 4217 |
4247 Add<HPushArgument>(Add<HConstant>(closure_literals)); | 4218 Add<HPushArgument>(Add<HConstant>(closure_literals)); |
4248 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4219 Add<HPushArgument>(Add<HConstant>(literal_index)); |
4249 Add<HPushArgument>(Add<HConstant>(constant_properties)); | 4220 Add<HPushArgument>(Add<HConstant>(constant_properties)); |
4250 Add<HPushArgument>(Add<HConstant>(flags)); | 4221 Add<HPushArgument>(Add<HConstant>(flags)); |
4251 | 4222 |
4252 Runtime::FunctionId function_id = | 4223 Runtime::FunctionId function_id = |
4253 (expr->depth() > 1 || expr->may_store_doubles()) | 4224 (expr->depth() > 1 || expr->may_store_doubles()) |
4254 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; | 4225 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; |
4255 literal = Add<HCallRuntime>(context, | 4226 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4256 isolate()->factory()->empty_string(), | |
4257 Runtime::FunctionForId(function_id), | 4227 Runtime::FunctionForId(function_id), |
4258 4); | 4228 4); |
4259 } | 4229 } |
4260 | 4230 |
4261 // The object is expected in the bailout environment during computation | 4231 // The object is expected in the bailout environment during computation |
4262 // of the property values and is the value of the entire expression. | 4232 // of the property values and is the value of the entire expression. |
4263 Push(literal); | 4233 Push(literal); |
4264 | 4234 |
4265 expr->CalculateEmitStore(zone()); | 4235 expr->CalculateEmitStore(zone()); |
4266 | 4236 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4328 } | 4298 } |
4329 } | 4299 } |
4330 | 4300 |
4331 | 4301 |
4332 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4302 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
4333 ASSERT(!HasStackOverflow()); | 4303 ASSERT(!HasStackOverflow()); |
4334 ASSERT(current_block() != NULL); | 4304 ASSERT(current_block() != NULL); |
4335 ASSERT(current_block()->HasPredecessor()); | 4305 ASSERT(current_block()->HasPredecessor()); |
4336 ZoneList<Expression*>* subexprs = expr->values(); | 4306 ZoneList<Expression*>* subexprs = expr->values(); |
4337 int length = subexprs->length(); | 4307 int length = subexprs->length(); |
4338 HValue* context = environment()->LookupContext(); | 4308 HValue* context = environment()->context(); |
4339 HInstruction* literal; | 4309 HInstruction* literal; |
4340 | 4310 |
4341 Handle<AllocationSite> site; | 4311 Handle<AllocationSite> site; |
4342 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4312 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
4343 bool uninitialized = false; | 4313 bool uninitialized = false; |
4344 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4314 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
4345 isolate()); | 4315 isolate()); |
4346 Handle<Object> raw_boilerplate; | 4316 Handle<Object> raw_boilerplate; |
4347 if (literals_cell->IsUndefined()) { | 4317 if (literals_cell->IsUndefined()) { |
4348 uninitialized = true; | 4318 uninitialized = true; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4407 // pass an empty fixed array to the runtime function instead. | 4377 // pass an empty fixed array to the runtime function instead. |
4408 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4378 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
4409 int literal_index = expr->literal_index(); | 4379 int literal_index = expr->literal_index(); |
4410 | 4380 |
4411 Add<HPushArgument>(Add<HConstant>(literals)); | 4381 Add<HPushArgument>(Add<HConstant>(literals)); |
4412 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4382 Add<HPushArgument>(Add<HConstant>(literal_index)); |
4413 Add<HPushArgument>(Add<HConstant>(constants)); | 4383 Add<HPushArgument>(Add<HConstant>(constants)); |
4414 | 4384 |
4415 Runtime::FunctionId function_id = (expr->depth() > 1) | 4385 Runtime::FunctionId function_id = (expr->depth() > 1) |
4416 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4386 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
4417 literal = Add<HCallRuntime>(context, | 4387 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4418 isolate()->factory()->empty_string(), | |
4419 Runtime::FunctionForId(function_id), | 4388 Runtime::FunctionForId(function_id), |
4420 3); | 4389 3); |
4421 | 4390 |
4422 // De-opt if elements kind changed from boilerplate_elements_kind. | 4391 // De-opt if elements kind changed from boilerplate_elements_kind. |
4423 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4392 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
4424 isolate()); | 4393 isolate()); |
4425 AddInstruction(HCheckMaps::New(literal, map, zone(), top_info())); | 4394 Add<HCheckMaps>(literal, map, top_info()); |
4426 } | 4395 } |
4427 | 4396 |
4428 // The array is expected in the bailout environment during computation | 4397 // The array is expected in the bailout environment during computation |
4429 // of the property values and is the value of the entire expression. | 4398 // of the property values and is the value of the entire expression. |
4430 Push(literal); | 4399 Push(literal); |
4431 // The literal index is on the stack, too. | 4400 // The literal index is on the stack, too. |
4432 Push(Add<HConstant>(expr->literal_index())); | 4401 Push(Add<HConstant>(expr->literal_index())); |
4433 | 4402 |
4434 HInstruction* elements = NULL; | 4403 HInstruction* elements = NULL; |
4435 | 4404 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4492 // 2nd chance: A store into a non-existent field can still be inlined if we | 4461 // 2nd chance: A store into a non-existent field can still be inlined if we |
4493 // have a matching transition and some room left in the object. | 4462 // have a matching transition and some room left in the object. |
4494 type->LookupTransition(NULL, *name, lookup); | 4463 type->LookupTransition(NULL, *name, lookup); |
4495 return lookup->IsTransitionToField(*type) && | 4464 return lookup->IsTransitionToField(*type) && |
4496 (type->unused_property_fields() > 0); | 4465 (type->unused_property_fields() > 0); |
4497 } | 4466 } |
4498 | 4467 |
4499 | 4468 |
4500 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 4469 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
4501 BuildCheckHeapObject(object); | 4470 BuildCheckHeapObject(object); |
4502 AddInstruction(HCheckMaps::New(object, map, zone(), top_info())); | 4471 Add<HCheckMaps>(object, map, top_info()); |
4503 } | 4472 } |
4504 | 4473 |
4505 | 4474 |
4506 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 4475 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
4507 HValue* object, | 4476 HValue* object, |
4508 Handle<String> name, | 4477 Handle<String> name, |
4509 HValue* value, | 4478 HValue* value, |
4510 Handle<Map> map, | 4479 Handle<Map> map, |
4511 LookupResult* lookup) { | 4480 LookupResult* lookup) { |
4512 ASSERT(lookup->IsFound()); | 4481 ASSERT(lookup->IsFound()); |
(...skipping 14 matching lines...) Expand all Loading... |
4527 // We only need to check up to the preexisting property. | 4496 // We only need to check up to the preexisting property. |
4528 proto = proto_result.holder(); | 4497 proto = proto_result.holder(); |
4529 } else { | 4498 } else { |
4530 // Otherwise, find the top prototype. | 4499 // Otherwise, find the top prototype. |
4531 while (proto->GetPrototype(isolate())->IsJSObject()) { | 4500 while (proto->GetPrototype(isolate())->IsJSObject()) { |
4532 proto = proto->GetPrototype(isolate()); | 4501 proto = proto->GetPrototype(isolate()); |
4533 } | 4502 } |
4534 ASSERT(proto->GetPrototype(isolate())->IsNull()); | 4503 ASSERT(proto->GetPrototype(isolate())->IsNull()); |
4535 } | 4504 } |
4536 ASSERT(proto->IsJSObject()); | 4505 ASSERT(proto->IsJSObject()); |
4537 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())), | 4506 Add<HCheckPrototypeMaps>( |
4538 Handle<JSObject>(JSObject::cast(proto)), | 4507 Handle<JSObject>(JSObject::cast(map->prototype())), |
4539 zone(), top_info()); | 4508 Handle<JSObject>(JSObject::cast(proto)), top_info()); |
4540 } | 4509 } |
4541 | 4510 |
4542 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); | 4511 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); |
4543 bool transition_to_field = lookup->IsTransitionToField(*map); | 4512 bool transition_to_field = lookup->IsTransitionToField(*map); |
4544 | 4513 |
4545 HStoreNamedField *instr; | 4514 HStoreNamedField *instr; |
4546 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { | 4515 if (FLAG_track_double_fields && field_access.representation().IsDouble()) { |
4547 HObjectAccess heap_number_access = | 4516 HObjectAccess heap_number_access = |
4548 field_access.WithRepresentation(Representation::Tagged()); | 4517 field_access.WithRepresentation(Representation::Tagged()); |
4549 if (transition_to_field) { | 4518 if (transition_to_field) { |
4550 // The store requires a mutable HeapNumber to be allocated. | 4519 // The store requires a mutable HeapNumber to be allocated. |
4551 NoObservableSideEffectsScope no_side_effects(this); | 4520 NoObservableSideEffectsScope no_side_effects(this); |
4552 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 4521 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
4553 HInstruction* heap_number = Add<HAllocate>( | 4522 HInstruction* heap_number = Add<HAllocate>(heap_number_size, |
4554 environment()->LookupContext(), heap_number_size, | |
4555 HType::HeapNumber(), false); | 4523 HType::HeapNumber(), false); |
4556 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); | 4524 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
4557 AddStore(heap_number, HObjectAccess::ForHeapNumberValue(), value); | 4525 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), |
4558 instr = new(zone()) HStoreNamedField( | 4526 value); |
4559 object, heap_number_access, heap_number); | 4527 instr = New<HStoreNamedField>(object, heap_number_access, |
| 4528 heap_number); |
4560 } else { | 4529 } else { |
4561 // Already holds a HeapNumber; load the box and write its value field. | 4530 // Already holds a HeapNumber; load the box and write its value field. |
4562 HInstruction* heap_number = AddLoad(object, heap_number_access); | 4531 HInstruction* heap_number = Add<HLoadNamedField>(object, |
| 4532 heap_number_access); |
4563 heap_number->set_type(HType::HeapNumber()); | 4533 heap_number->set_type(HType::HeapNumber()); |
4564 instr = new(zone()) HStoreNamedField(heap_number, | 4534 instr = New<HStoreNamedField>(heap_number, |
4565 HObjectAccess::ForHeapNumberValue(), value); | 4535 HObjectAccess::ForHeapNumberValue(), |
| 4536 value); |
4566 } | 4537 } |
4567 } else { | 4538 } else { |
4568 // This is a normal store. | 4539 // This is a normal store. |
4569 instr = new(zone()) HStoreNamedField(object, field_access, value); | 4540 instr = New<HStoreNamedField>(object, field_access, value); |
4570 } | 4541 } |
4571 | 4542 |
4572 if (transition_to_field) { | 4543 if (transition_to_field) { |
4573 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4544 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
4574 instr->SetTransition(transition, top_info()); | 4545 instr->SetTransition(transition, top_info()); |
4575 // TODO(fschneider): Record the new map type of the object in the IR to | 4546 // TODO(fschneider): Record the new map type of the object in the IR to |
4576 // enable elimination of redundant checks after the transition store. | 4547 // enable elimination of redundant checks after the transition store. |
4577 instr->SetGVNFlag(kChangesMaps); | 4548 instr->SetGVNFlag(kChangesMaps); |
4578 } | 4549 } |
4579 return instr; | 4550 return instr; |
4580 } | 4551 } |
4581 | 4552 |
4582 | 4553 |
4583 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | 4554 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( |
4584 HValue* object, | 4555 HValue* object, |
4585 Handle<String> name, | 4556 Handle<String> name, |
4586 HValue* value) { | 4557 HValue* value) { |
4587 HValue* context = environment()->LookupContext(); | 4558 HValue* context = environment()->context(); |
4588 return new(zone()) HStoreNamedGeneric( | 4559 return new(zone()) HStoreNamedGeneric( |
4589 context, | 4560 context, |
4590 object, | 4561 object, |
4591 name, | 4562 name, |
4592 value, | 4563 value, |
4593 function_strict_mode_flag()); | 4564 function_strict_mode_flag()); |
4594 } | 4565 } |
4595 | 4566 |
4596 | 4567 |
4597 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 4568 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4654 // In-objectness did not match. | 4625 // In-objectness did not match. |
4655 break; | 4626 break; |
4656 } | 4627 } |
4657 access = access.WithRepresentation( | 4628 access = access.WithRepresentation( |
4658 access.representation().generalize(new_access.representation())); | 4629 access.representation().generalize(new_access.representation())); |
4659 } | 4630 } |
4660 | 4631 |
4661 if (count == types->length()) { | 4632 if (count == types->length()) { |
4662 // Everything matched; can use monomorphic load. | 4633 // Everything matched; can use monomorphic load. |
4663 BuildCheckHeapObject(object); | 4634 BuildCheckHeapObject(object); |
4664 AddInstruction(HCheckMaps::New(object, types, zone())); | 4635 Add<HCheckMaps>(object, types); |
4665 return BuildLoadNamedField(object, access); | 4636 return BuildLoadNamedField(object, access); |
4666 } | 4637 } |
4667 | 4638 |
4668 if (count != 0) return NULL; | 4639 if (count != 0) return NULL; |
4669 | 4640 |
4670 // Second chance: the property is on the prototype and all maps have the | 4641 // Second chance: the property is on the prototype and all maps have the |
4671 // same prototype. | 4642 // same prototype. |
4672 Handle<Map> map(types->at(0)); | 4643 Handle<Map> map(types->at(0)); |
4673 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; | 4644 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
4674 | 4645 |
4675 Handle<Object> prototype(map->prototype(), isolate()); | 4646 Handle<Object> prototype(map->prototype(), isolate()); |
4676 for (count = 1; count < types->length(); ++count) { | 4647 for (count = 1; count < types->length(); ++count) { |
4677 Handle<Map> test_map(types->at(count)); | 4648 Handle<Map> test_map(types->at(count)); |
4678 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; | 4649 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
4679 if (test_map->prototype() != *prototype) return NULL; | 4650 if (test_map->prototype() != *prototype) return NULL; |
4680 } | 4651 } |
4681 | 4652 |
4682 LookupInPrototypes(map, name, &lookup); | 4653 LookupInPrototypes(map, name, &lookup); |
4683 if (!lookup.IsField()) return NULL; | 4654 if (!lookup.IsField()) return NULL; |
4684 | 4655 |
4685 BuildCheckHeapObject(object); | 4656 BuildCheckHeapObject(object); |
4686 AddInstruction(HCheckMaps::New(object, types, zone())); | 4657 Add<HCheckMaps>(object, types); |
4687 | 4658 |
4688 Handle<JSObject> holder(lookup.holder()); | 4659 Handle<JSObject> holder(lookup.holder()); |
4689 Handle<Map> holder_map(holder->map()); | 4660 Handle<Map> holder_map(holder->map()); |
4690 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4661 Add<HCheckPrototypeMaps>( |
4691 Handle<JSObject>::cast(prototype), holder, zone(), top_info())); | 4662 Handle<JSObject>::cast(prototype), holder, top_info()); |
4692 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder)); | 4663 HValue* holder_value = Add<HConstant>(holder); |
4693 return BuildLoadNamedField(holder_value, | 4664 return BuildLoadNamedField(holder_value, |
4694 HObjectAccess::ForField(holder_map, &lookup, name)); | 4665 HObjectAccess::ForField(holder_map, &lookup, name)); |
4695 } | 4666 } |
4696 | 4667 |
4697 | 4668 |
4698 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4669 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
4699 Property* expr, | 4670 Property* expr, |
4700 HValue* object, | 4671 HValue* object, |
4701 SmallMapList* types, | 4672 SmallMapList* types, |
4702 Handle<String> name) { | 4673 Handle<String> name) { |
4703 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 4674 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
4704 expr, object, types, name); | 4675 expr, object, types, name); |
4705 if (instr == NULL) { | 4676 if (instr == NULL) { |
4706 // Something did not match; must use a polymorphic load. | 4677 // Something did not match; must use a polymorphic load. |
4707 BuildCheckHeapObject(object); | 4678 BuildCheckHeapObject(object); |
4708 HValue* context = environment()->LookupContext(); | 4679 HValue* context = environment()->context(); |
4709 instr = new(zone()) HLoadNamedFieldPolymorphic( | 4680 instr = new(zone()) HLoadNamedFieldPolymorphic( |
4710 context, object, types, name, zone()); | 4681 context, object, types, name, zone()); |
4711 } | 4682 } |
4712 | 4683 |
4713 instr->set_position(expr->position()); | 4684 instr->set_position(expr->position()); |
4714 return ast_context()->ReturnInstruction(instr, expr->id()); | 4685 return ast_context()->ReturnInstruction(instr, expr->id()); |
4715 } | 4686 } |
4716 | 4687 |
4717 | 4688 |
4718 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 4689 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4755 } else if (access.IsInobject() != new_access.IsInobject()) { | 4726 } else if (access.IsInobject() != new_access.IsInobject()) { |
4756 // In-objectness did not match. | 4727 // In-objectness did not match. |
4757 break; | 4728 break; |
4758 } | 4729 } |
4759 } | 4730 } |
4760 | 4731 |
4761 if (count != types->length()) return false; | 4732 if (count != types->length()) return false; |
4762 | 4733 |
4763 // Everything matched; can use monomorphic store. | 4734 // Everything matched; can use monomorphic store. |
4764 BuildCheckHeapObject(object); | 4735 BuildCheckHeapObject(object); |
4765 AddInstruction(HCheckMaps::New(object, types, zone())); | 4736 Add<HCheckMaps>(object, types); |
4766 HInstruction* store; | 4737 HInstruction* store; |
4767 CHECK_ALIVE_OR_RETURN( | 4738 CHECK_ALIVE_OR_RETURN( |
4768 store = BuildStoreNamedField( | 4739 store = BuildStoreNamedField( |
4769 object, name, store_value, types->at(count - 1), &lookup), | 4740 object, name, store_value, types->at(count - 1), &lookup), |
4770 true); | 4741 true); |
4771 if (!ast_context()->IsEffect()) Push(result_value); | 4742 if (!ast_context()->IsEffect()) Push(result_value); |
4772 store->set_position(position); | 4743 store->set_position(position); |
4773 AddInstruction(store); | 4744 AddInstruction(store); |
4774 Add<HSimulate>(assignment_id); | 4745 Add<HSimulate>(assignment_id); |
4775 if (!ast_context()->IsEffect()) Drop(1); | 4746 if (!ast_context()->IsEffect()) Drop(1); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 Add<HDeoptimize>(Deoptimizer::EAGER); | 4898 Add<HDeoptimize>(Deoptimizer::EAGER); |
4928 builder.End(); | 4899 builder.End(); |
4929 } | 4900 } |
4930 HInstruction* instr = | 4901 HInstruction* instr = |
4931 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4902 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
4932 instr->set_position(position); | 4903 instr->set_position(position); |
4933 if (instr->HasObservableSideEffects()) { | 4904 if (instr->HasObservableSideEffects()) { |
4934 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4905 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4935 } | 4906 } |
4936 } else { | 4907 } else { |
4937 HValue* context = environment()->LookupContext(); | 4908 HGlobalObject* global_object = Add<HGlobalObject>(); |
4938 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
4939 HStoreGlobalGeneric* instr = | 4909 HStoreGlobalGeneric* instr = |
4940 Add<HStoreGlobalGeneric>(context, global_object, var->name(), | 4910 Add<HStoreGlobalGeneric>(global_object, var->name(), |
4941 value, function_strict_mode_flag()); | 4911 value, function_strict_mode_flag()); |
4942 instr->set_position(position); | 4912 instr->set_position(position); |
4943 ASSERT(instr->HasObservableSideEffects()); | 4913 ASSERT(instr->HasObservableSideEffects()); |
4944 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4914 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4945 } | 4915 } |
4946 } | 4916 } |
4947 | 4917 |
4948 | 4918 |
4949 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4919 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
4950 BailoutId id, | 4920 BailoutId id, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5071 return ast_context()->ReturnValue(Pop()); | 5041 return ast_context()->ReturnValue(Pop()); |
5072 case CONST_HARMONY: | 5042 case CONST_HARMONY: |
5073 // This case is checked statically so no need to | 5043 // This case is checked statically so no need to |
5074 // perform checks here | 5044 // perform checks here |
5075 UNREACHABLE(); | 5045 UNREACHABLE(); |
5076 default: | 5046 default: |
5077 mode = HStoreContextSlot::kNoCheck; | 5047 mode = HStoreContextSlot::kNoCheck; |
5078 } | 5048 } |
5079 | 5049 |
5080 HValue* context = BuildContextChainWalk(var); | 5050 HValue* context = BuildContextChainWalk(var); |
5081 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5051 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
5082 mode, Top()); | 5052 context, var->index(), mode, Top()); |
5083 if (instr->HasObservableSideEffects()) { | 5053 if (instr->HasObservableSideEffects()) { |
5084 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5054 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5085 } | 5055 } |
5086 break; | 5056 break; |
5087 } | 5057 } |
5088 | 5058 |
5089 case Variable::LOOKUP: | 5059 case Variable::LOOKUP: |
5090 return Bailout("compound assignment to lookup slot"); | 5060 return Bailout("compound assignment to lookup slot"); |
5091 } | 5061 } |
5092 return ast_context()->ReturnValue(Pop()); | 5062 return ast_context()->ReturnValue(Pop()); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5283 expr->op() == Token::INIT_LET || | 5253 expr->op() == Token::INIT_LET || |
5284 expr->op() == Token::INIT_CONST_HARMONY) { | 5254 expr->op() == Token::INIT_CONST_HARMONY) { |
5285 mode = HStoreContextSlot::kNoCheck; | 5255 mode = HStoreContextSlot::kNoCheck; |
5286 } else { | 5256 } else { |
5287 ASSERT(expr->op() == Token::INIT_CONST); | 5257 ASSERT(expr->op() == Token::INIT_CONST); |
5288 | 5258 |
5289 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 5259 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
5290 } | 5260 } |
5291 | 5261 |
5292 HValue* context = BuildContextChainWalk(var); | 5262 HValue* context = BuildContextChainWalk(var); |
5293 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(), | 5263 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
5294 mode, Top()); | 5264 context, var->index(), mode, Top()); |
5295 if (instr->HasObservableSideEffects()) { | 5265 if (instr->HasObservableSideEffects()) { |
5296 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 5266 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
5297 } | 5267 } |
5298 return ast_context()->ReturnValue(Pop()); | 5268 return ast_context()->ReturnValue(Pop()); |
5299 } | 5269 } |
5300 | 5270 |
5301 case Variable::LOOKUP: | 5271 case Variable::LOOKUP: |
5302 return Bailout("assignment to LOOKUP variable"); | 5272 return Bailout("assignment to LOOKUP variable"); |
5303 } | 5273 } |
5304 } else { | 5274 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
5316 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 5286 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { |
5317 ASSERT(!HasStackOverflow()); | 5287 ASSERT(!HasStackOverflow()); |
5318 ASSERT(current_block() != NULL); | 5288 ASSERT(current_block() != NULL); |
5319 ASSERT(current_block()->HasPredecessor()); | 5289 ASSERT(current_block()->HasPredecessor()); |
5320 // We don't optimize functions with invalid left-hand sides in | 5290 // We don't optimize functions with invalid left-hand sides in |
5321 // assignments, count operations, or for-in. Consequently throw can | 5291 // assignments, count operations, or for-in. Consequently throw can |
5322 // currently only occur in an effect context. | 5292 // currently only occur in an effect context. |
5323 ASSERT(ast_context()->IsEffect()); | 5293 ASSERT(ast_context()->IsEffect()); |
5324 CHECK_ALIVE(VisitForValue(expr->exception())); | 5294 CHECK_ALIVE(VisitForValue(expr->exception())); |
5325 | 5295 |
5326 HValue* context = environment()->LookupContext(); | |
5327 HValue* value = environment()->Pop(); | 5296 HValue* value = environment()->Pop(); |
5328 HThrow* instr = Add<HThrow>(context, value); | 5297 HThrow* instr = Add<HThrow>(value); |
5329 instr->set_position(expr->position()); | 5298 instr->set_position(expr->position()); |
5330 Add<HSimulate>(expr->id()); | 5299 Add<HSimulate>(expr->id()); |
5331 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5300 current_block()->FinishExit(new(zone()) HAbnormalExit); |
5332 set_current_block(NULL); | 5301 set_current_block(NULL); |
5333 } | 5302 } |
5334 | 5303 |
5335 | 5304 |
5336 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5305 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
5337 HObjectAccess access) { | 5306 HObjectAccess access) { |
5338 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5307 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
5339 // load the heap number | 5308 // load the heap number |
5340 HLoadNamedField* heap_number = | 5309 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
5341 AddLoad(object, access.WithRepresentation(Representation::Tagged())); | 5310 object, access.WithRepresentation(Representation::Tagged())); |
5342 heap_number->set_type(HType::HeapNumber()); | 5311 heap_number->set_type(HType::HeapNumber()); |
5343 // load the double value from it | 5312 // load the double value from it |
5344 return new(zone()) HLoadNamedField(heap_number, | 5313 return New<HLoadNamedField>(heap_number, |
5345 HObjectAccess::ForHeapNumberValue(), NULL); | 5314 HObjectAccess::ForHeapNumberValue()); |
5346 } | 5315 } |
5347 return new(zone()) HLoadNamedField(object, access, NULL); | 5316 return New<HLoadNamedField>(object, access); |
5348 } | 5317 } |
5349 | 5318 |
5350 | 5319 |
5351 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5320 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5352 HValue* object, | 5321 HValue* object, |
5353 Handle<String> name, | 5322 Handle<String> name, |
5354 Property* expr) { | 5323 Property* expr) { |
5355 if (expr->IsUninitialized()) { | 5324 if (expr->IsUninitialized()) { |
5356 Add<HDeoptimize>(Deoptimizer::SOFT); | 5325 Add<HDeoptimize>(Deoptimizer::SOFT); |
5357 } | 5326 } |
5358 HValue* context = environment()->LookupContext(); | 5327 HValue* context = environment()->context(); |
5359 return new(zone()) HLoadNamedGeneric(context, object, name); | 5328 return new(zone()) HLoadNamedGeneric(context, object, name); |
5360 } | 5329 } |
5361 | 5330 |
5362 | 5331 |
5363 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5332 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
5364 HValue* object, | 5333 HValue* object, |
5365 Handle<Map> map, | 5334 Handle<Map> map, |
5366 Handle<JSFunction> getter, | 5335 Handle<JSFunction> getter, |
5367 Handle<JSObject> holder) { | 5336 Handle<JSObject> holder) { |
5368 AddCheckConstantFunction(holder, object, map); | 5337 AddCheckConstantFunction(holder, object, map); |
5369 Add<HPushArgument>(object); | 5338 Add<HPushArgument>(object); |
5370 return new(zone()) HCallConstantFunction(getter, 1); | 5339 return new(zone()) HCallConstantFunction(getter, 1); |
5371 } | 5340 } |
5372 | 5341 |
5373 | 5342 |
5374 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( | 5343 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
5375 HValue* object, | 5344 HValue* object, |
5376 Handle<String> name, | 5345 Handle<String> name, |
5377 Property* expr, | 5346 Property* expr, |
5378 Handle<Map> map) { | 5347 Handle<Map> map) { |
5379 // Handle a load from a known field. | 5348 // Handle a load from a known field. |
5380 ASSERT(!map->is_dictionary_map()); | 5349 ASSERT(!map->is_dictionary_map()); |
5381 | 5350 |
5382 // Handle access to various length properties | 5351 // Handle access to various length properties |
5383 if (name->Equals(isolate()->heap()->length_string())) { | 5352 if (name->Equals(isolate()->heap()->length_string())) { |
5384 if (map->instance_type() == JS_ARRAY_TYPE) { | 5353 if (map->instance_type() == JS_ARRAY_TYPE) { |
5385 AddCheckMap(object, map); | 5354 AddCheckMap(object, map); |
5386 return new(zone()) HLoadNamedField(object, | 5355 return New<HLoadNamedField>(object, |
5387 HObjectAccess::ForArrayLength(map->elements_kind())); | 5356 HObjectAccess::ForArrayLength(map->elements_kind())); |
5388 } | 5357 } |
5389 } | 5358 } |
5390 | 5359 |
5391 LookupResult lookup(isolate()); | 5360 LookupResult lookup(isolate()); |
5392 map->LookupDescriptor(NULL, *name, &lookup); | 5361 map->LookupDescriptor(NULL, *name, &lookup); |
5393 if (lookup.IsField()) { | 5362 if (lookup.IsField()) { |
5394 AddCheckMap(object, map); | 5363 AddCheckMap(object, map); |
5395 return BuildLoadNamedField(object, | 5364 return BuildLoadNamedField(object, |
5396 HObjectAccess::ForField(map, &lookup, name)); | 5365 HObjectAccess::ForField(map, &lookup, name)); |
5397 } | 5366 } |
5398 | 5367 |
5399 // Handle a load of a constant known function. | 5368 // Handle a load of a constant known function. |
5400 if (lookup.IsConstant()) { | 5369 if (lookup.IsConstant()) { |
5401 AddCheckMap(object, map); | 5370 AddCheckMap(object, map); |
5402 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5371 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
5403 return new(zone()) HConstant(constant); | 5372 return New<HConstant>(constant); |
5404 } | 5373 } |
5405 | 5374 |
5406 // Handle a load from a known field somewhere in the prototype chain. | 5375 // Handle a load from a known field somewhere in the prototype chain. |
5407 LookupInPrototypes(map, name, &lookup); | 5376 LookupInPrototypes(map, name, &lookup); |
5408 if (lookup.IsField()) { | 5377 if (lookup.IsField()) { |
5409 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5378 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5410 Handle<JSObject> holder(lookup.holder()); | 5379 Handle<JSObject> holder(lookup.holder()); |
5411 Handle<Map> holder_map(holder->map()); | 5380 Handle<Map> holder_map(holder->map()); |
5412 AddCheckMap(object, map); | 5381 AddCheckMap(object, map); |
5413 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5382 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5414 HValue* holder_value = Add<HConstant>(holder); | 5383 HValue* holder_value = Add<HConstant>(holder); |
5415 return BuildLoadNamedField(holder_value, | 5384 return BuildLoadNamedField(holder_value, |
5416 HObjectAccess::ForField(holder_map, &lookup, name)); | 5385 HObjectAccess::ForField(holder_map, &lookup, name)); |
5417 } | 5386 } |
5418 | 5387 |
5419 // Handle a load of a constant function somewhere in the prototype chain. | 5388 // Handle a load of a constant function somewhere in the prototype chain. |
5420 if (lookup.IsConstant()) { | 5389 if (lookup.IsConstant()) { |
5421 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5390 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
5422 Handle<JSObject> holder(lookup.holder()); | 5391 Handle<JSObject> holder(lookup.holder()); |
5423 Handle<Map> holder_map(holder->map()); | 5392 Handle<Map> holder_map(holder->map()); |
5424 AddCheckMap(object, map); | 5393 AddCheckMap(object, map); |
5425 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5394 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5426 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5395 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
5427 return new(zone()) HConstant(constant); | 5396 return New<HConstant>(constant); |
5428 } | 5397 } |
5429 | 5398 |
5430 // No luck, do a generic load. | 5399 // No luck, do a generic load. |
5431 return BuildLoadNamedGeneric(object, name, expr); | 5400 return BuildLoadNamedGeneric(object, name, expr); |
5432 } | 5401 } |
5433 | 5402 |
5434 | 5403 |
5435 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5404 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
5436 HValue* key) { | 5405 HValue* key) { |
5437 HValue* context = environment()->LookupContext(); | 5406 HValue* context = environment()->context(); |
5438 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5407 return new(zone()) HLoadKeyedGeneric(context, object, key); |
5439 } | 5408 } |
5440 | 5409 |
5441 | 5410 |
5442 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 5411 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
5443 HValue* object, | 5412 HValue* object, |
5444 HValue* key, | 5413 HValue* key, |
5445 HValue* val, | 5414 HValue* val, |
5446 HValue* dependency, | 5415 HValue* dependency, |
5447 Handle<Map> map, | 5416 Handle<Map> map, |
5448 bool is_store, | 5417 bool is_store, |
5449 KeyedAccessStoreMode store_mode) { | 5418 KeyedAccessStoreMode store_mode) { |
5450 HCheckMaps* mapcheck = HCheckMaps::New( | 5419 HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency); |
5451 object, map, zone(), top_info(), dependency); | |
5452 AddInstruction(mapcheck); | |
5453 if (dependency) { | 5420 if (dependency) { |
5454 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 5421 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
5455 } | 5422 } |
5456 | 5423 |
5457 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5424 // Loads from a "stock" fast holey double arrays can elide the hole check. |
5458 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5425 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
5459 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5426 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
5460 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5427 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
5461 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5428 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
5462 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 5429 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
5463 Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info()); | 5430 Add<HCheckPrototypeMaps>(prototype, object_prototype, top_info()); |
5464 load_mode = ALLOW_RETURN_HOLE; | 5431 load_mode = ALLOW_RETURN_HOLE; |
5465 graph()->MarkDependsOnEmptyArrayProtoElements(); | 5432 graph()->MarkDependsOnEmptyArrayProtoElements(); |
5466 } | 5433 } |
5467 | 5434 |
5468 return BuildUncheckedMonomorphicElementAccess( | 5435 return BuildUncheckedMonomorphicElementAccess( |
5469 object, key, val, | 5436 object, key, val, |
5470 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 5437 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
5471 map->elements_kind(), is_store, load_mode, store_mode); | 5438 map->elements_kind(), is_store, load_mode, store_mode); |
5472 } | 5439 } |
5473 | 5440 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5510 // Remember the most general elements kind, the code for its load will | 5477 // Remember the most general elements kind, the code for its load will |
5511 // properly handle all of the more specific cases. | 5478 // properly handle all of the more specific cases. |
5512 if ((i == 0) || IsMoreGeneralElementsKindTransition( | 5479 if ((i == 0) || IsMoreGeneralElementsKindTransition( |
5513 most_general_consolidated_map->elements_kind(), | 5480 most_general_consolidated_map->elements_kind(), |
5514 map->elements_kind())) { | 5481 map->elements_kind())) { |
5515 most_general_consolidated_map = map; | 5482 most_general_consolidated_map = map; |
5516 } | 5483 } |
5517 } | 5484 } |
5518 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 5485 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
5519 | 5486 |
5520 HCheckMaps* check_maps = HCheckMaps::New(object, maps, zone()); | 5487 HCheckMaps* check_maps = Add<HCheckMaps>(object, maps); |
5521 AddInstruction(check_maps); | |
5522 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 5488 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
5523 object, key, val, check_maps, | 5489 object, key, val, check_maps, |
5524 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 5490 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
5525 most_general_consolidated_map->elements_kind(), | 5491 most_general_consolidated_map->elements_kind(), |
5526 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 5492 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
5527 return instr; | 5493 return instr; |
5528 } | 5494 } |
5529 | 5495 |
5530 | 5496 |
5531 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 5497 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5576 | 5542 |
5577 MapHandleList untransitionable_maps(maps->length()); | 5543 MapHandleList untransitionable_maps(maps->length()); |
5578 HTransitionElementsKind* transition = NULL; | 5544 HTransitionElementsKind* transition = NULL; |
5579 for (int i = 0; i < maps->length(); ++i) { | 5545 for (int i = 0; i < maps->length(); ++i) { |
5580 Handle<Map> map = maps->at(i); | 5546 Handle<Map> map = maps->at(i); |
5581 ASSERT(map->IsMap()); | 5547 ASSERT(map->IsMap()); |
5582 if (!transition_target.at(i).is_null()) { | 5548 if (!transition_target.at(i).is_null()) { |
5583 ASSERT(Map::IsValidElementsTransition( | 5549 ASSERT(Map::IsValidElementsTransition( |
5584 map->elements_kind(), | 5550 map->elements_kind(), |
5585 transition_target.at(i)->elements_kind())); | 5551 transition_target.at(i)->elements_kind())); |
5586 HValue* context = environment()->LookupContext(); | 5552 transition = Add<HTransitionElementsKind>(object, map, |
5587 transition = Add<HTransitionElementsKind>(context, object, map, | |
5588 transition_target.at(i)); | 5553 transition_target.at(i)); |
5589 } else { | 5554 } else { |
5590 untransitionable_maps.Add(map); | 5555 untransitionable_maps.Add(map); |
5591 } | 5556 } |
5592 } | 5557 } |
5593 | 5558 |
5594 // If only one map is left after transitioning, handle this case | 5559 // If only one map is left after transitioning, handle this case |
5595 // monomorphically. | 5560 // monomorphically. |
5596 ASSERT(untransitionable_maps.length() >= 1); | 5561 ASSERT(untransitionable_maps.length() >= 1); |
5597 if (untransitionable_maps.length() == 1) { | 5562 if (untransitionable_maps.length() == 1) { |
(...skipping 25 matching lines...) Expand all Loading... |
5623 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5588 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
5624 HCompareMap* mapcompare = | 5589 HCompareMap* mapcompare = |
5625 new(zone()) HCompareMap(object, map, this_map, other_map); | 5590 new(zone()) HCompareMap(object, map, this_map, other_map); |
5626 current_block()->Finish(mapcompare); | 5591 current_block()->Finish(mapcompare); |
5627 | 5592 |
5628 set_current_block(this_map); | 5593 set_current_block(this_map); |
5629 HInstruction* checked_key = NULL; | 5594 HInstruction* checked_key = NULL; |
5630 HInstruction* access = NULL; | 5595 HInstruction* access = NULL; |
5631 if (IsFastElementsKind(elements_kind)) { | 5596 if (IsFastElementsKind(elements_kind)) { |
5632 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | 5597 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { |
5633 AddInstruction(HCheckMaps::New( | 5598 Add<HCheckMaps>( |
5634 elements, isolate()->factory()->fixed_array_map(), | 5599 elements, isolate()->factory()->fixed_array_map(), |
5635 zone(), top_info(), mapcompare)); | 5600 top_info(), mapcompare); |
5636 } | 5601 } |
5637 if (map->instance_type() == JS_ARRAY_TYPE) { | 5602 if (map->instance_type() == JS_ARRAY_TYPE) { |
5638 HInstruction* length = AddLoad( | 5603 HInstruction* length = Add<HLoadNamedField>( |
5639 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); | 5604 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); |
5640 checked_key = Add<HBoundsCheck>(key, length); | 5605 checked_key = Add<HBoundsCheck>(key, length); |
5641 } else { | 5606 } else { |
5642 HInstruction* length = AddLoadFixedArrayLength(elements); | 5607 HInstruction* length = AddLoadFixedArrayLength(elements); |
5643 checked_key = Add<HBoundsCheck>(key, length); | 5608 checked_key = Add<HBoundsCheck>(key, length); |
5644 } | 5609 } |
5645 access = AddFastElementAccess( | 5610 access = AddFastElementAccess( |
5646 elements, checked_key, val, mapcompare, | 5611 elements, checked_key, val, mapcompare, |
5647 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); | 5612 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); |
5648 } else if (IsDictionaryElementsKind(elements_kind)) { | 5613 } else if (IsDictionaryElementsKind(elements_kind)) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5724 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5689 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
5725 *has_side_effects = instr->HasObservableSideEffects(); | 5690 *has_side_effects = instr->HasObservableSideEffects(); |
5726 return instr; | 5691 return instr; |
5727 } | 5692 } |
5728 | 5693 |
5729 | 5694 |
5730 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 5695 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
5731 HValue* object, | 5696 HValue* object, |
5732 HValue* key, | 5697 HValue* key, |
5733 HValue* value) { | 5698 HValue* value) { |
5734 HValue* context = environment()->LookupContext(); | 5699 HValue* context = environment()->context(); |
5735 return new(zone()) HStoreKeyedGeneric( | 5700 return new(zone()) HStoreKeyedGeneric( |
5736 context, | 5701 context, |
5737 object, | 5702 object, |
5738 key, | 5703 key, |
5739 value, | 5704 value, |
5740 function_strict_mode_flag()); | 5705 function_strict_mode_flag()); |
5741 } | 5706 } |
5742 | 5707 |
5743 | 5708 |
5744 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 5709 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
5745 // Outermost function already has arguments on the stack. | 5710 // Outermost function already has arguments on the stack. |
5746 if (function_state()->outer() == NULL) return; | 5711 if (function_state()->outer() == NULL) return; |
5747 | 5712 |
5748 if (function_state()->arguments_pushed()) return; | 5713 if (function_state()->arguments_pushed()) return; |
5749 | 5714 |
5750 // Push arguments when entering inlined function. | 5715 // Push arguments when entering inlined function. |
5751 HEnterInlined* entry = function_state()->entry(); | 5716 HEnterInlined* entry = function_state()->entry(); |
5752 entry->set_arguments_pushed(); | 5717 entry->set_arguments_pushed(); |
5753 | 5718 |
5754 HArgumentsObject* arguments = entry->arguments_object(); | 5719 HArgumentsObject* arguments = entry->arguments_object(); |
5755 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); | 5720 const ZoneList<HValue*>* arguments_values = arguments->arguments_values(); |
5756 | 5721 |
5757 HInstruction* insert_after = entry; | 5722 HInstruction* insert_after = entry; |
5758 for (int i = 0; i < arguments_values->length(); i++) { | 5723 for (int i = 0; i < arguments_values->length(); i++) { |
5759 HValue* argument = arguments_values->at(i); | 5724 HValue* argument = arguments_values->at(i); |
5760 HInstruction* push_argument = new(zone()) HPushArgument(argument); | 5725 HInstruction* push_argument = New<HPushArgument>(argument); |
5761 push_argument->InsertAfter(insert_after); | 5726 push_argument->InsertAfter(insert_after); |
5762 insert_after = push_argument; | 5727 insert_after = push_argument; |
5763 } | 5728 } |
5764 | 5729 |
5765 HArgumentsElements* arguments_elements = | 5730 HArgumentsElements* arguments_elements = New<HArgumentsElements>(true); |
5766 new(zone()) HArgumentsElements(true); | |
5767 arguments_elements->ClearFlag(HValue::kUseGVN); | 5731 arguments_elements->ClearFlag(HValue::kUseGVN); |
5768 arguments_elements->InsertAfter(insert_after); | 5732 arguments_elements->InsertAfter(insert_after); |
5769 function_state()->set_arguments_elements(arguments_elements); | 5733 function_state()->set_arguments_elements(arguments_elements); |
5770 } | 5734 } |
5771 | 5735 |
5772 | 5736 |
5773 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { | 5737 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { |
5774 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 5738 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
5775 if (proxy == NULL) return false; | 5739 if (proxy == NULL) return false; |
5776 if (!proxy->var()->IsStackAllocated()) return false; | 5740 if (!proxy->var()->IsStackAllocated()) return false; |
5777 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 5741 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
5778 return false; | 5742 return false; |
5779 } | 5743 } |
5780 | 5744 |
5781 HInstruction* result = NULL; | 5745 HInstruction* result = NULL; |
5782 if (expr->key()->IsPropertyName()) { | 5746 if (expr->key()->IsPropertyName()) { |
5783 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5747 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
5784 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; | 5748 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; |
5785 | 5749 |
5786 if (function_state()->outer() == NULL) { | 5750 if (function_state()->outer() == NULL) { |
5787 HInstruction* elements = Add<HArgumentsElements>(false); | 5751 HInstruction* elements = Add<HArgumentsElements>(false); |
5788 result = new(zone()) HArgumentsLength(elements); | 5752 result = New<HArgumentsLength>(elements); |
5789 } else { | 5753 } else { |
5790 // Number of arguments without receiver. | 5754 // Number of arguments without receiver. |
5791 int argument_count = environment()-> | 5755 int argument_count = environment()-> |
5792 arguments_environment()->parameter_count() - 1; | 5756 arguments_environment()->parameter_count() - 1; |
5793 result = new(zone()) HConstant(argument_count); | 5757 result = New<HConstant>(argument_count); |
5794 } | 5758 } |
5795 } else { | 5759 } else { |
5796 Push(graph()->GetArgumentsObject()); | 5760 Push(graph()->GetArgumentsObject()); |
5797 VisitForValue(expr->key()); | 5761 VisitForValue(expr->key()); |
5798 if (HasStackOverflow() || current_block() == NULL) return true; | 5762 if (HasStackOverflow() || current_block() == NULL) return true; |
5799 HValue* key = Pop(); | 5763 HValue* key = Pop(); |
5800 Drop(1); // Arguments object. | 5764 Drop(1); // Arguments object. |
5801 if (function_state()->outer() == NULL) { | 5765 if (function_state()->outer() == NULL) { |
5802 HInstruction* elements = Add<HArgumentsElements>(false); | 5766 HInstruction* elements = Add<HArgumentsElements>(false); |
5803 HInstruction* length = Add<HArgumentsLength>(elements); | 5767 HInstruction* length = Add<HArgumentsLength>(elements); |
(...skipping 23 matching lines...) Expand all Loading... |
5827 | 5791 |
5828 if (TryArgumentsAccess(expr)) return; | 5792 if (TryArgumentsAccess(expr)) return; |
5829 | 5793 |
5830 CHECK_ALIVE(VisitForValue(expr->obj())); | 5794 CHECK_ALIVE(VisitForValue(expr->obj())); |
5831 | 5795 |
5832 HInstruction* instr = NULL; | 5796 HInstruction* instr = NULL; |
5833 if (expr->IsStringLength()) { | 5797 if (expr->IsStringLength()) { |
5834 HValue* string = Pop(); | 5798 HValue* string = Pop(); |
5835 BuildCheckHeapObject(string); | 5799 BuildCheckHeapObject(string); |
5836 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 5800 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
5837 instr = HStringLength::New(zone(), string); | 5801 instr = NewUncasted<HStringLength>(string); |
5838 } else if (expr->IsStringAccess()) { | 5802 } else if (expr->IsStringAccess()) { |
5839 CHECK_ALIVE(VisitForValue(expr->key())); | 5803 CHECK_ALIVE(VisitForValue(expr->key())); |
5840 HValue* index = Pop(); | 5804 HValue* index = Pop(); |
5841 HValue* string = Pop(); | 5805 HValue* string = Pop(); |
5842 HValue* context = environment()->LookupContext(); | 5806 HValue* context = environment()->context(); |
5843 HInstruction* char_code = | 5807 HInstruction* char_code = |
5844 BuildStringCharCodeAt(context, string, index); | 5808 BuildStringCharCodeAt(string, index); |
5845 AddInstruction(char_code); | 5809 AddInstruction(char_code); |
5846 instr = HStringCharFromCode::New(zone(), context, char_code); | 5810 instr = HStringCharFromCode::New(zone(), context, char_code); |
5847 | 5811 |
5848 } else if (expr->IsFunctionPrototype()) { | 5812 } else if (expr->IsFunctionPrototype()) { |
5849 HValue* function = Pop(); | 5813 HValue* function = Pop(); |
5850 BuildCheckHeapObject(function); | 5814 BuildCheckHeapObject(function); |
5851 instr = new(zone()) HLoadFunctionPrototype(function); | 5815 instr = new(zone()) HLoadFunctionPrototype(function); |
5852 | 5816 |
5853 } else if (expr->key()->IsPropertyName()) { | 5817 } else if (expr->key()->IsPropertyName()) { |
5854 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5818 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5905 } | 5869 } |
5906 instr->set_position(expr->position()); | 5870 instr->set_position(expr->position()); |
5907 return ast_context()->ReturnInstruction(instr, expr->id()); | 5871 return ast_context()->ReturnInstruction(instr, expr->id()); |
5908 } | 5872 } |
5909 | 5873 |
5910 | 5874 |
5911 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 5875 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
5912 Handle<Map> receiver_map) { | 5876 Handle<Map> receiver_map) { |
5913 if (!holder.is_null()) { | 5877 if (!holder.is_null()) { |
5914 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 5878 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
5915 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info()); | 5879 Add<HCheckPrototypeMaps>(prototype, holder, top_info()); |
5916 } | 5880 } |
5917 } | 5881 } |
5918 | 5882 |
5919 | 5883 |
5920 void HOptimizedGraphBuilder::AddCheckConstantFunction( | 5884 void HOptimizedGraphBuilder::AddCheckConstantFunction( |
5921 Handle<JSObject> holder, | 5885 Handle<JSObject> holder, |
5922 HValue* receiver, | 5886 HValue* receiver, |
5923 Handle<Map> receiver_map) { | 5887 Handle<Map> receiver_map) { |
5924 // Constant functions have the nice property that the map will change if they | 5888 // Constant functions have the nice property that the map will change if they |
5925 // are overwritten. Therefore it is enough to check the map of the holder and | 5889 // are overwritten. Therefore it is enough to check the map of the holder and |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5974 Handle<Object> prototype(map->prototype(), isolate()); | 5938 Handle<Object> prototype(map->prototype(), isolate()); |
5975 for (int count = 1; count < types->length(); ++count) { | 5939 for (int count = 1; count < types->length(); ++count) { |
5976 Handle<Map> test_map(types->at(count)); | 5940 Handle<Map> test_map(types->at(count)); |
5977 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false; | 5941 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false; |
5978 if (test_map->prototype() != *prototype) return false; | 5942 if (test_map->prototype() != *prototype) return false; |
5979 } | 5943 } |
5980 | 5944 |
5981 if (!expr->ComputeTarget(map, name)) return false; | 5945 if (!expr->ComputeTarget(map, name)) return false; |
5982 | 5946 |
5983 BuildCheckHeapObject(receiver); | 5947 BuildCheckHeapObject(receiver); |
5984 AddInstruction(HCheckMaps::New(receiver, types, zone())); | 5948 Add<HCheckMaps>(receiver, types); |
5985 AddCheckPrototypeMaps(expr->holder(), map); | 5949 AddCheckPrototypeMaps(expr->holder(), map); |
5986 if (FLAG_trace_inlining) { | 5950 if (FLAG_trace_inlining) { |
5987 Handle<JSFunction> caller = current_info()->closure(); | 5951 Handle<JSFunction> caller = current_info()->closure(); |
5988 SmartArrayPointer<char> caller_name = | 5952 SmartArrayPointer<char> caller_name = |
5989 caller->shared()->DebugName()->ToCString(); | 5953 caller->shared()->DebugName()->ToCString(); |
5990 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 5954 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
5991 *name->ToCString(), *caller_name); | 5955 *name->ToCString(), *caller_name); |
5992 } | 5956 } |
5993 | 5957 |
5994 if (!TryInlineCall(expr)) { | 5958 if (!TryInlineCall(expr)) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6130 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6094 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6131 // know about and do not want to handle ones we've never seen. Otherwise | 6095 // know about and do not want to handle ones we've never seen. Otherwise |
6132 // use a generic IC. | 6096 // use a generic IC. |
6133 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6097 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6134 // Because the deopt may be the only path in the polymorphic call, make sure | 6098 // Because the deopt may be the only path in the polymorphic call, make sure |
6135 // that the environment stack matches the depth on deopt that it otherwise | 6099 // that the environment stack matches the depth on deopt that it otherwise |
6136 // would have had after a successful call. | 6100 // would have had after a successful call. |
6137 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); | 6101 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); |
6138 FinishExitWithHardDeoptimization(join); | 6102 FinishExitWithHardDeoptimization(join); |
6139 } else { | 6103 } else { |
6140 HValue* context = environment()->LookupContext(); | 6104 HValue* context = environment()->context(); |
6141 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6105 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
6142 call->set_position(expr->position()); | 6106 call->set_position(expr->position()); |
6143 PreProcessCall(call); | 6107 PreProcessCall(call); |
6144 | 6108 |
6145 if (join != NULL) { | 6109 if (join != NULL) { |
6146 AddInstruction(call); | 6110 AddInstruction(call); |
6147 if (!ast_context()->IsEffect()) Push(call); | 6111 if (!ast_context()->IsEffect()) Push(call); |
6148 current_block()->Goto(join); | 6112 current_block()->Goto(join); |
6149 } else { | 6113 } else { |
6150 return ast_context()->ReturnInstruction(call, expr->id()); | 6114 return ast_context()->ReturnInstruction(call, expr->id()); |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6396 Add<HSimulate>(return_id); | 6360 Add<HSimulate>(return_id); |
6397 current_block()->UpdateEnvironment(inner_env); | 6361 current_block()->UpdateEnvironment(inner_env); |
6398 HArgumentsObject* arguments_object = NULL; | 6362 HArgumentsObject* arguments_object = NULL; |
6399 | 6363 |
6400 // If the function uses arguments object create and bind one, also copy | 6364 // If the function uses arguments object create and bind one, also copy |
6401 // current arguments values to use them for materialization. | 6365 // current arguments values to use them for materialization. |
6402 if (function->scope()->arguments() != NULL) { | 6366 if (function->scope()->arguments() != NULL) { |
6403 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 6367 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
6404 HEnvironment* arguments_env = inner_env->arguments_environment(); | 6368 HEnvironment* arguments_env = inner_env->arguments_environment(); |
6405 int arguments_count = arguments_env->parameter_count(); | 6369 int arguments_count = arguments_env->parameter_count(); |
6406 arguments_object = Add<HArgumentsObject>(arguments_count, zone()); | 6370 arguments_object = Add<HArgumentsObject>(arguments_count); |
6407 inner_env->Bind(function->scope()->arguments(), arguments_object); | 6371 inner_env->Bind(function->scope()->arguments(), arguments_object); |
6408 for (int i = 0; i < arguments_count; i++) { | 6372 for (int i = 0; i < arguments_count; i++) { |
6409 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); | 6373 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
6410 } | 6374 } |
6411 } | 6375 } |
6412 | 6376 |
6413 HEnterInlined* enter_inlined = | 6377 HEnterInlined* enter_inlined = |
6414 Add<HEnterInlined>(target, arguments_count, function, | 6378 Add<HEnterInlined>(target, arguments_count, function, |
6415 function_state()->inlining_kind(), | 6379 function_state()->inlining_kind(), |
6416 function->scope()->arguments(), | 6380 function->scope()->arguments(), |
6417 arguments_object, undefined_receiver, zone()); | 6381 arguments_object, undefined_receiver); |
6418 function_state()->set_entry(enter_inlined); | 6382 function_state()->set_entry(enter_inlined); |
6419 | 6383 |
6420 VisitDeclarations(target_info.scope()->declarations()); | 6384 VisitDeclarations(target_info.scope()->declarations()); |
6421 VisitStatements(function->body()); | 6385 VisitStatements(function->body()); |
6422 if (HasStackOverflow()) { | 6386 if (HasStackOverflow()) { |
6423 // Bail out if the inline function did, as we cannot residualize a call | 6387 // Bail out if the inline function did, as we cannot residualize a call |
6424 // instead. | 6388 // instead. |
6425 TraceInline(target, caller, "inline graph construction failed"); | 6389 TraceInline(target, caller, "inline graph construction failed"); |
6426 target_shared->DisableOptimization("inlining bailed out"); | 6390 target_shared->DisableOptimization("inlining bailed out"); |
6427 inline_bailout_ = true; | 6391 inline_bailout_ = true; |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6598 case kMathRound: | 6562 case kMathRound: |
6599 case kMathFloor: | 6563 case kMathFloor: |
6600 case kMathAbs: | 6564 case kMathAbs: |
6601 case kMathSqrt: | 6565 case kMathSqrt: |
6602 case kMathLog: | 6566 case kMathLog: |
6603 case kMathSin: | 6567 case kMathSin: |
6604 case kMathCos: | 6568 case kMathCos: |
6605 case kMathTan: | 6569 case kMathTan: |
6606 if (expr->arguments()->length() == 1) { | 6570 if (expr->arguments()->length() == 1) { |
6607 HValue* argument = Pop(); | 6571 HValue* argument = Pop(); |
6608 HValue* context = environment()->LookupContext(); | 6572 HValue* context = environment()->context(); |
6609 Drop(1); // Receiver. | 6573 Drop(1); // Receiver. |
6610 HInstruction* op = | 6574 HInstruction* op = |
6611 HUnaryMathOperation::New(zone(), context, argument, id); | 6575 HUnaryMathOperation::New(zone(), context, argument, id); |
6612 op->set_position(expr->position()); | 6576 op->set_position(expr->position()); |
6613 if (drop_extra) Drop(1); // Optionally drop the function. | 6577 if (drop_extra) Drop(1); // Optionally drop the function. |
6614 ast_context()->ReturnInstruction(op, expr->id()); | 6578 ast_context()->ReturnInstruction(op, expr->id()); |
6615 return true; | 6579 return true; |
6616 } | 6580 } |
6617 break; | 6581 break; |
6618 case kMathImul: | 6582 case kMathImul: |
6619 if (expr->arguments()->length() == 2) { | 6583 if (expr->arguments()->length() == 2) { |
6620 HValue* right = Pop(); | 6584 HValue* right = Pop(); |
6621 HValue* left = Pop(); | 6585 HValue* left = Pop(); |
6622 Drop(1); // Receiver. | 6586 Drop(1); // Receiver. |
6623 HValue* context = environment()->LookupContext(); | 6587 HValue* context = environment()->context(); |
6624 HInstruction* op = HMul::NewImul(zone(), context, left, right); | 6588 HInstruction* op = HMul::NewImul(zone(), context, left, right); |
6625 if (drop_extra) Drop(1); // Optionally drop the function. | 6589 if (drop_extra) Drop(1); // Optionally drop the function. |
6626 ast_context()->ReturnInstruction(op, expr->id()); | 6590 ast_context()->ReturnInstruction(op, expr->id()); |
6627 return true; | 6591 return true; |
6628 } | 6592 } |
6629 break; | 6593 break; |
6630 default: | 6594 default: |
6631 // Not supported for inlining yet. | 6595 // Not supported for inlining yet. |
6632 break; | 6596 break; |
6633 } | 6597 } |
(...skipping 10 matching lines...) Expand all Loading... |
6644 // Try to inline calls like Math.* as operations in the calling function. | 6608 // Try to inline calls like Math.* as operations in the calling function. |
6645 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 6609 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
6646 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 6610 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
6647 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 6611 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
6648 switch (id) { | 6612 switch (id) { |
6649 case kStringCharCodeAt: | 6613 case kStringCharCodeAt: |
6650 case kStringCharAt: | 6614 case kStringCharAt: |
6651 if (argument_count == 2 && check_type == STRING_CHECK) { | 6615 if (argument_count == 2 && check_type == STRING_CHECK) { |
6652 HValue* index = Pop(); | 6616 HValue* index = Pop(); |
6653 HValue* string = Pop(); | 6617 HValue* string = Pop(); |
6654 HValue* context = environment()->LookupContext(); | 6618 HValue* context = environment()->context(); |
6655 ASSERT(!expr->holder().is_null()); | 6619 ASSERT(!expr->holder().is_null()); |
6656 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( | 6620 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck( |
6657 STRING_CHECK, expr->holder()->GetIsolate()), | 6621 STRING_CHECK, expr->holder()->GetIsolate()), |
6658 expr->holder(), zone(), top_info()); | 6622 expr->holder(), top_info()); |
6659 HInstruction* char_code = | 6623 HInstruction* char_code = |
6660 BuildStringCharCodeAt(context, string, index); | 6624 BuildStringCharCodeAt(string, index); |
6661 if (id == kStringCharCodeAt) { | 6625 if (id == kStringCharCodeAt) { |
6662 ast_context()->ReturnInstruction(char_code, expr->id()); | 6626 ast_context()->ReturnInstruction(char_code, expr->id()); |
6663 return true; | 6627 return true; |
6664 } | 6628 } |
6665 AddInstruction(char_code); | 6629 AddInstruction(char_code); |
6666 HInstruction* result = | 6630 HInstruction* result = |
6667 HStringCharFromCode::New(zone(), context, char_code); | 6631 HStringCharFromCode::New(zone(), context, char_code); |
6668 ast_context()->ReturnInstruction(result, expr->id()); | 6632 ast_context()->ReturnInstruction(result, expr->id()); |
6669 return true; | 6633 return true; |
6670 } | 6634 } |
6671 break; | 6635 break; |
6672 case kStringFromCharCode: | 6636 case kStringFromCharCode: |
6673 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6637 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6674 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6638 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6675 HValue* argument = Pop(); | 6639 HValue* argument = Pop(); |
6676 HValue* context = environment()->LookupContext(); | 6640 HValue* context = environment()->context(); |
6677 Drop(1); // Receiver. | 6641 Drop(1); // Receiver. |
6678 HInstruction* result = | 6642 HInstruction* result = |
6679 HStringCharFromCode::New(zone(), context, argument); | 6643 HStringCharFromCode::New(zone(), context, argument); |
6680 ast_context()->ReturnInstruction(result, expr->id()); | 6644 ast_context()->ReturnInstruction(result, expr->id()); |
6681 return true; | 6645 return true; |
6682 } | 6646 } |
6683 break; | 6647 break; |
6684 case kMathExp: | 6648 case kMathExp: |
6685 if (!FLAG_fast_math) break; | 6649 if (!FLAG_fast_math) break; |
6686 // Fall through if FLAG_fast_math. | 6650 // Fall through if FLAG_fast_math. |
6687 case kMathRound: | 6651 case kMathRound: |
6688 case kMathFloor: | 6652 case kMathFloor: |
6689 case kMathAbs: | 6653 case kMathAbs: |
6690 case kMathSqrt: | 6654 case kMathSqrt: |
6691 case kMathLog: | 6655 case kMathLog: |
6692 case kMathSin: | 6656 case kMathSin: |
6693 case kMathCos: | 6657 case kMathCos: |
6694 case kMathTan: | 6658 case kMathTan: |
6695 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 6659 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
6696 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6660 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6697 HValue* argument = Pop(); | 6661 HValue* argument = Pop(); |
6698 HValue* context = environment()->LookupContext(); | 6662 HValue* context = environment()->context(); |
6699 Drop(1); // Receiver. | 6663 Drop(1); // Receiver. |
6700 HInstruction* op = | 6664 HInstruction* op = |
6701 HUnaryMathOperation::New(zone(), context, argument, id); | 6665 HUnaryMathOperation::New(zone(), context, argument, id); |
6702 op->set_position(expr->position()); | 6666 op->set_position(expr->position()); |
6703 ast_context()->ReturnInstruction(op, expr->id()); | 6667 ast_context()->ReturnInstruction(op, expr->id()); |
6704 return true; | 6668 return true; |
6705 } | 6669 } |
6706 break; | 6670 break; |
6707 case kMathPow: | 6671 case kMathPow: |
6708 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6672 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6709 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6673 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6710 HValue* right = Pop(); | 6674 HValue* right = Pop(); |
6711 HValue* left = Pop(); | 6675 HValue* left = Pop(); |
6712 Pop(); // Pop receiver. | 6676 Pop(); // Pop receiver. |
6713 HValue* context = environment()->LookupContext(); | 6677 HValue* context = environment()->context(); |
6714 HInstruction* result = NULL; | 6678 HInstruction* result = NULL; |
6715 // Use sqrt() if exponent is 0.5 or -0.5. | 6679 // Use sqrt() if exponent is 0.5 or -0.5. |
6716 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 6680 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
6717 double exponent = HConstant::cast(right)->DoubleValue(); | 6681 double exponent = HConstant::cast(right)->DoubleValue(); |
6718 if (exponent == 0.5) { | 6682 if (exponent == 0.5) { |
6719 result = | 6683 result = |
6720 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 6684 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
6721 } else if (exponent == -0.5) { | 6685 } else if (exponent == -0.5) { |
6722 HValue* one = graph()->GetConstant1(); | 6686 HValue* one = graph()->GetConstant1(); |
6723 HInstruction* sqrt = | 6687 HInstruction* sqrt = |
6724 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 6688 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
6725 AddInstruction(sqrt); | 6689 AddInstruction(sqrt); |
6726 // MathPowHalf doesn't have side effects so there's no need for | 6690 // MathPowHalf doesn't have side effects so there's no need for |
6727 // an environment simulation here. | 6691 // an environment simulation here. |
6728 ASSERT(!sqrt->HasObservableSideEffects()); | 6692 ASSERT(!sqrt->HasObservableSideEffects()); |
6729 result = HDiv::New(zone(), context, one, sqrt); | 6693 result = HDiv::New(zone(), context, one, sqrt); |
6730 } else if (exponent == 2.0) { | 6694 } else if (exponent == 2.0) { |
6731 result = HMul::New(zone(), context, left, left); | 6695 result = HMul::New(zone(), context, left, left); |
6732 } | 6696 } |
6733 } else if (right->EqualsInteger32Constant(2)) { | 6697 } else if (right->EqualsInteger32Constant(2)) { |
6734 result = HMul::New(zone(), context, left, left); | 6698 result = HMul::New(zone(), context, left, left); |
6735 } | 6699 } |
6736 | 6700 |
6737 if (result == NULL) { | 6701 if (result == NULL) { |
6738 result = HPower::New(zone(), left, right); | 6702 result = HPower::New(zone(), context, left, right); |
6739 } | 6703 } |
6740 ast_context()->ReturnInstruction(result, expr->id()); | 6704 ast_context()->ReturnInstruction(result, expr->id()); |
6741 return true; | 6705 return true; |
6742 } | 6706 } |
6743 break; | 6707 break; |
6744 case kMathRandom: | 6708 case kMathRandom: |
6745 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 6709 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
6746 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6710 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6747 Drop(1); // Receiver. | 6711 Drop(1); // Receiver. |
6748 HValue* context = environment()->LookupContext(); | 6712 HGlobalObject* global_object = Add<HGlobalObject>(); |
6749 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
6750 HRandom* result = new(zone()) HRandom(global_object); | 6713 HRandom* result = new(zone()) HRandom(global_object); |
6751 ast_context()->ReturnInstruction(result, expr->id()); | 6714 ast_context()->ReturnInstruction(result, expr->id()); |
6752 return true; | 6715 return true; |
6753 } | 6716 } |
6754 break; | 6717 break; |
6755 case kMathMax: | 6718 case kMathMax: |
6756 case kMathMin: | 6719 case kMathMin: |
6757 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6720 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6758 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6721 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6759 HValue* right = Pop(); | 6722 HValue* right = Pop(); |
6760 HValue* left = Pop(); | 6723 HValue* left = Pop(); |
6761 Drop(1); // Receiver. | 6724 Drop(1); // Receiver. |
6762 HValue* context = environment()->LookupContext(); | 6725 HValue* context = environment()->context(); |
6763 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin | 6726 HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin |
6764 : HMathMinMax::kMathMax; | 6727 : HMathMinMax::kMathMax; |
6765 HInstruction* result = | 6728 HInstruction* result = |
6766 HMathMinMax::New(zone(), context, left, right, op); | 6729 HMathMinMax::New(zone(), context, left, right, op); |
6767 ast_context()->ReturnInstruction(result, expr->id()); | 6730 ast_context()->ReturnInstruction(result, expr->id()); |
6768 return true; | 6731 return true; |
6769 } | 6732 } |
6770 break; | 6733 break; |
6771 case kMathImul: | 6734 case kMathImul: |
6772 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 6735 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
6773 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6736 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6774 HValue* right = Pop(); | 6737 HValue* right = Pop(); |
6775 HValue* left = Pop(); | 6738 HValue* left = Pop(); |
6776 Drop(1); // Receiver. | 6739 Drop(1); // Receiver. |
6777 HValue* context = environment()->LookupContext(); | 6740 HValue* context = environment()->context(); |
6778 HInstruction* result = HMul::NewImul(zone(), context, left, right); | 6741 HInstruction* result = HMul::NewImul(zone(), context, left, right); |
6779 ast_context()->ReturnInstruction(result, expr->id()); | 6742 ast_context()->ReturnInstruction(result, expr->id()); |
6780 return true; | 6743 return true; |
6781 } | 6744 } |
6782 break; | 6745 break; |
6783 default: | 6746 default: |
6784 // Not yet supported for inlining. | 6747 // Not yet supported for inlining. |
6785 break; | 6748 break; |
6786 } | 6749 } |
6787 return false; | 6750 return false; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6851 | 6814 |
6852 Handle<JSFunction> known_function; | 6815 Handle<JSFunction> known_function; |
6853 if (function->IsConstant()) { | 6816 if (function->IsConstant()) { |
6854 HConstant* constant_function = HConstant::cast(function); | 6817 HConstant* constant_function = HConstant::cast(function); |
6855 known_function = Handle<JSFunction>::cast(constant_function->handle()); | 6818 known_function = Handle<JSFunction>::cast(constant_function->handle()); |
6856 int args_count = arguments_count - 1; // Excluding receiver. | 6819 int args_count = arguments_count - 1; // Excluding receiver. |
6857 if (TryInlineApply(known_function, expr, args_count)) return true; | 6820 if (TryInlineApply(known_function, expr, args_count)) return true; |
6858 } | 6821 } |
6859 | 6822 |
6860 Drop(arguments_count - 1); | 6823 Drop(arguments_count - 1); |
6861 PushAndAdd(new(zone()) HPushArgument(Pop())); | 6824 PushAndAdd(New<HPushArgument>(Pop())); |
6862 for (int i = 1; i < arguments_count; i++) { | 6825 for (int i = 1; i < arguments_count; i++) { |
6863 PushAndAdd(new(zone()) HPushArgument(arguments_values->at(i))); | 6826 PushAndAdd(New<HPushArgument>(arguments_values->at(i))); |
6864 } | 6827 } |
6865 | 6828 |
6866 HValue* context = environment()->LookupContext(); | 6829 HValue* context = environment()->context(); |
6867 HInvokeFunction* call = new(zone()) HInvokeFunction( | 6830 HInvokeFunction* call = new(zone()) HInvokeFunction( |
6868 context, | 6831 context, |
6869 function, | 6832 function, |
6870 known_function, | 6833 known_function, |
6871 arguments_count); | 6834 arguments_count); |
6872 Drop(arguments_count); | 6835 Drop(arguments_count); |
6873 call->set_position(expr->position()); | 6836 call->set_position(expr->position()); |
6874 ast_context()->ReturnInstruction(call, expr->id()); | 6837 ast_context()->ReturnInstruction(call, expr->id()); |
6875 return true; | 6838 return true; |
6876 } | 6839 } |
(...skipping 16 matching lines...) Expand all Loading... |
6893 | 6856 |
6894 CHECK_ALIVE(VisitForValue(prop->key())); | 6857 CHECK_ALIVE(VisitForValue(prop->key())); |
6895 // Push receiver and key like the non-optimized code generator expects it. | 6858 // Push receiver and key like the non-optimized code generator expects it. |
6896 HValue* key = Pop(); | 6859 HValue* key = Pop(); |
6897 HValue* receiver = Pop(); | 6860 HValue* receiver = Pop(); |
6898 Push(key); | 6861 Push(key); |
6899 Push(receiver); | 6862 Push(receiver); |
6900 | 6863 |
6901 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 6864 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
6902 | 6865 |
6903 HValue* context = environment()->LookupContext(); | 6866 HValue* context = environment()->context(); |
6904 call = new(zone()) HCallKeyed(context, key, argument_count); | 6867 call = new(zone()) HCallKeyed(context, key, argument_count); |
6905 call->set_position(expr->position()); | 6868 call->set_position(expr->position()); |
6906 Drop(argument_count + 1); // 1 is the key. | 6869 Drop(argument_count + 1); // 1 is the key. |
6907 return ast_context()->ReturnInstruction(call, expr->id()); | 6870 return ast_context()->ReturnInstruction(call, expr->id()); |
6908 } | 6871 } |
6909 | 6872 |
6910 // Named function call. | 6873 // Named function call. |
6911 if (TryCallApply(expr)) return; | 6874 if (TryCallApply(expr)) return; |
6912 | 6875 |
6913 CHECK_ALIVE(VisitForValue(prop->obj())); | 6876 CHECK_ALIVE(VisitForValue(prop->obj())); |
(...skipping 23 matching lines...) Expand all Loading... |
6937 PrintF("\n"); | 6900 PrintF("\n"); |
6938 } | 6901 } |
6939 return; | 6902 return; |
6940 } | 6903 } |
6941 | 6904 |
6942 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 6905 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
6943 expr->check_type() != RECEIVER_MAP_CHECK) { | 6906 expr->check_type() != RECEIVER_MAP_CHECK) { |
6944 // When the target has a custom call IC generator, use the IC, | 6907 // When the target has a custom call IC generator, use the IC, |
6945 // because it is likely to generate better code. Also use the IC | 6908 // because it is likely to generate better code. Also use the IC |
6946 // when a primitive receiver check is required. | 6909 // when a primitive receiver check is required. |
6947 HValue* context = environment()->LookupContext(); | 6910 HValue* context = environment()->context(); |
6948 call = PreProcessCall( | 6911 call = PreProcessCall( |
6949 new(zone()) HCallNamed(context, name, argument_count)); | 6912 new(zone()) HCallNamed(context, name, argument_count)); |
6950 } else { | 6913 } else { |
6951 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 6914 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
6952 | 6915 |
6953 if (TryInlineCall(expr)) return; | 6916 if (TryInlineCall(expr)) return; |
6954 call = PreProcessCall( | 6917 call = PreProcessCall( |
6955 new(zone()) HCallConstantFunction(expr->target(), | 6918 new(zone()) HCallConstantFunction(expr->target(), |
6956 argument_count)); | 6919 argument_count)); |
6957 } | 6920 } |
6958 } else if (types != NULL && types->length() > 1) { | 6921 } else if (types != NULL && types->length() > 1) { |
6959 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 6922 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
6960 HandlePolymorphicCallNamed(expr, receiver, types, name); | 6923 HandlePolymorphicCallNamed(expr, receiver, types, name); |
6961 return; | 6924 return; |
6962 | 6925 |
6963 } else { | 6926 } else { |
6964 HValue* context = environment()->LookupContext(); | 6927 HValue* context = environment()->context(); |
6965 call = PreProcessCall( | 6928 call = PreProcessCall( |
6966 new(zone()) HCallNamed(context, name, argument_count)); | 6929 new(zone()) HCallNamed(context, name, argument_count)); |
6967 } | 6930 } |
6968 | 6931 |
6969 } else { | 6932 } else { |
6970 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 6933 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
6971 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 6934 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
6972 return Bailout("possible direct call to eval"); | 6935 return Bailout("possible direct call to eval"); |
6973 } | 6936 } |
6974 | 6937 |
6975 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 6938 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
6976 if (global_call) { | 6939 if (global_call) { |
6977 Variable* var = proxy->var(); | 6940 Variable* var = proxy->var(); |
6978 bool known_global_function = false; | 6941 bool known_global_function = false; |
6979 // If there is a global property cell for the name at compile time and | 6942 // If there is a global property cell for the name at compile time and |
6980 // access check is not enabled we assume that the function will not change | 6943 // access check is not enabled we assume that the function will not change |
6981 // and generate optimized code for calling the function. | 6944 // and generate optimized code for calling the function. |
6982 LookupResult lookup(isolate()); | 6945 LookupResult lookup(isolate()); |
6983 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 6946 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
6984 if (type == kUseCell && | 6947 if (type == kUseCell && |
6985 !current_info()->global_object()->IsAccessCheckNeeded()) { | 6948 !current_info()->global_object()->IsAccessCheckNeeded()) { |
6986 Handle<GlobalObject> global(current_info()->global_object()); | 6949 Handle<GlobalObject> global(current_info()->global_object()); |
6987 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 6950 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
6988 } | 6951 } |
6989 if (known_global_function) { | 6952 if (known_global_function) { |
6990 // Push the global object instead of the global receiver because | 6953 // Push the global object instead of the global receiver because |
6991 // code generated by the full code generator expects it. | 6954 // code generated by the full code generator expects it. |
6992 HValue* context = environment()->LookupContext(); | 6955 HValue* context = environment()->context(); |
6993 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 6956 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
6994 PushAndAdd(global_object); | 6957 PushAndAdd(global_object); |
6995 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 6958 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
6996 | 6959 |
6997 CHECK_ALIVE(VisitForValue(expr->expression())); | 6960 CHECK_ALIVE(VisitForValue(expr->expression())); |
6998 HValue* function = Pop(); | 6961 HValue* function = Pop(); |
6999 Add<HCheckFunction>(function, expr->target()); | 6962 Add<HCheckFunction>(function, expr->target()); |
7000 | 6963 |
7001 // Replace the global object with the global receiver. | 6964 // Replace the global object with the global receiver. |
7002 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); | 6965 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); |
(...skipping 13 matching lines...) Expand all Loading... |
7016 } | 6979 } |
7017 if (TryInlineCall(expr)) return; | 6980 if (TryInlineCall(expr)) return; |
7018 | 6981 |
7019 if (expr->target().is_identical_to(current_info()->closure())) { | 6982 if (expr->target().is_identical_to(current_info()->closure())) { |
7020 graph()->MarkRecursive(); | 6983 graph()->MarkRecursive(); |
7021 } | 6984 } |
7022 | 6985 |
7023 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { | 6986 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
7024 // When the target has a custom call IC generator, use the IC, | 6987 // When the target has a custom call IC generator, use the IC, |
7025 // because it is likely to generate better code. | 6988 // because it is likely to generate better code. |
7026 HValue* context = environment()->LookupContext(); | 6989 HValue* context = environment()->context(); |
7027 call = PreProcessCall( | 6990 call = PreProcessCall( |
7028 new(zone()) HCallNamed(context, var->name(), argument_count)); | 6991 new(zone()) HCallNamed(context, var->name(), argument_count)); |
7029 } else { | 6992 } else { |
7030 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 6993 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
7031 argument_count)); | 6994 argument_count)); |
7032 } | 6995 } |
7033 } else { | 6996 } else { |
7034 HValue* context = environment()->LookupContext(); | 6997 HGlobalObject* receiver = Add<HGlobalObject>(); |
7035 HGlobalObject* receiver = Add<HGlobalObject>(context); | 6998 PushAndAdd(New<HPushArgument>(receiver)); |
7036 PushAndAdd(new(zone()) HPushArgument(receiver)); | |
7037 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 6999 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7038 | 7000 |
7039 call = new(zone()) HCallGlobal(context, var->name(), argument_count); | 7001 call = New<HCallGlobal>(var->name(), argument_count); |
7040 Drop(argument_count); | 7002 Drop(argument_count); |
7041 } | 7003 } |
7042 | 7004 |
7043 } else if (expr->IsMonomorphic()) { | 7005 } else if (expr->IsMonomorphic()) { |
7044 // The function is on the stack in the unoptimized code during | 7006 // The function is on the stack in the unoptimized code during |
7045 // evaluation of the arguments. | 7007 // evaluation of the arguments. |
7046 CHECK_ALIVE(VisitForValue(expr->expression())); | 7008 CHECK_ALIVE(VisitForValue(expr->expression())); |
7047 HValue* function = Top(); | 7009 HValue* function = Top(); |
7048 HValue* context = environment()->LookupContext(); | 7010 HGlobalObject* global = Add<HGlobalObject>(); |
7049 HGlobalObject* global = Add<HGlobalObject>(context); | 7011 HGlobalReceiver* receiver = New<HGlobalReceiver>(global); |
7050 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); | |
7051 PushAndAdd(receiver); | 7012 PushAndAdd(receiver); |
7052 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7013 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7053 Add<HCheckFunction>(function, expr->target()); | 7014 Add<HCheckFunction>(function, expr->target()); |
7054 | 7015 |
7055 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. | 7016 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. |
7056 if (FLAG_trace_inlining) { | 7017 if (FLAG_trace_inlining) { |
7057 PrintF("Inlining builtin "); | 7018 PrintF("Inlining builtin "); |
7058 expr->target()->ShortPrint(); | 7019 expr->target()->ShortPrint(); |
7059 PrintF("\n"); | 7020 PrintF("\n"); |
7060 } | 7021 } |
7061 return; | 7022 return; |
7062 } | 7023 } |
7063 | 7024 |
7064 if (TryInlineCall(expr, true)) { // Drop function from environment. | 7025 if (TryInlineCall(expr, true)) { // Drop function from environment. |
7065 return; | 7026 return; |
7066 } else { | 7027 } else { |
7067 call = PreProcessCall( | 7028 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), |
7068 new(zone()) HInvokeFunction(context, | 7029 argument_count)); |
7069 function, | |
7070 expr->target(), | |
7071 argument_count)); | |
7072 Drop(1); // The function. | 7030 Drop(1); // The function. |
7073 } | 7031 } |
7074 | 7032 |
7075 } else { | 7033 } else { |
7076 CHECK_ALIVE(VisitForValue(expr->expression())); | 7034 CHECK_ALIVE(VisitForValue(expr->expression())); |
7077 HValue* function = Top(); | 7035 HValue* function = Top(); |
7078 HValue* context = environment()->LookupContext(); | 7036 HGlobalObject* global_object = Add<HGlobalObject>(); |
7079 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
7080 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); | 7037 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); |
7081 PushAndAdd(new(zone()) HPushArgument(receiver)); | 7038 PushAndAdd(New<HPushArgument>(receiver)); |
7082 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7039 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7083 | 7040 |
7084 call = new(zone()) HCallFunction(context, function, argument_count); | 7041 call = New<HCallFunction>(function, argument_count); |
7085 Drop(argument_count + 1); | 7042 Drop(argument_count + 1); |
7086 } | 7043 } |
7087 } | 7044 } |
7088 | 7045 |
7089 call->set_position(expr->position()); | 7046 call->set_position(expr->position()); |
7090 return ast_context()->ReturnInstruction(call, expr->id()); | 7047 return ast_context()->ReturnInstruction(call, expr->id()); |
7091 } | 7048 } |
7092 | 7049 |
7093 | 7050 |
7094 // Checks whether allocation using the given constructor can be inlined. | 7051 // Checks whether allocation using the given constructor can be inlined. |
7095 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7052 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7096 return constructor->has_initial_map() && | 7053 return constructor->has_initial_map() && |
7097 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7054 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7098 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7055 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
7099 constructor->initial_map()->InitialPropertiesLength() == 0; | 7056 constructor->initial_map()->InitialPropertiesLength() == 0; |
7100 } | 7057 } |
7101 | 7058 |
7102 | 7059 |
7103 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7060 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
7104 ASSERT(!HasStackOverflow()); | 7061 ASSERT(!HasStackOverflow()); |
7105 ASSERT(current_block() != NULL); | 7062 ASSERT(current_block() != NULL); |
7106 ASSERT(current_block()->HasPredecessor()); | 7063 ASSERT(current_block()->HasPredecessor()); |
7107 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7064 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7108 HValue* context = environment()->LookupContext(); | 7065 HValue* context = environment()->context(); |
7109 Factory* factory = isolate()->factory(); | 7066 Factory* factory = isolate()->factory(); |
7110 | 7067 |
7111 if (FLAG_inline_construct && | 7068 if (FLAG_inline_construct && |
7112 expr->IsMonomorphic() && | 7069 expr->IsMonomorphic() && |
7113 IsAllocationInlineable(expr->target())) { | 7070 IsAllocationInlineable(expr->target())) { |
7114 // The constructor function is on the stack in the unoptimized code | 7071 // The constructor function is on the stack in the unoptimized code |
7115 // during evaluation of the arguments. | 7072 // during evaluation of the arguments. |
7116 CHECK_ALIVE(VisitForValue(expr->expression())); | 7073 CHECK_ALIVE(VisitForValue(expr->expression())); |
7117 HValue* function = Top(); | 7074 HValue* function = Top(); |
7118 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7075 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
(...skipping 10 matching lines...) Expand all Loading... |
7129 ASSERT(constructor->has_initial_map()); | 7086 ASSERT(constructor->has_initial_map()); |
7130 Handle<Map> initial_map(constructor->initial_map()); | 7087 Handle<Map> initial_map(constructor->initial_map()); |
7131 int instance_size = initial_map->instance_size(); | 7088 int instance_size = initial_map->instance_size(); |
7132 ASSERT(initial_map->InitialPropertiesLength() == 0); | 7089 ASSERT(initial_map->InitialPropertiesLength() == 0); |
7133 | 7090 |
7134 // Allocate an instance of the implicit receiver object. | 7091 // Allocate an instance of the implicit receiver object. |
7135 HValue* size_in_bytes = Add<HConstant>(instance_size); | 7092 HValue* size_in_bytes = Add<HConstant>(instance_size); |
7136 bool pretenure = FLAG_pretenuring_call_new && | 7093 bool pretenure = FLAG_pretenuring_call_new && |
7137 isolate()->heap()->ShouldGloballyPretenure(); | 7094 isolate()->heap()->ShouldGloballyPretenure(); |
7138 HAllocate* receiver = | 7095 HAllocate* receiver = |
7139 Add<HAllocate>(context, size_in_bytes, HType::JSObject(), pretenure); | 7096 Add<HAllocate>(size_in_bytes, HType::JSObject(), pretenure); |
7140 receiver->set_known_initial_map(initial_map); | 7097 receiver->set_known_initial_map(initial_map); |
7141 | 7098 |
7142 // Load the initial map from the constructor. | 7099 // Load the initial map from the constructor. |
7143 HValue* constructor_value = Add<HConstant>(constructor); | 7100 HValue* constructor_value = Add<HConstant>(constructor); |
7144 HValue* initial_map_value = | 7101 HValue* initial_map_value = |
7145 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | 7102 Add<HLoadNamedField>(constructor_value, HObjectAccess::ForJSObjectOffset( |
7146 JSFunction::kPrototypeOrInitialMapOffset)); | 7103 JSFunction::kPrototypeOrInitialMapOffset)); |
7147 | 7104 |
7148 // Initialize map and fields of the newly allocated object. | 7105 // Initialize map and fields of the newly allocated object. |
7149 { NoObservableSideEffectsScope no_effects(this); | 7106 { NoObservableSideEffectsScope no_effects(this); |
7150 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 7107 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
7151 AddStore(receiver, | 7108 Add<HStoreNamedField>(receiver, |
7152 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | 7109 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), |
7153 initial_map_value); | 7110 initial_map_value); |
7154 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); | 7111 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); |
7155 AddStore(receiver, | 7112 Add<HStoreNamedField>(receiver, |
7156 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | 7113 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), |
7157 empty_fixed_array); | 7114 empty_fixed_array); |
7158 AddStore(receiver, | 7115 Add<HStoreNamedField>(receiver, |
7159 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | 7116 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), |
7160 empty_fixed_array); | 7117 empty_fixed_array); |
7161 if (initial_map->inobject_properties() != 0) { | 7118 if (initial_map->inobject_properties() != 0) { |
7162 HConstant* undefined = graph()->GetConstantUndefined(); | 7119 HConstant* undefined = graph()->GetConstantUndefined(); |
7163 for (int i = 0; i < initial_map->inobject_properties(); i++) { | 7120 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
7164 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | 7121 int property_offset = JSObject::kHeaderSize + i * kPointerSize; |
7165 AddStore(receiver, | 7122 Add<HStoreNamedField>(receiver, |
7166 HObjectAccess::ForJSObjectOffset(property_offset), | 7123 HObjectAccess::ForJSObjectOffset(property_offset), |
7167 undefined); | 7124 undefined); |
7168 } | 7125 } |
7169 } | 7126 } |
7170 } | 7127 } |
7171 | 7128 |
7172 // Replace the constructor function with a newly allocated receiver using | 7129 // Replace the constructor function with a newly allocated receiver using |
7173 // the index of the receiver from the top of the expression stack. | 7130 // the index of the receiver from the top of the expression stack. |
7174 const int receiver_index = argument_count - 1; | 7131 const int receiver_index = argument_count - 1; |
7175 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 7132 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
7176 environment()->SetExpressionStackAt(receiver_index, receiver); | 7133 environment()->SetExpressionStackAt(receiver_index, receiver); |
7177 | 7134 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7255 ASSERT(static_cast<size_t>(lookup_index) < | 7212 ASSERT(static_cast<size_t>(lookup_index) < |
7256 ARRAY_SIZE(kInlineFunctionGenerators)); | 7213 ARRAY_SIZE(kInlineFunctionGenerators)); |
7257 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 7214 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
7258 | 7215 |
7259 // Call the inline code generator using the pointer-to-member. | 7216 // Call the inline code generator using the pointer-to-member. |
7260 (this->*generator)(expr); | 7217 (this->*generator)(expr); |
7261 } else { | 7218 } else { |
7262 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 7219 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
7263 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7220 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7264 | 7221 |
7265 HValue* context = environment()->LookupContext(); | |
7266 Handle<String> name = expr->name(); | 7222 Handle<String> name = expr->name(); |
7267 int argument_count = expr->arguments()->length(); | 7223 int argument_count = expr->arguments()->length(); |
7268 HCallRuntime* call = | 7224 HCallRuntime* call = New<HCallRuntime>(name, function, |
7269 new(zone()) HCallRuntime(context, name, function, argument_count); | 7225 argument_count); |
7270 Drop(argument_count); | 7226 Drop(argument_count); |
7271 return ast_context()->ReturnInstruction(call, expr->id()); | 7227 return ast_context()->ReturnInstruction(call, expr->id()); |
7272 } | 7228 } |
7273 } | 7229 } |
7274 | 7230 |
7275 | 7231 |
7276 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 7232 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
7277 ASSERT(!HasStackOverflow()); | 7233 ASSERT(!HasStackOverflow()); |
7278 ASSERT(current_block() != NULL); | 7234 ASSERT(current_block() != NULL); |
7279 ASSERT(current_block()->HasPredecessor()); | 7235 ASSERT(current_block()->HasPredecessor()); |
(...skipping 10 matching lines...) Expand all Loading... |
7290 | 7246 |
7291 | 7247 |
7292 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { | 7248 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { |
7293 Property* prop = expr->expression()->AsProperty(); | 7249 Property* prop = expr->expression()->AsProperty(); |
7294 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7250 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7295 if (prop != NULL) { | 7251 if (prop != NULL) { |
7296 CHECK_ALIVE(VisitForValue(prop->obj())); | 7252 CHECK_ALIVE(VisitForValue(prop->obj())); |
7297 CHECK_ALIVE(VisitForValue(prop->key())); | 7253 CHECK_ALIVE(VisitForValue(prop->key())); |
7298 HValue* key = Pop(); | 7254 HValue* key = Pop(); |
7299 HValue* obj = Pop(); | 7255 HValue* obj = Pop(); |
7300 HValue* context = environment()->LookupContext(); | 7256 HValue* function = AddLoadJSBuiltin(Builtins::DELETE); |
7301 HValue* function = AddLoadJSBuiltin(Builtins::DELETE, context); | |
7302 Add<HPushArgument>(obj); | 7257 Add<HPushArgument>(obj); |
7303 Add<HPushArgument>(key); | 7258 Add<HPushArgument>(key); |
7304 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); | 7259 Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag())); |
7305 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 7260 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
7306 // even though we are certain to pass the correct number of arguments here. | 7261 // even though we are certain to pass the correct number of arguments here. |
7307 HInstruction* instr = new(zone()) HInvokeFunction(context, function, 3); | 7262 HInstruction* instr = New<HInvokeFunction>(function, 3); |
7308 return ast_context()->ReturnInstruction(instr, expr->id()); | 7263 return ast_context()->ReturnInstruction(instr, expr->id()); |
7309 } else if (proxy != NULL) { | 7264 } else if (proxy != NULL) { |
7310 Variable* var = proxy->var(); | 7265 Variable* var = proxy->var(); |
7311 if (var->IsUnallocated()) { | 7266 if (var->IsUnallocated()) { |
7312 Bailout("delete with global variable"); | 7267 Bailout("delete with global variable"); |
7313 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 7268 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
7314 // Result of deleting non-global variables is false. 'this' is not | 7269 // Result of deleting non-global variables is false. 'this' is not |
7315 // really a variable, though we implement it as one. The | 7270 // really a variable, though we implement it as one. The |
7316 // subexpression does not have side effects. | 7271 // subexpression does not have side effects. |
7317 HValue* value = var->is_this() | 7272 HValue* value = var->is_this() |
(...skipping 14 matching lines...) Expand all Loading... |
7332 | 7287 |
7333 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7288 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { |
7334 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7289 CHECK_ALIVE(VisitForEffect(expr->expression())); |
7335 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7290 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
7336 } | 7291 } |
7337 | 7292 |
7338 | 7293 |
7339 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7294 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
7340 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7295 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
7341 HValue* value = Pop(); | 7296 HValue* value = Pop(); |
7342 HValue* context = environment()->LookupContext(); | 7297 HValue* context = environment()->context(); |
7343 HInstruction* instr = new(zone()) HTypeof(context, value); | 7298 HInstruction* instr = new(zone()) HTypeof(context, value); |
7344 return ast_context()->ReturnInstruction(instr, expr->id()); | 7299 return ast_context()->ReturnInstruction(instr, expr->id()); |
7345 } | 7300 } |
7346 | 7301 |
7347 | 7302 |
7348 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 7303 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
7349 CHECK_ALIVE(VisitForValue(expr->expression())); | 7304 CHECK_ALIVE(VisitForValue(expr->expression())); |
7350 Handle<Type> operand_type = expr->expression()->bounds().lower; | 7305 Handle<Type> operand_type = expr->expression()->bounds().lower; |
7351 HValue* value = TruncateToNumber(Pop(), &operand_type); | 7306 HValue* value = TruncateToNumber(Pop(), &operand_type); |
7352 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); | 7307 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7429 } | 7384 } |
7430 Push(number_input); | 7385 Push(number_input); |
7431 } | 7386 } |
7432 | 7387 |
7433 // The addition has no side effects, so we do not need | 7388 // The addition has no side effects, so we do not need |
7434 // to simulate the expression stack after this instruction. | 7389 // to simulate the expression stack after this instruction. |
7435 // Any later failures deopt to the load of the input or earlier. | 7390 // Any later failures deopt to the load of the input or earlier. |
7436 HConstant* delta = (expr->op() == Token::INC) | 7391 HConstant* delta = (expr->op() == Token::INC) |
7437 ? graph()->GetConstant1() | 7392 ? graph()->GetConstant1() |
7438 : graph()->GetConstantMinus1(); | 7393 : graph()->GetConstantMinus1(); |
7439 HValue* context = environment()->LookupContext(); | 7394 HInstruction* instr = Add<HAdd>(Top(), delta); |
7440 HInstruction* instr = HAdd::New(zone(), context, Top(), delta); | |
7441 instr->SetFlag(HInstruction::kCannotBeTagged); | 7395 instr->SetFlag(HInstruction::kCannotBeTagged); |
7442 instr->ClearAllSideEffects(); | 7396 instr->ClearAllSideEffects(); |
7443 AddInstruction(instr); | |
7444 return instr; | 7397 return instr; |
7445 } | 7398 } |
7446 | 7399 |
7447 | 7400 |
7448 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7401 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7449 ASSERT(!HasStackOverflow()); | 7402 ASSERT(!HasStackOverflow()); |
7450 ASSERT(current_block() != NULL); | 7403 ASSERT(current_block() != NULL); |
7451 ASSERT(current_block()->HasPredecessor()); | 7404 ASSERT(current_block()->HasPredecessor()); |
7452 Expression* target = expr->expression(); | 7405 Expression* target = expr->expression(); |
7453 VariableProxy* proxy = target->AsVariableProxy(); | 7406 VariableProxy* proxy = target->AsVariableProxy(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7598 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7551 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7599 } | 7552 } |
7600 } | 7553 } |
7601 | 7554 |
7602 Drop(returns_original_input ? 2 : 1); | 7555 Drop(returns_original_input ? 2 : 1); |
7603 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7556 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
7604 } | 7557 } |
7605 | 7558 |
7606 | 7559 |
7607 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7560 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
7608 HValue* context, | |
7609 HValue* string, | 7561 HValue* string, |
7610 HValue* index) { | 7562 HValue* index) { |
7611 if (string->IsConstant() && index->IsConstant()) { | 7563 if (string->IsConstant() && index->IsConstant()) { |
7612 HConstant* c_string = HConstant::cast(string); | 7564 HConstant* c_string = HConstant::cast(string); |
7613 HConstant* c_index = HConstant::cast(index); | 7565 HConstant* c_index = HConstant::cast(index); |
7614 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 7566 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
7615 int32_t i = c_index->NumberValueAsInteger32(); | 7567 int32_t i = c_index->NumberValueAsInteger32(); |
7616 Handle<String> s = c_string->StringValue(); | 7568 Handle<String> s = c_string->StringValue(); |
7617 if (i < 0 || i >= s->length()) { | 7569 if (i < 0 || i >= s->length()) { |
7618 return new(zone()) HConstant(OS::nan_value()); | 7570 return New<HConstant>(OS::nan_value()); |
7619 } | 7571 } |
7620 return new(zone()) HConstant(s->Get(i)); | 7572 return New<HConstant>(s->Get(i)); |
7621 } | 7573 } |
7622 } | 7574 } |
7623 BuildCheckHeapObject(string); | 7575 BuildCheckHeapObject(string); |
7624 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 7576 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
7625 HInstruction* length = HStringLength::New(zone(), string); | 7577 HInstruction* length = Add<HStringLength>(string); |
7626 AddInstruction(length); | |
7627 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | 7578 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
7628 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 7579 return New<HStringCharCodeAt>(string, checked_index); |
7629 } | 7580 } |
7630 | 7581 |
7631 | 7582 |
7632 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 7583 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
7633 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 7584 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
7634 HValue* const32_minus_sa) { | 7585 HValue* const32_minus_sa) { |
7635 if (!const32_minus_sa->IsSub()) return false; | 7586 if (!const32_minus_sa->IsSub()) return false; |
7636 HSub* sub = HSub::cast(const32_minus_sa); | 7587 HSub* sub = HSub::cast(const32_minus_sa); |
7637 if (sa != sub->right()) return false; | 7588 if (sa != sub->right()) return false; |
7638 HValue* const32 = sub->left(); | 7589 HValue* const32 = sub->left(); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7707 // tagged representation later on. | 7658 // tagged representation later on. |
7708 if (expected_type->Is(Type::Oddball())) { | 7659 if (expected_type->Is(Type::Oddball())) { |
7709 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to | 7660 // TODO(olivf) The BinaryOpStub only records undefined. It might pay off to |
7710 // also record booleans and convert them to 0/1 here. | 7661 // also record booleans and convert them to 0/1 here. |
7711 IfBuilder if_nan(this); | 7662 IfBuilder if_nan(this); |
7712 if_nan.If<HCompareObjectEqAndBranch>(value, | 7663 if_nan.If<HCompareObjectEqAndBranch>(value, |
7713 graph()->GetConstantUndefined()); | 7664 graph()->GetConstantUndefined()); |
7714 if_nan.Then(); | 7665 if_nan.Then(); |
7715 if_nan.ElseDeopt(); | 7666 if_nan.ElseDeopt(); |
7716 if_nan.End(); | 7667 if_nan.End(); |
7717 return Add<HConstant>(OS::nan_value(), Representation::Double()); | 7668 return Add<HConstant>(OS::nan_value()); |
7718 } | 7669 } |
7719 | 7670 |
7720 return value; | 7671 return value; |
7721 } | 7672 } |
7722 | 7673 |
7723 | 7674 |
7724 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7675 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7725 BinaryOperation* expr, | 7676 BinaryOperation* expr, |
7726 HValue* left, | 7677 HValue* left, |
7727 HValue* right) { | 7678 HValue* right) { |
7728 HValue* context = environment()->LookupContext(); | 7679 HValue* context = environment()->context(); |
7729 Handle<Type> left_type = expr->left()->bounds().lower; | 7680 Handle<Type> left_type = expr->left()->bounds().lower; |
7730 Handle<Type> right_type = expr->right()->bounds().lower; | 7681 Handle<Type> right_type = expr->right()->bounds().lower; |
7731 Handle<Type> result_type = expr->bounds().lower; | 7682 Handle<Type> result_type = expr->bounds().lower; |
7732 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7683 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
7733 Representation left_rep = Representation::FromType(left_type); | 7684 Representation left_rep = Representation::FromType(left_type); |
7734 Representation right_rep = Representation::FromType(right_type); | 7685 Representation right_rep = Representation::FromType(right_type); |
7735 Representation result_rep = Representation::FromType(result_type); | 7686 Representation result_rep = Representation::FromType(result_type); |
7736 | 7687 |
7737 if (expr->op() != Token::ADD || | 7688 if (expr->op() != Token::ADD || |
7738 (left->type().IsNonString() && right->type().IsNonString())) { | 7689 (left->type().IsNonString() && right->type().IsNonString())) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7771 instr = HMul::New(zone(), context, left, right); | 7722 instr = HMul::New(zone(), context, left, right); |
7772 break; | 7723 break; |
7773 case Token::MOD: | 7724 case Token::MOD: |
7774 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7725 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
7775 break; | 7726 break; |
7776 case Token::DIV: | 7727 case Token::DIV: |
7777 instr = HDiv::New(zone(), context, left, right); | 7728 instr = HDiv::New(zone(), context, left, right); |
7778 break; | 7729 break; |
7779 case Token::BIT_XOR: | 7730 case Token::BIT_XOR: |
7780 case Token::BIT_AND: | 7731 case Token::BIT_AND: |
7781 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 7732 instr = New<HBitwise>(expr->op(), left, right); |
7782 break; | 7733 break; |
7783 case Token::BIT_OR: { | 7734 case Token::BIT_OR: { |
7784 HValue* operand, *shift_amount; | 7735 HValue* operand, *shift_amount; |
7785 if (left_type->Is(Type::Signed32()) && | 7736 if (left_type->Is(Type::Signed32()) && |
7786 right_type->Is(Type::Signed32()) && | 7737 right_type->Is(Type::Signed32()) && |
7787 MatchRotateRight(left, right, &operand, &shift_amount)) { | 7738 MatchRotateRight(left, right, &operand, &shift_amount)) { |
7788 instr = new(zone()) HRor(context, operand, shift_amount); | 7739 instr = new(zone()) HRor(context, operand, shift_amount); |
7789 } else { | 7740 } else { |
7790 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 7741 instr = New<HBitwise>(expr->op(), left, right); |
7791 } | 7742 } |
7792 break; | 7743 break; |
7793 } | 7744 } |
7794 case Token::SAR: | 7745 case Token::SAR: |
7795 instr = HSar::New(zone(), context, left, right); | 7746 instr = HSar::New(zone(), context, left, right); |
7796 break; | 7747 break; |
7797 case Token::SHR: | 7748 case Token::SHR: |
7798 instr = HShr::New(zone(), context, left, right); | 7749 instr = HShr::New(zone(), context, left, right); |
7799 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 7750 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7800 CanBeZero(right)) { | 7751 CanBeZero(right)) { |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8025 Handle<Type> left_type = expr->left()->bounds().lower; | 7976 Handle<Type> left_type = expr->left()->bounds().lower; |
8026 Handle<Type> right_type = expr->right()->bounds().lower; | 7977 Handle<Type> right_type = expr->right()->bounds().lower; |
8027 Handle<Type> combined_type = expr->combined_type(); | 7978 Handle<Type> combined_type = expr->combined_type(); |
8028 Representation combined_rep = Representation::FromType(combined_type); | 7979 Representation combined_rep = Representation::FromType(combined_type); |
8029 Representation left_rep = Representation::FromType(left_type); | 7980 Representation left_rep = Representation::FromType(left_type); |
8030 Representation right_rep = Representation::FromType(right_type); | 7981 Representation right_rep = Representation::FromType(right_type); |
8031 | 7982 |
8032 CHECK_ALIVE(VisitForValue(expr->left())); | 7983 CHECK_ALIVE(VisitForValue(expr->left())); |
8033 CHECK_ALIVE(VisitForValue(expr->right())); | 7984 CHECK_ALIVE(VisitForValue(expr->right())); |
8034 | 7985 |
8035 HValue* context = environment()->LookupContext(); | 7986 HValue* context = environment()->context(); |
8036 HValue* right = Pop(); | 7987 HValue* right = Pop(); |
8037 HValue* left = Pop(); | 7988 HValue* left = Pop(); |
8038 Token::Value op = expr->op(); | 7989 Token::Value op = expr->op(); |
8039 | 7990 |
8040 if (IsLiteralCompareBool(left, op, right)) { | 7991 if (IsLiteralCompareBool(left, op, right)) { |
8041 HCompareObjectEqAndBranch* result = | 7992 HCompareObjectEqAndBranch* result = |
8042 new(zone()) HCompareObjectEqAndBranch(left, right); | 7993 New<HCompareObjectEqAndBranch>(left, right); |
8043 result->set_position(expr->position()); | 7994 result->set_position(expr->position()); |
8044 return ast_context()->ReturnControl(result, expr->id()); | 7995 return ast_context()->ReturnControl(result, expr->id()); |
8045 } | 7996 } |
8046 | 7997 |
8047 if (op == Token::INSTANCEOF) { | 7998 if (op == Token::INSTANCEOF) { |
8048 // Check to see if the rhs of the instanceof is a global function not | 7999 // Check to see if the rhs of the instanceof is a global function not |
8049 // residing in new space. If it is we assume that the function will stay the | 8000 // residing in new space. If it is we assume that the function will stay the |
8050 // same. | 8001 // same. |
8051 Handle<JSFunction> target = Handle<JSFunction>::null(); | 8002 Handle<JSFunction> target = Handle<JSFunction>::null(); |
8052 VariableProxy* proxy = expr->right()->AsVariableProxy(); | 8003 VariableProxy* proxy = expr->right()->AsVariableProxy(); |
(...skipping 25 matching lines...) Expand all Loading... |
8078 Add<HCheckFunction>(right, target); | 8029 Add<HCheckFunction>(right, target); |
8079 HInstanceOfKnownGlobal* result = | 8030 HInstanceOfKnownGlobal* result = |
8080 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8031 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
8081 result->set_position(expr->position()); | 8032 result->set_position(expr->position()); |
8082 return ast_context()->ReturnInstruction(result, expr->id()); | 8033 return ast_context()->ReturnInstruction(result, expr->id()); |
8083 } | 8034 } |
8084 | 8035 |
8085 // Code below assumes that we don't fall through. | 8036 // Code below assumes that we don't fall through. |
8086 UNREACHABLE(); | 8037 UNREACHABLE(); |
8087 } else if (op == Token::IN) { | 8038 } else if (op == Token::IN) { |
8088 HValue* function = AddLoadJSBuiltin(Builtins::IN, context); | 8039 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
8089 Add<HPushArgument>(left); | 8040 Add<HPushArgument>(left); |
8090 Add<HPushArgument>(right); | 8041 Add<HPushArgument>(right); |
8091 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8042 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
8092 // even though we are certain to pass the correct number of arguments here. | 8043 // even though we are certain to pass the correct number of arguments here. |
8093 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8044 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
8094 result->set_position(expr->position()); | 8045 result->set_position(expr->position()); |
8095 return ast_context()->ReturnInstruction(result, expr->id()); | 8046 return ast_context()->ReturnInstruction(result, expr->id()); |
8096 } | 8047 } |
8097 | 8048 |
8098 // Cases handled below depend on collected type feedback. They should | 8049 // Cases handled below depend on collected type feedback. They should |
8099 // soft deoptimize when there is no type feedback. | 8050 // soft deoptimize when there is no type feedback. |
8100 if (combined_type->Is(Type::None())) { | 8051 if (combined_type->Is(Type::None())) { |
8101 Add<HDeoptimize>(Deoptimizer::SOFT); | 8052 Add<HDeoptimize>(Deoptimizer::SOFT); |
8102 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8053 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
8103 } | 8054 } |
8104 | 8055 |
8105 if (combined_type->Is(Type::Receiver())) { | 8056 if (combined_type->Is(Type::Receiver())) { |
8106 switch (op) { | 8057 switch (op) { |
8107 case Token::EQ: | 8058 case Token::EQ: |
8108 case Token::EQ_STRICT: { | 8059 case Token::EQ_STRICT: { |
8109 // Can we get away with map check and not instance type check? | 8060 // Can we get away with map check and not instance type check? |
8110 if (combined_type->IsClass()) { | 8061 if (combined_type->IsClass()) { |
8111 Handle<Map> map = combined_type->AsClass(); | 8062 Handle<Map> map = combined_type->AsClass(); |
8112 AddCheckMap(left, map); | 8063 AddCheckMap(left, map); |
8113 AddCheckMap(right, map); | 8064 AddCheckMap(right, map); |
8114 HCompareObjectEqAndBranch* result = | 8065 HCompareObjectEqAndBranch* result = |
8115 new(zone()) HCompareObjectEqAndBranch(left, right); | 8066 New<HCompareObjectEqAndBranch>(left, right); |
8116 result->set_position(expr->position()); | 8067 result->set_position(expr->position()); |
8117 return ast_context()->ReturnControl(result, expr->id()); | 8068 return ast_context()->ReturnControl(result, expr->id()); |
8118 } else { | 8069 } else { |
8119 BuildCheckHeapObject(left); | 8070 BuildCheckHeapObject(left); |
8120 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 8071 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
8121 BuildCheckHeapObject(right); | 8072 BuildCheckHeapObject(right); |
8122 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 8073 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
8123 HCompareObjectEqAndBranch* result = | 8074 HCompareObjectEqAndBranch* result = |
8124 new(zone()) HCompareObjectEqAndBranch(left, right); | 8075 new(zone()) HCompareObjectEqAndBranch(left, right); |
8125 result->set_position(expr->position()); | 8076 result->set_position(expr->position()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8186 ? handle(Type::Any(), isolate_) : expr->combined_type(); | 8137 ? handle(Type::Any(), isolate_) : expr->combined_type(); |
8187 BuildCompareNil(value, type, expr->position(), &continuation); | 8138 BuildCompareNil(value, type, expr->position(), &continuation); |
8188 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8139 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
8189 } | 8140 } |
8190 | 8141 |
8191 | 8142 |
8192 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8143 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
8193 // If we share optimized code between different closures, the | 8144 // If we share optimized code between different closures, the |
8194 // this-function is not a constant, except inside an inlined body. | 8145 // this-function is not a constant, except inside an inlined body. |
8195 if (function_state()->outer() != NULL) { | 8146 if (function_state()->outer() != NULL) { |
8196 return new(zone()) HConstant( | 8147 return New<HConstant>( |
8197 function_state()->compilation_info()->closure()); | 8148 function_state()->compilation_info()->closure()); |
8198 } else { | 8149 } else { |
8199 return new(zone()) HThisFunction; | 8150 return new(zone()) HThisFunction; |
8200 } | 8151 } |
8201 } | 8152 } |
8202 | 8153 |
8203 | 8154 |
8204 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 8155 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
8205 HValue* context, | 8156 HValue* context, |
8206 Handle<JSObject> boilerplate_object, | 8157 Handle<JSObject> boilerplate_object, |
8207 Handle<JSObject> original_boilerplate_object, | 8158 Handle<JSObject> original_boilerplate_object, |
8208 Handle<Object> allocation_site, | 8159 Handle<Object> allocation_site, |
8209 int data_size, | 8160 int data_size, |
8210 int pointer_size, | 8161 int pointer_size, |
8211 AllocationSiteMode mode) { | 8162 AllocationSiteMode mode) { |
8212 NoObservableSideEffectsScope no_effects(this); | 8163 NoObservableSideEffectsScope no_effects(this); |
8213 | 8164 |
8214 HInstruction* target = NULL; | 8165 HInstruction* target = NULL; |
8215 HInstruction* data_target = NULL; | 8166 HInstruction* data_target = NULL; |
8216 | 8167 |
8217 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8168 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
8218 | 8169 |
8219 if (isolate()->heap()->ShouldGloballyPretenure()) { | 8170 if (isolate()->heap()->ShouldGloballyPretenure()) { |
8220 if (data_size != 0) { | 8171 if (data_size != 0) { |
8221 HValue* size_in_bytes = Add<HConstant>(data_size); | 8172 HValue* size_in_bytes = Add<HConstant>(data_size); |
8222 data_target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), | 8173 data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
8223 true, FAST_DOUBLE_ELEMENTS); | 8174 true, FAST_DOUBLE_ELEMENTS); |
8224 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | 8175 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); |
8225 AddStoreMapConstant(data_target, free_space_map); | 8176 AddStoreMapConstant(data_target, free_space_map); |
8226 HObjectAccess access = | 8177 HObjectAccess access = |
8227 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | 8178 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
8228 AddStore(data_target, access, size_in_bytes); | 8179 Add<HStoreNamedField>(data_target, access, size_in_bytes); |
8229 } | 8180 } |
8230 if (pointer_size != 0) { | 8181 if (pointer_size != 0) { |
8231 HValue* size_in_bytes = Add<HConstant>(pointer_size); | 8182 HValue* size_in_bytes = Add<HConstant>(pointer_size); |
8232 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), | 8183 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), true); |
8233 true); | |
8234 } | 8184 } |
8235 } else { | 8185 } else { |
8236 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); | 8186 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); |
8237 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), false, | 8187 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), false, kind); |
8238 kind); | |
8239 } | 8188 } |
8240 | 8189 |
8241 int offset = 0; | 8190 int offset = 0; |
8242 int data_offset = 0; | 8191 int data_offset = 0; |
8243 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, | 8192 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, |
8244 allocation_site, target, &offset, data_target, | 8193 allocation_site, target, &offset, data_target, |
8245 &data_offset, mode); | 8194 &data_offset, mode); |
8246 return target; | 8195 return target; |
8247 } | 8196 } |
8248 | 8197 |
8249 | 8198 |
8250 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 8199 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
8251 Handle<JSObject> boilerplate_object, | 8200 Handle<JSObject> boilerplate_object, |
8252 Handle<JSObject> original_boilerplate_object, | 8201 Handle<JSObject> original_boilerplate_object, |
8253 Handle<Object> allocation_site_object, | 8202 Handle<Object> allocation_site_object, |
8254 HInstruction* target, | 8203 HInstruction* target, |
8255 int* offset, | 8204 int* offset, |
8256 HInstruction* data_target, | 8205 HInstruction* data_target, |
8257 int* data_offset, | 8206 int* data_offset, |
8258 AllocationSiteMode mode) { | 8207 AllocationSiteMode mode) { |
8259 Zone* zone = this->zone(); | |
8260 | |
8261 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 8208 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
8262 boilerplate_object->map()->CanTrackAllocationSite(); | 8209 boilerplate_object->map()->CanTrackAllocationSite(); |
8263 | 8210 |
8264 // If using allocation sites, then the payload on the site should already | 8211 // If using allocation sites, then the payload on the site should already |
8265 // be filled in as a valid (boilerplate) array. | 8212 // be filled in as a valid (boilerplate) array. |
8266 ASSERT(!create_allocation_site_info || | 8213 ASSERT(!create_allocation_site_info || |
8267 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); | 8214 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); |
8268 | 8215 |
8269 HInstruction* allocation_site = NULL; | 8216 HInstruction* allocation_site = NULL; |
8270 | 8217 |
8271 if (create_allocation_site_info) { | 8218 if (create_allocation_site_info) { |
8272 allocation_site = AddInstruction(new(zone) HConstant( | 8219 allocation_site = Add<HConstant>(allocation_site_object); |
8273 allocation_site_object, Representation::Tagged())); | |
8274 } | 8220 } |
8275 | 8221 |
8276 // Only elements backing stores for non-COW arrays need to be copied. | 8222 // Only elements backing stores for non-COW arrays need to be copied. |
8277 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 8223 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
8278 Handle<FixedArrayBase> original_elements( | 8224 Handle<FixedArrayBase> original_elements( |
8279 original_boilerplate_object->elements()); | 8225 original_boilerplate_object->elements()); |
8280 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8226 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
8281 | 8227 |
8282 int object_offset = *offset; | 8228 int object_offset = *offset; |
8283 int object_size = boilerplate_object->map()->instance_size(); | 8229 int object_size = boilerplate_object->map()->instance_size(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8344 Handle<Object>(boilerplate_object->elements(), isolate()); | 8290 Handle<Object>(boilerplate_object->elements(), isolate()); |
8345 elements = Add<HConstant>(elements_field); | 8291 elements = Add<HConstant>(elements_field); |
8346 } else { | 8292 } else { |
8347 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | 8293 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { |
8348 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); | 8294 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); |
8349 } else { | 8295 } else { |
8350 elements = Add<HInnerAllocatedObject>(target, elements_offset); | 8296 elements = Add<HInnerAllocatedObject>(target, elements_offset); |
8351 } | 8297 } |
8352 result = elements; | 8298 result = elements; |
8353 } | 8299 } |
8354 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); | 8300 Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(), |
| 8301 elements); |
8355 | 8302 |
8356 Handle<Object> properties_field = | 8303 Handle<Object> properties_field = |
8357 Handle<Object>(boilerplate_object->properties(), isolate()); | 8304 Handle<Object>(boilerplate_object->properties(), isolate()); |
8358 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 8305 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
8359 HInstruction* properties = Add<HConstant>(properties_field); | 8306 HInstruction* properties = Add<HConstant>(properties_field); |
8360 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 8307 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
8361 AddStore(object_header, access, properties); | 8308 Add<HStoreNamedField>(object_header, access, properties); |
8362 | 8309 |
8363 if (boilerplate_object->IsJSArray()) { | 8310 if (boilerplate_object->IsJSArray()) { |
8364 Handle<JSArray> boilerplate_array = | 8311 Handle<JSArray> boilerplate_array = |
8365 Handle<JSArray>::cast(boilerplate_object); | 8312 Handle<JSArray>::cast(boilerplate_object); |
8366 Handle<Object> length_field = | 8313 Handle<Object> length_field = |
8367 Handle<Object>(boilerplate_array->length(), isolate()); | 8314 Handle<Object>(boilerplate_array->length(), isolate()); |
8368 HInstruction* length = Add<HConstant>(length_field); | 8315 HInstruction* length = Add<HConstant>(length_field); |
8369 | 8316 |
8370 ASSERT(boilerplate_array->length()->IsSmi()); | 8317 ASSERT(boilerplate_array->length()->IsSmi()); |
8371 AddStore(object_header, HObjectAccess::ForArrayLength( | 8318 Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength( |
8372 boilerplate_array->GetElementsKind()), length); | 8319 boilerplate_array->GetElementsKind()), length); |
8373 } | 8320 } |
8374 | 8321 |
8375 return result; | 8322 return result; |
8376 } | 8323 } |
8377 | 8324 |
8378 | 8325 |
8379 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8326 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
8380 Handle<JSObject> boilerplate_object, | 8327 Handle<JSObject> boilerplate_object, |
8381 Handle<JSObject> original_boilerplate_object, | 8328 Handle<JSObject> original_boilerplate_object, |
(...skipping 24 matching lines...) Expand all Loading... |
8406 HObjectAccess::ForJSObjectOffset(property_offset); | 8353 HObjectAccess::ForJSObjectOffset(property_offset); |
8407 | 8354 |
8408 if (value->IsJSObject()) { | 8355 if (value->IsJSObject()) { |
8409 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8356 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
8410 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8357 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
8411 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 8358 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
8412 isolate())); | 8359 isolate())); |
8413 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8360 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, |
8414 *offset); | 8361 *offset); |
8415 | 8362 |
8416 AddStore(object_properties, access, value_instruction); | 8363 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8417 BuildEmitDeepCopy(value_object, original_value_object, | 8364 BuildEmitDeepCopy(value_object, original_value_object, |
8418 Handle<Object>::null(), target, | 8365 Handle<Object>::null(), target, |
8419 offset, data_target, data_offset, | 8366 offset, data_target, data_offset, |
8420 DONT_TRACK_ALLOCATION_SITE); | 8367 DONT_TRACK_ALLOCATION_SITE); |
8421 } else { | 8368 } else { |
8422 Representation representation = details.representation(); | 8369 Representation representation = details.representation(); |
8423 HInstruction* value_instruction = Add<HConstant>(value); | 8370 HInstruction* value_instruction = Add<HConstant>(value); |
8424 | 8371 |
8425 if (representation.IsDouble()) { | 8372 if (representation.IsDouble()) { |
8426 // Allocate a HeapNumber box and store the value into it. | 8373 // Allocate a HeapNumber box and store the value into it. |
8427 HInstruction* double_box; | 8374 HInstruction* double_box; |
8428 if (data_target != NULL) { | 8375 if (data_target != NULL) { |
8429 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8376 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); |
8430 *data_offset += HeapNumber::kSize; | 8377 *data_offset += HeapNumber::kSize; |
8431 } else { | 8378 } else { |
8432 double_box = Add<HInnerAllocatedObject>(target, *offset); | 8379 double_box = Add<HInnerAllocatedObject>(target, *offset); |
8433 *offset += HeapNumber::kSize; | 8380 *offset += HeapNumber::kSize; |
8434 } | 8381 } |
8435 AddStoreMapConstant(double_box, | 8382 AddStoreMapConstant(double_box, |
8436 isolate()->factory()->heap_number_map()); | 8383 isolate()->factory()->heap_number_map()); |
8437 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 8384 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
8438 value_instruction); | 8385 value_instruction); |
8439 value_instruction = double_box; | 8386 value_instruction = double_box; |
8440 } | 8387 } |
8441 | 8388 |
8442 AddStore(object_properties, access, value_instruction); | 8389 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8443 } | 8390 } |
8444 } | 8391 } |
8445 | 8392 |
8446 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8393 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
8447 HInstruction* value_instruction = | 8394 HInstruction* value_instruction = |
8448 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8395 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
8449 for (int i = copied_fields; i < inobject_properties; i++) { | 8396 for (int i = copied_fields; i < inobject_properties; i++) { |
8450 ASSERT(boilerplate_object->IsJSObject()); | 8397 ASSERT(boilerplate_object->IsJSObject()); |
8451 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 8398 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
8452 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 8399 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
8453 AddStore(object_properties, access, value_instruction); | 8400 Add<HStoreNamedField>(object_properties, access, value_instruction); |
8454 } | 8401 } |
8455 } | 8402 } |
8456 | 8403 |
8457 | 8404 |
8458 void HOptimizedGraphBuilder::BuildEmitElements( | 8405 void HOptimizedGraphBuilder::BuildEmitElements( |
8459 Handle<FixedArrayBase> elements, | 8406 Handle<FixedArrayBase> elements, |
8460 Handle<FixedArrayBase> original_elements, | 8407 Handle<FixedArrayBase> original_elements, |
8461 ElementsKind kind, | 8408 ElementsKind kind, |
8462 HValue* object_elements, | 8409 HValue* object_elements, |
8463 HInstruction* target, | 8410 HInstruction* target, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8552 ZoneList<Declaration*>* declarations) { | 8499 ZoneList<Declaration*>* declarations) { |
8553 ASSERT(globals_.is_empty()); | 8500 ASSERT(globals_.is_empty()); |
8554 AstVisitor::VisitDeclarations(declarations); | 8501 AstVisitor::VisitDeclarations(declarations); |
8555 if (!globals_.is_empty()) { | 8502 if (!globals_.is_empty()) { |
8556 Handle<FixedArray> array = | 8503 Handle<FixedArray> array = |
8557 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 8504 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
8558 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 8505 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
8559 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 8506 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
8560 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 8507 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
8561 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); | 8508 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); |
8562 Add<HDeclareGlobals>(environment()->LookupContext(), array, flags); | 8509 Add<HDeclareGlobals>(array, flags); |
8563 globals_.Clear(); | 8510 globals_.Clear(); |
8564 } | 8511 } |
8565 } | 8512 } |
8566 | 8513 |
8567 | 8514 |
8568 void HOptimizedGraphBuilder::VisitVariableDeclaration( | 8515 void HOptimizedGraphBuilder::VisitVariableDeclaration( |
8569 VariableDeclaration* declaration) { | 8516 VariableDeclaration* declaration) { |
8570 VariableProxy* proxy = declaration->proxy(); | 8517 VariableProxy* proxy = declaration->proxy(); |
8571 VariableMode mode = declaration->mode(); | 8518 VariableMode mode = declaration->mode(); |
8572 Variable* variable = proxy->var(); | 8519 Variable* variable = proxy->var(); |
8573 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 8520 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; |
8574 switch (variable->location()) { | 8521 switch (variable->location()) { |
8575 case Variable::UNALLOCATED: | 8522 case Variable::UNALLOCATED: |
8576 globals_.Add(variable->name(), zone()); | 8523 globals_.Add(variable->name(), zone()); |
8577 globals_.Add(variable->binding_needs_init() | 8524 globals_.Add(variable->binding_needs_init() |
8578 ? isolate()->factory()->the_hole_value() | 8525 ? isolate()->factory()->the_hole_value() |
8579 : isolate()->factory()->undefined_value(), zone()); | 8526 : isolate()->factory()->undefined_value(), zone()); |
8580 return; | 8527 return; |
8581 case Variable::PARAMETER: | 8528 case Variable::PARAMETER: |
8582 case Variable::LOCAL: | 8529 case Variable::LOCAL: |
8583 if (hole_init) { | 8530 if (hole_init) { |
8584 HValue* value = graph()->GetConstantHole(); | 8531 HValue* value = graph()->GetConstantHole(); |
8585 environment()->Bind(variable, value); | 8532 environment()->Bind(variable, value); |
8586 } | 8533 } |
8587 break; | 8534 break; |
8588 case Variable::CONTEXT: | 8535 case Variable::CONTEXT: |
8589 if (hole_init) { | 8536 if (hole_init) { |
8590 HValue* value = graph()->GetConstantHole(); | 8537 HValue* value = graph()->GetConstantHole(); |
8591 HValue* context = environment()->LookupContext(); | 8538 HValue* context = environment()->context(); |
8592 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8539 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8593 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8540 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8594 if (store->HasObservableSideEffects()) { | 8541 if (store->HasObservableSideEffects()) { |
8595 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8542 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8596 } | 8543 } |
8597 } | 8544 } |
8598 break; | 8545 break; |
8599 case Variable::LOOKUP: | 8546 case Variable::LOOKUP: |
8600 return Bailout("unsupported lookup slot in declaration"); | 8547 return Bailout("unsupported lookup slot in declaration"); |
8601 } | 8548 } |
(...skipping 17 matching lines...) Expand all Loading... |
8619 case Variable::PARAMETER: | 8566 case Variable::PARAMETER: |
8620 case Variable::LOCAL: { | 8567 case Variable::LOCAL: { |
8621 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8568 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8622 HValue* value = Pop(); | 8569 HValue* value = Pop(); |
8623 BindIfLive(variable, value); | 8570 BindIfLive(variable, value); |
8624 break; | 8571 break; |
8625 } | 8572 } |
8626 case Variable::CONTEXT: { | 8573 case Variable::CONTEXT: { |
8627 CHECK_ALIVE(VisitForValue(declaration->fun())); | 8574 CHECK_ALIVE(VisitForValue(declaration->fun())); |
8628 HValue* value = Pop(); | 8575 HValue* value = Pop(); |
8629 HValue* context = environment()->LookupContext(); | 8576 HValue* context = environment()->context(); |
8630 HStoreContextSlot* store = Add<HStoreContextSlot>( | 8577 HStoreContextSlot* store = Add<HStoreContextSlot>( |
8631 context, variable->index(), HStoreContextSlot::kNoCheck, value); | 8578 context, variable->index(), HStoreContextSlot::kNoCheck, value); |
8632 if (store->HasObservableSideEffects()) { | 8579 if (store->HasObservableSideEffects()) { |
8633 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); | 8580 Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE); |
8634 } | 8581 } |
8635 break; | 8582 break; |
8636 } | 8583 } |
8637 case Variable::LOOKUP: | 8584 case Variable::LOOKUP: |
8638 return Bailout("unsupported lookup slot in declaration"); | 8585 return Bailout("unsupported lookup slot in declaration"); |
8639 } | 8586 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8794 | 8741 |
8795 | 8742 |
8796 // Support for arguments.length and arguments[?]. | 8743 // Support for arguments.length and arguments[?]. |
8797 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 8744 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
8798 // Our implementation of arguments (based on this stack frame or an | 8745 // Our implementation of arguments (based on this stack frame or an |
8799 // adapter below it) does not work for inlined functions. This runtime | 8746 // adapter below it) does not work for inlined functions. This runtime |
8800 // function is blacklisted by AstNode::IsInlineable. | 8747 // function is blacklisted by AstNode::IsInlineable. |
8801 ASSERT(function_state()->outer() == NULL); | 8748 ASSERT(function_state()->outer() == NULL); |
8802 ASSERT(call->arguments()->length() == 0); | 8749 ASSERT(call->arguments()->length() == 0); |
8803 HInstruction* elements = Add<HArgumentsElements>(false); | 8750 HInstruction* elements = Add<HArgumentsElements>(false); |
8804 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); | 8751 HArgumentsLength* result = New<HArgumentsLength>(elements); |
8805 return ast_context()->ReturnInstruction(result, call->id()); | 8752 return ast_context()->ReturnInstruction(result, call->id()); |
8806 } | 8753 } |
8807 | 8754 |
8808 | 8755 |
8809 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 8756 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { |
8810 // Our implementation of arguments (based on this stack frame or an | 8757 // Our implementation of arguments (based on this stack frame or an |
8811 // adapter below it) does not work for inlined functions. This runtime | 8758 // adapter below it) does not work for inlined functions. This runtime |
8812 // function is blacklisted by AstNode::IsInlineable. | 8759 // function is blacklisted by AstNode::IsInlineable. |
8813 ASSERT(function_state()->outer() == NULL); | 8760 ASSERT(function_state()->outer() == NULL); |
8814 ASSERT(call->arguments()->length() == 1); | 8761 ASSERT(call->arguments()->length() == 1); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8903 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); | 8850 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); |
8904 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); | 8851 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); |
8905 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); | 8852 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); |
8906 typecheck->SetSuccessorAt(0, if_js_value); | 8853 typecheck->SetSuccessorAt(0, if_js_value); |
8907 typecheck->SetSuccessorAt(1, not_js_value); | 8854 typecheck->SetSuccessorAt(1, not_js_value); |
8908 current_block()->Finish(typecheck); | 8855 current_block()->Finish(typecheck); |
8909 not_js_value->Goto(join); | 8856 not_js_value->Goto(join); |
8910 | 8857 |
8911 // Create in-object property store to kValueOffset. | 8858 // Create in-object property store to kValueOffset. |
8912 set_current_block(if_js_value); | 8859 set_current_block(if_js_value); |
8913 AddStore(object, | 8860 Add<HStoreNamedField>(object, |
8914 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); | 8861 HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value); |
8915 if_js_value->Goto(join); | 8862 if_js_value->Goto(join); |
8916 join->SetJoinId(call->id()); | 8863 join->SetJoinId(call->id()); |
8917 set_current_block(join); | 8864 set_current_block(join); |
8918 return ast_context()->ReturnValue(value); | 8865 return ast_context()->ReturnValue(value); |
8919 } | 8866 } |
8920 | 8867 |
8921 | 8868 |
8922 // Fast support for charCodeAt(n). | 8869 // Fast support for charCodeAt(n). |
8923 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 8870 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
8924 ASSERT(call->arguments()->length() == 2); | 8871 ASSERT(call->arguments()->length() == 2); |
8925 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8872 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8926 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8873 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
8927 HValue* index = Pop(); | 8874 HValue* index = Pop(); |
8928 HValue* string = Pop(); | 8875 HValue* string = Pop(); |
8929 HValue* context = environment()->LookupContext(); | 8876 HInstruction* result = BuildStringCharCodeAt(string, index); |
8930 HInstruction* result = BuildStringCharCodeAt(context, string, index); | |
8931 return ast_context()->ReturnInstruction(result, call->id()); | 8877 return ast_context()->ReturnInstruction(result, call->id()); |
8932 } | 8878 } |
8933 | 8879 |
8934 | 8880 |
8935 // Fast support for string.charAt(n) and string[n]. | 8881 // Fast support for string.charAt(n) and string[n]. |
8936 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 8882 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
8937 ASSERT(call->arguments()->length() == 1); | 8883 ASSERT(call->arguments()->length() == 1); |
8938 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8884 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8939 HValue* char_code = Pop(); | 8885 HValue* char_code = Pop(); |
8940 HValue* context = environment()->LookupContext(); | 8886 HInstruction* result = New<HStringCharFromCode>(char_code); |
8941 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code); | |
8942 return ast_context()->ReturnInstruction(result, call->id()); | 8887 return ast_context()->ReturnInstruction(result, call->id()); |
8943 } | 8888 } |
8944 | 8889 |
8945 | 8890 |
8946 // Fast support for string.charAt(n) and string[n]. | 8891 // Fast support for string.charAt(n) and string[n]. |
8947 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 8892 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
8948 ASSERT(call->arguments()->length() == 2); | 8893 ASSERT(call->arguments()->length() == 2); |
8949 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8894 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8950 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8895 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
8951 HValue* index = Pop(); | 8896 HValue* index = Pop(); |
8952 HValue* string = Pop(); | 8897 HValue* string = Pop(); |
8953 HValue* context = environment()->LookupContext(); | 8898 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
8954 HInstruction* char_code = BuildStringCharCodeAt(context, string, index); | |
8955 AddInstruction(char_code); | 8899 AddInstruction(char_code); |
8956 HInstruction* result = HStringCharFromCode::New(zone(), context, char_code); | 8900 HInstruction* result = New<HStringCharFromCode>(char_code); |
8957 return ast_context()->ReturnInstruction(result, call->id()); | 8901 return ast_context()->ReturnInstruction(result, call->id()); |
8958 } | 8902 } |
8959 | 8903 |
8960 | 8904 |
8961 // Fast support for object equality testing. | 8905 // Fast support for object equality testing. |
8962 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 8906 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
8963 ASSERT(call->arguments()->length() == 2); | 8907 ASSERT(call->arguments()->length() == 2); |
8964 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8908 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8965 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8909 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
8966 HValue* right = Pop(); | 8910 HValue* right = Pop(); |
8967 HValue* left = Pop(); | 8911 HValue* left = Pop(); |
8968 HCompareObjectEqAndBranch* result = | 8912 HCompareObjectEqAndBranch* result = |
8969 new(zone()) HCompareObjectEqAndBranch(left, right); | 8913 New<HCompareObjectEqAndBranch>(left, right); |
8970 return ast_context()->ReturnControl(result, call->id()); | 8914 return ast_context()->ReturnControl(result, call->id()); |
8971 } | 8915 } |
8972 | 8916 |
8973 | 8917 |
8974 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { | 8918 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { |
8975 // %_Log is ignored in optimized code. | 8919 // %_Log is ignored in optimized code. |
8976 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 8920 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
8977 } | 8921 } |
8978 | 8922 |
8979 | 8923 |
8980 // Fast support for Math.random(). | 8924 // Fast support for Math.random(). |
8981 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 8925 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
8982 HValue* context = environment()->LookupContext(); | 8926 HGlobalObject* global_object = Add<HGlobalObject>(); |
8983 HGlobalObject* global_object = Add<HGlobalObject>(context); | |
8984 HRandom* result = new(zone()) HRandom(global_object); | 8927 HRandom* result = new(zone()) HRandom(global_object); |
8985 return ast_context()->ReturnInstruction(result, call->id()); | 8928 return ast_context()->ReturnInstruction(result, call->id()); |
8986 } | 8929 } |
8987 | 8930 |
8988 | 8931 |
8989 // Fast support for StringAdd. | 8932 // Fast support for StringAdd. |
8990 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 8933 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
8991 ASSERT_EQ(2, call->arguments()->length()); | 8934 ASSERT_EQ(2, call->arguments()->length()); |
8992 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 8935 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8993 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 8936 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
8994 HValue* right = Pop(); | 8937 HValue* right = Pop(); |
8995 HValue* left = Pop(); | 8938 HValue* left = Pop(); |
8996 HValue* context = environment()->LookupContext(); | 8939 HValue* context = environment()->context(); |
8997 HInstruction* result = HStringAdd::New( | 8940 HInstruction* result = HStringAdd::New( |
8998 zone(), context, left, right, STRING_ADD_CHECK_BOTH); | 8941 zone(), context, left, right, STRING_ADD_CHECK_BOTH); |
8999 return ast_context()->ReturnInstruction(result, call->id()); | 8942 return ast_context()->ReturnInstruction(result, call->id()); |
9000 } | 8943 } |
9001 | 8944 |
9002 | 8945 |
9003 // Fast support for SubString. | 8946 // Fast support for SubString. |
9004 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 8947 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
9005 ASSERT_EQ(3, call->arguments()->length()); | 8948 ASSERT_EQ(3, call->arguments()->length()); |
9006 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 8949 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9007 HValue* context = environment()->LookupContext(); | 8950 HValue* context = environment()->context(); |
9008 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 8951 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
9009 Drop(3); | 8952 Drop(3); |
9010 return ast_context()->ReturnInstruction(result, call->id()); | 8953 return ast_context()->ReturnInstruction(result, call->id()); |
9011 } | 8954 } |
9012 | 8955 |
9013 | 8956 |
9014 // Fast support for StringCompare. | 8957 // Fast support for StringCompare. |
9015 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 8958 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
9016 ASSERT_EQ(2, call->arguments()->length()); | 8959 ASSERT_EQ(2, call->arguments()->length()); |
9017 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 8960 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9018 HValue* context = environment()->LookupContext(); | 8961 HValue* context = environment()->context(); |
9019 HCallStub* result = | 8962 HCallStub* result = |
9020 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 8963 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
9021 Drop(2); | 8964 Drop(2); |
9022 return ast_context()->ReturnInstruction(result, call->id()); | 8965 return ast_context()->ReturnInstruction(result, call->id()); |
9023 } | 8966 } |
9024 | 8967 |
9025 | 8968 |
9026 // Support for direct calls from JavaScript to native RegExp code. | 8969 // Support for direct calls from JavaScript to native RegExp code. |
9027 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 8970 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
9028 ASSERT_EQ(4, call->arguments()->length()); | 8971 ASSERT_EQ(4, call->arguments()->length()); |
9029 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 8972 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9030 HValue* context = environment()->LookupContext(); | 8973 HValue* context = environment()->context(); |
9031 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 8974 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
9032 Drop(4); | 8975 Drop(4); |
9033 return ast_context()->ReturnInstruction(result, call->id()); | 8976 return ast_context()->ReturnInstruction(result, call->id()); |
9034 } | 8977 } |
9035 | 8978 |
9036 | 8979 |
9037 // Construct a RegExp exec result with two in-object properties. | 8980 // Construct a RegExp exec result with two in-object properties. |
9038 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 8981 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
9039 ASSERT_EQ(3, call->arguments()->length()); | 8982 ASSERT_EQ(3, call->arguments()->length()); |
9040 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 8983 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9041 HValue* context = environment()->LookupContext(); | 8984 HValue* context = environment()->context(); |
9042 HCallStub* result = | 8985 HCallStub* result = |
9043 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 8986 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
9044 Drop(3); | 8987 Drop(3); |
9045 return ast_context()->ReturnInstruction(result, call->id()); | 8988 return ast_context()->ReturnInstruction(result, call->id()); |
9046 } | 8989 } |
9047 | 8990 |
9048 | 8991 |
9049 // Support for fast native caches. | 8992 // Support for fast native caches. |
9050 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 8993 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9051 return Bailout("inlined runtime function: GetFromCache"); | 8994 return Bailout("inlined runtime function: GetFromCache"); |
9052 } | 8995 } |
9053 | 8996 |
9054 | 8997 |
9055 // Fast support for number to string. | 8998 // Fast support for number to string. |
9056 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 8999 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9057 ASSERT_EQ(1, call->arguments()->length()); | 9000 ASSERT_EQ(1, call->arguments()->length()); |
9058 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9001 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9059 HValue* context = environment()->LookupContext(); | 9002 HValue* context = environment()->context(); |
9060 HCallStub* result = | 9003 HCallStub* result = |
9061 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9004 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
9062 Drop(1); | 9005 Drop(1); |
9063 return ast_context()->ReturnInstruction(result, call->id()); | 9006 return ast_context()->ReturnInstruction(result, call->id()); |
9064 } | 9007 } |
9065 | 9008 |
9066 | 9009 |
9067 // Fast call for custom callbacks. | 9010 // Fast call for custom callbacks. |
9068 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9011 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9069 // 1 ~ The function to call is not itself an argument to the call. | 9012 // 1 ~ The function to call is not itself an argument to the call. |
9070 int arg_count = call->arguments()->length() - 1; | 9013 int arg_count = call->arguments()->length() - 1; |
9071 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9014 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9072 | 9015 |
9073 for (int i = 0; i < arg_count; ++i) { | 9016 for (int i = 0; i < arg_count; ++i) { |
9074 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 9017 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
9075 } | 9018 } |
9076 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 9019 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
9077 | 9020 |
9078 HValue* function = Pop(); | 9021 HValue* function = Pop(); |
9079 HValue* context = environment()->LookupContext(); | |
9080 | 9022 |
9081 // Branch for function proxies, or other non-functions. | 9023 // Branch for function proxies, or other non-functions. |
9082 HHasInstanceTypeAndBranch* typecheck = | 9024 HHasInstanceTypeAndBranch* typecheck = |
9083 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); | 9025 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); |
9084 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); | 9026 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); |
9085 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); | 9027 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); |
9086 HBasicBlock* join = graph()->CreateBasicBlock(); | 9028 HBasicBlock* join = graph()->CreateBasicBlock(); |
9087 typecheck->SetSuccessorAt(0, if_jsfunction); | 9029 typecheck->SetSuccessorAt(0, if_jsfunction); |
9088 typecheck->SetSuccessorAt(1, if_nonfunction); | 9030 typecheck->SetSuccessorAt(1, if_nonfunction); |
9089 current_block()->Finish(typecheck); | 9031 current_block()->Finish(typecheck); |
9090 | 9032 |
9091 set_current_block(if_jsfunction); | 9033 set_current_block(if_jsfunction); |
9092 HInstruction* invoke_result = | 9034 HInstruction* invoke_result = Add<HInvokeFunction>(function, arg_count); |
9093 Add<HInvokeFunction>(context, function, arg_count); | |
9094 Drop(arg_count); | 9035 Drop(arg_count); |
9095 Push(invoke_result); | 9036 Push(invoke_result); |
9096 if_jsfunction->Goto(join); | 9037 if_jsfunction->Goto(join); |
9097 | 9038 |
9098 set_current_block(if_nonfunction); | 9039 set_current_block(if_nonfunction); |
9099 HInstruction* call_result = Add<HCallFunction>(context, function, arg_count); | 9040 HInstruction* call_result = Add<HCallFunction>(function, arg_count); |
9100 Drop(arg_count); | 9041 Drop(arg_count); |
9101 Push(call_result); | 9042 Push(call_result); |
9102 if_nonfunction->Goto(join); | 9043 if_nonfunction->Goto(join); |
9103 | 9044 |
9104 set_current_block(join); | 9045 set_current_block(join); |
9105 join->SetJoinId(call->id()); | 9046 join->SetJoinId(call->id()); |
9106 return ast_context()->ReturnValue(Pop()); | 9047 return ast_context()->ReturnValue(Pop()); |
9107 } | 9048 } |
9108 | 9049 |
9109 | 9050 |
9110 // Fast call to math functions. | 9051 // Fast call to math functions. |
9111 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 9052 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
9112 ASSERT_EQ(2, call->arguments()->length()); | 9053 ASSERT_EQ(2, call->arguments()->length()); |
9113 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9054 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9114 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9055 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
9115 HValue* right = Pop(); | 9056 HValue* right = Pop(); |
9116 HValue* left = Pop(); | 9057 HValue* left = Pop(); |
9117 HInstruction* result = HPower::New(zone(), left, right); | 9058 HInstruction* result = HPower::New(zone(), context(), left, right); |
9118 return ast_context()->ReturnInstruction(result, call->id()); | 9059 return ast_context()->ReturnInstruction(result, call->id()); |
9119 } | 9060 } |
9120 | 9061 |
9121 | 9062 |
9122 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9063 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { |
9123 ASSERT_EQ(1, call->arguments()->length()); | 9064 ASSERT_EQ(1, call->arguments()->length()); |
9124 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9065 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9125 HValue* context = environment()->LookupContext(); | 9066 HValue* context = environment()->context(); |
9126 HCallStub* result = | 9067 HCallStub* result = |
9127 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9068 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9128 result->set_transcendental_type(TranscendentalCache::SIN); | 9069 result->set_transcendental_type(TranscendentalCache::SIN); |
9129 Drop(1); | 9070 Drop(1); |
9130 return ast_context()->ReturnInstruction(result, call->id()); | 9071 return ast_context()->ReturnInstruction(result, call->id()); |
9131 } | 9072 } |
9132 | 9073 |
9133 | 9074 |
9134 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9075 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { |
9135 ASSERT_EQ(1, call->arguments()->length()); | 9076 ASSERT_EQ(1, call->arguments()->length()); |
9136 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9077 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9137 HValue* context = environment()->LookupContext(); | 9078 HValue* context = environment()->context(); |
9138 HCallStub* result = | 9079 HCallStub* result = |
9139 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9080 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9140 result->set_transcendental_type(TranscendentalCache::COS); | 9081 result->set_transcendental_type(TranscendentalCache::COS); |
9141 Drop(1); | 9082 Drop(1); |
9142 return ast_context()->ReturnInstruction(result, call->id()); | 9083 return ast_context()->ReturnInstruction(result, call->id()); |
9143 } | 9084 } |
9144 | 9085 |
9145 | 9086 |
9146 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9087 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { |
9147 ASSERT_EQ(1, call->arguments()->length()); | 9088 ASSERT_EQ(1, call->arguments()->length()); |
9148 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9089 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9149 HValue* context = environment()->LookupContext(); | 9090 HValue* context = environment()->context(); |
9150 HCallStub* result = | 9091 HCallStub* result = |
9151 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9092 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9152 result->set_transcendental_type(TranscendentalCache::TAN); | 9093 result->set_transcendental_type(TranscendentalCache::TAN); |
9153 Drop(1); | 9094 Drop(1); |
9154 return ast_context()->ReturnInstruction(result, call->id()); | 9095 return ast_context()->ReturnInstruction(result, call->id()); |
9155 } | 9096 } |
9156 | 9097 |
9157 | 9098 |
9158 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9099 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { |
9159 ASSERT_EQ(1, call->arguments()->length()); | 9100 ASSERT_EQ(1, call->arguments()->length()); |
9160 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9101 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9161 HValue* context = environment()->LookupContext(); | 9102 HValue* context = environment()->context(); |
9162 HCallStub* result = | 9103 HCallStub* result = |
9163 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 9104 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
9164 result->set_transcendental_type(TranscendentalCache::LOG); | 9105 result->set_transcendental_type(TranscendentalCache::LOG); |
9165 Drop(1); | 9106 Drop(1); |
9166 return ast_context()->ReturnInstruction(result, call->id()); | 9107 return ast_context()->ReturnInstruction(result, call->id()); |
9167 } | 9108 } |
9168 | 9109 |
9169 | 9110 |
9170 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9111 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
9171 ASSERT(call->arguments()->length() == 1); | 9112 ASSERT(call->arguments()->length() == 1); |
9172 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9113 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9173 HValue* value = Pop(); | 9114 HValue* value = Pop(); |
9174 HValue* context = environment()->LookupContext(); | 9115 HValue* context = environment()->context(); |
9175 HInstruction* result = | 9116 HInstruction* result = |
9176 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); | 9117 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); |
9177 return ast_context()->ReturnInstruction(result, call->id()); | 9118 return ast_context()->ReturnInstruction(result, call->id()); |
9178 } | 9119 } |
9179 | 9120 |
9180 | 9121 |
9181 // Check whether two RegExps are equivalent | 9122 // Check whether two RegExps are equivalent |
9182 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9123 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
9183 return Bailout("inlined runtime function: IsRegExpEquivalent"); | 9124 return Bailout("inlined runtime function: IsRegExpEquivalent"); |
9184 } | 9125 } |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9474 HValue* push = (i <= arguments) ? | 9415 HValue* push = (i <= arguments) ? |
9475 ExpressionStackAt(arguments - i) : undefined; | 9416 ExpressionStackAt(arguments - i) : undefined; |
9476 inner->SetValueAt(i, push); | 9417 inner->SetValueAt(i, push); |
9477 } | 9418 } |
9478 // If the function we are inlining is a strict mode function or a | 9419 // If the function we are inlining is a strict mode function or a |
9479 // builtin function, pass undefined as the receiver for function | 9420 // builtin function, pass undefined as the receiver for function |
9480 // calls (instead of the global receiver). | 9421 // calls (instead of the global receiver). |
9481 if (undefined_receiver) { | 9422 if (undefined_receiver) { |
9482 inner->SetValueAt(0, undefined); | 9423 inner->SetValueAt(0, undefined); |
9483 } | 9424 } |
9484 inner->SetValueAt(arity + 1, LookupContext()); | 9425 inner->SetValueAt(arity + 1, context()); |
9485 for (int i = arity + 2; i < inner->length(); ++i) { | 9426 for (int i = arity + 2; i < inner->length(); ++i) { |
9486 inner->SetValueAt(i, undefined); | 9427 inner->SetValueAt(i, undefined); |
9487 } | 9428 } |
9488 | 9429 |
9489 inner->set_ast_id(BailoutId::FunctionEntry()); | 9430 inner->set_ast_id(BailoutId::FunctionEntry()); |
9490 return inner; | 9431 return inner; |
9491 } | 9432 } |
9492 | 9433 |
9493 | 9434 |
9494 void HEnvironment::PrintTo(StringStream* stream) { | 9435 void HEnvironment::PrintTo(StringStream* stream) { |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9824 if (ShouldProduceTraceOutput()) { | 9765 if (ShouldProduceTraceOutput()) { |
9825 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9766 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9826 } | 9767 } |
9827 | 9768 |
9828 #ifdef DEBUG | 9769 #ifdef DEBUG |
9829 graph_->Verify(false); // No full verify. | 9770 graph_->Verify(false); // No full verify. |
9830 #endif | 9771 #endif |
9831 } | 9772 } |
9832 | 9773 |
9833 } } // namespace v8::internal | 9774 } } // namespace v8::internal |
OLD | NEW |