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