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