| 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 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 } | 823 } |
| 824 builder_->set_current_block(first_true_block_); | 824 builder_->set_current_block(first_true_block_); |
| 825 } | 825 } |
| 826 | 826 |
| 827 | 827 |
| 828 void HGraphBuilder::IfBuilder::Else() { | 828 void HGraphBuilder::IfBuilder::Else() { |
| 829 ASSERT(did_then_); | 829 ASSERT(did_then_); |
| 830 ASSERT(!captured_); | 830 ASSERT(!captured_); |
| 831 ASSERT(!finished_); | 831 ASSERT(!finished_); |
| 832 last_true_block_ = builder_->current_block(); | 832 last_true_block_ = builder_->current_block(); |
| 833 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); | |
| 834 builder_->set_current_block(first_false_block_); | 833 builder_->set_current_block(first_false_block_); |
| 835 did_else_ = true; | 834 did_else_ = true; |
| 836 } | 835 } |
| 837 | 836 |
| 838 | 837 |
| 839 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 838 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
| 840 ASSERT(did_then_); | 839 ASSERT(did_then_); |
| 841 if (did_else_) { | 840 if (did_else_) { |
| 842 deopt_else_ = true; | 841 deopt_else_ = true; |
| 843 } else { | 842 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 859 } | 858 } |
| 860 } | 859 } |
| 861 | 860 |
| 862 | 861 |
| 863 void HGraphBuilder::IfBuilder::End() { | 862 void HGraphBuilder::IfBuilder::End() { |
| 864 if (!captured_) { | 863 if (!captured_) { |
| 865 ASSERT(did_then_); | 864 ASSERT(did_then_); |
| 866 if (!did_else_) { | 865 if (!did_else_) { |
| 867 last_true_block_ = builder_->current_block(); | 866 last_true_block_ = builder_->current_block(); |
| 868 } | 867 } |
| 869 if (first_true_block_ == NULL) { | 868 if (last_true_block_ == NULL || last_true_block_->IsFinished()) { |
| 869 ASSERT(did_else_); |
| 870 // Return on true. Nothing to do, just continue the false block. | 870 // Return on true. Nothing to do, just continue the false block. |
| 871 } else if (first_false_block_ == NULL) { | 871 } else if (first_false_block_ == NULL || |
| 872 (did_else_ && builder_->current_block()->IsFinished())) { |
| 872 // Deopt on false. Nothing to do except switching to the true block. | 873 // Deopt on false. Nothing to do except switching to the true block. |
| 873 builder_->set_current_block(last_true_block_); | 874 builder_->set_current_block(last_true_block_); |
| 874 } else { | 875 } else { |
| 875 merge_block_ = builder_->graph()->CreateBasicBlock(); | 876 merge_block_ = builder_->graph()->CreateBasicBlock(); |
| 876 ASSERT(!finished_); | 877 ASSERT(!finished_); |
| 877 if (!did_else_) Else(); | 878 if (!did_else_) Else(); |
| 878 ASSERT(!last_true_block_->IsFinished()); | 879 ASSERT(!last_true_block_->IsFinished()); |
| 879 HBasicBlock* last_false_block = builder_->current_block(); | 880 HBasicBlock* last_false_block = builder_->current_block(); |
| 880 ASSERT(!last_false_block->IsFinished()); | 881 ASSERT(!last_false_block->IsFinished()); |
| 881 if (deopt_then_) { | 882 if (deopt_then_) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 901 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 902 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
| 902 HValue* context, | 903 HValue* context, |
| 903 LoopBuilder::Direction direction) | 904 LoopBuilder::Direction direction) |
| 904 : builder_(builder), | 905 : builder_(builder), |
| 905 context_(context), | 906 context_(context), |
| 906 direction_(direction), | 907 direction_(direction), |
| 907 finished_(false) { | 908 finished_(false) { |
| 908 header_block_ = builder->CreateLoopHeaderBlock(); | 909 header_block_ = builder->CreateLoopHeaderBlock(); |
| 909 body_block_ = NULL; | 910 body_block_ = NULL; |
| 910 exit_block_ = NULL; | 911 exit_block_ = NULL; |
| 912 exit_trampoline_block_ = NULL; |
| 913 increment_amount_ = builder_->graph()->GetConstant1(); |
| 911 } | 914 } |
| 912 | 915 |
| 913 | 916 |
| 917 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
| 918 HValue* context, |
| 919 LoopBuilder::Direction direction, |
| 920 HValue* increment_amount) |
| 921 : builder_(builder), |
| 922 context_(context), |
| 923 direction_(direction), |
| 924 finished_(false) { |
| 925 header_block_ = builder->CreateLoopHeaderBlock(); |
| 926 body_block_ = NULL; |
| 927 exit_block_ = NULL; |
| 928 exit_trampoline_block_ = NULL; |
| 929 increment_amount_ = increment_amount; |
| 930 } |
| 931 |
| 932 |
| 914 HValue* HGraphBuilder::LoopBuilder::BeginBody( | 933 HValue* HGraphBuilder::LoopBuilder::BeginBody( |
| 915 HValue* initial, | 934 HValue* initial, |
| 916 HValue* terminating, | 935 HValue* terminating, |
| 917 Token::Value token) { | 936 Token::Value token) { |
| 918 HEnvironment* env = builder_->environment(); | 937 HEnvironment* env = builder_->environment(); |
| 919 phi_ = header_block_->AddNewPhi(env->values()->length()); | 938 phi_ = header_block_->AddNewPhi(env->values()->length()); |
| 920 phi_->AddInput(initial); | 939 phi_->AddInput(initial); |
| 921 env->Push(initial); | 940 env->Push(initial); |
| 922 builder_->current_block()->GotoNoSimulate(header_block_); | 941 builder_->current_block()->GotoNoSimulate(header_block_); |
| 923 | 942 |
| 924 HEnvironment* body_env = env->Copy(); | 943 HEnvironment* body_env = env->Copy(); |
| 925 HEnvironment* exit_env = env->Copy(); | 944 HEnvironment* exit_env = env->Copy(); |
| 945 // Remove the phi from the expression stack |
| 946 body_env->Pop(); |
| 947 exit_env->Pop(); |
| 926 body_block_ = builder_->CreateBasicBlock(body_env); | 948 body_block_ = builder_->CreateBasicBlock(body_env); |
| 927 exit_block_ = builder_->CreateBasicBlock(exit_env); | 949 exit_block_ = builder_->CreateBasicBlock(exit_env); |
| 928 // Remove the phi from the expression stack | |
| 929 body_env->Pop(); | |
| 930 | 950 |
| 931 builder_->set_current_block(header_block_); | 951 builder_->set_current_block(header_block_); |
| 952 env->Pop(); |
| 932 HCompareNumericAndBranch* compare = | 953 HCompareNumericAndBranch* compare = |
| 933 new(zone()) HCompareNumericAndBranch(phi_, terminating, token); | 954 new(zone()) HCompareNumericAndBranch(phi_, terminating, token); |
| 934 compare->SetSuccessorAt(0, body_block_); | 955 compare->SetSuccessorAt(0, body_block_); |
| 935 compare->SetSuccessorAt(1, exit_block_); | 956 compare->SetSuccessorAt(1, exit_block_); |
| 936 builder_->current_block()->Finish(compare); | 957 builder_->current_block()->Finish(compare); |
| 937 | 958 |
| 938 builder_->set_current_block(body_block_); | 959 builder_->set_current_block(body_block_); |
| 939 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { | 960 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { |
| 940 HValue* one = builder_->graph()->GetConstant1(); | 961 HValue* one = builder_->graph()->GetConstant1(); |
| 941 if (direction_ == kPreIncrement) { | 962 if (direction_ == kPreIncrement) { |
| 942 increment_ = HAdd::New(zone(), context_, phi_, one); | 963 increment_ = HAdd::New(zone(), context_, phi_, one); |
| 943 } else { | 964 } else { |
| 944 increment_ = HSub::New(zone(), context_, phi_, one); | 965 increment_ = HSub::New(zone(), context_, phi_, one); |
| 945 } | 966 } |
| 946 increment_->ClearFlag(HValue::kCanOverflow); | 967 increment_->ClearFlag(HValue::kCanOverflow); |
| 947 builder_->AddInstruction(increment_); | 968 builder_->AddInstruction(increment_); |
| 948 return increment_; | 969 return increment_; |
| 949 } else { | 970 } else { |
| 950 return phi_; | 971 return phi_; |
| 951 } | 972 } |
| 952 } | 973 } |
| 953 | 974 |
| 954 | 975 |
| 976 void HGraphBuilder::LoopBuilder::Break() { |
| 977 if (exit_trampoline_block_ == NULL) { |
| 978 // Its the first time we saw a break. |
| 979 HEnvironment* env = exit_block_->last_environment()->Copy(); |
| 980 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
| 981 exit_block_->GotoNoSimulate(exit_trampoline_block_); |
| 982 } |
| 983 |
| 984 builder_->current_block()->GotoNoSimulate(exit_trampoline_block_); |
| 985 } |
| 986 |
| 987 |
| 955 void HGraphBuilder::LoopBuilder::EndBody() { | 988 void HGraphBuilder::LoopBuilder::EndBody() { |
| 956 ASSERT(!finished_); | 989 ASSERT(!finished_); |
| 957 | 990 |
| 958 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { | 991 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { |
| 959 HValue* one = builder_->graph()->GetConstant1(); | |
| 960 if (direction_ == kPostIncrement) { | 992 if (direction_ == kPostIncrement) { |
| 961 increment_ = HAdd::New(zone(), context_, phi_, one); | 993 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); |
| 962 } else { | 994 } else { |
| 963 increment_ = HSub::New(zone(), context_, phi_, one); | 995 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); |
| 964 } | 996 } |
| 965 increment_->ClearFlag(HValue::kCanOverflow); | 997 increment_->ClearFlag(HValue::kCanOverflow); |
| 966 builder_->AddInstruction(increment_); | 998 builder_->AddInstruction(increment_); |
| 967 } | 999 } |
| 968 | 1000 |
| 969 // Push the new increment value on the expression stack to merge into the phi. | 1001 // Push the new increment value on the expression stack to merge into the phi. |
| 970 builder_->environment()->Push(increment_); | 1002 builder_->environment()->Push(increment_); |
| 971 HBasicBlock* last_block = builder_->current_block(); | 1003 HBasicBlock* last_block = builder_->current_block(); |
| 972 last_block->GotoNoSimulate(header_block_); | 1004 last_block->GotoNoSimulate(header_block_); |
| 973 header_block_->loop_information()->RegisterBackEdge(last_block); | 1005 header_block_->loop_information()->RegisterBackEdge(last_block); |
| 974 | 1006 |
| 975 builder_->set_current_block(exit_block_); | 1007 if (exit_trampoline_block_ != NULL) { |
| 976 // Pop the phi from the expression stack | 1008 builder_->set_current_block(exit_trampoline_block_); |
| 977 builder_->environment()->Pop(); | 1009 } else { |
| 1010 builder_->set_current_block(exit_block_); |
| 1011 } |
| 978 finished_ = true; | 1012 finished_ = true; |
| 979 } | 1013 } |
| 980 | 1014 |
| 981 | 1015 |
| 982 HGraph* HGraphBuilder::CreateGraph() { | 1016 HGraph* HGraphBuilder::CreateGraph() { |
| 983 graph_ = new(zone()) HGraph(info_); | 1017 graph_ = new(zone()) HGraph(info_); |
| 984 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1018 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
| 985 CompilationPhase phase("H_Block building", info_); | 1019 CompilationPhase phase("H_Block building", info_); |
| 986 set_current_block(graph()->entry_block()); | 1020 set_current_block(graph()->entry_block()); |
| 987 if (!BuildGraph()) return NULL; | 1021 if (!BuildGraph()) return NULL; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 ElementsKind to_kind, | 1220 ElementsKind to_kind, |
| 1187 bool is_jsarray) { | 1221 bool is_jsarray) { |
| 1188 ASSERT(!IsFastHoleyElementsKind(from_kind) || | 1222 ASSERT(!IsFastHoleyElementsKind(from_kind) || |
| 1189 IsFastHoleyElementsKind(to_kind)); | 1223 IsFastHoleyElementsKind(to_kind)); |
| 1190 | 1224 |
| 1191 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1225 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 1192 Add<HTrapAllocationMemento>(object); | 1226 Add<HTrapAllocationMemento>(object); |
| 1193 } | 1227 } |
| 1194 | 1228 |
| 1195 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1229 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 1196 HInstruction* elements = AddLoadElements(object, NULL); | 1230 HInstruction* elements = AddLoadElements(object); |
| 1197 | 1231 |
| 1198 HInstruction* empty_fixed_array = Add<HConstant>( | 1232 HInstruction* empty_fixed_array = Add<HConstant>( |
| 1199 isolate()->factory()->empty_fixed_array()); | 1233 isolate()->factory()->empty_fixed_array()); |
| 1200 | 1234 |
| 1201 IfBuilder if_builder(this); | 1235 IfBuilder if_builder(this); |
| 1202 | 1236 |
| 1203 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); | 1237 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); |
| 1204 | 1238 |
| 1205 if_builder.Then(); | 1239 if_builder.Then(); |
| 1206 | 1240 |
| 1207 HInstruction* elements_length = AddLoadFixedArrayLength(elements); | 1241 HInstruction* elements_length = AddLoadFixedArrayLength(elements); |
| 1208 | 1242 |
| 1209 HInstruction* array_length = is_jsarray | 1243 HInstruction* array_length = is_jsarray |
| 1210 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) | 1244 ? Add<HLoadNamedField>(object, HObjectAccess::ForArrayLength(from_kind)) |
| 1211 : elements_length; | 1245 : elements_length; |
| 1212 | 1246 |
| 1213 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1247 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
| 1214 array_length, elements_length); | 1248 array_length, elements_length); |
| 1215 | 1249 |
| 1216 if_builder.End(); | 1250 if_builder.End(); |
| 1217 } | 1251 } |
| 1218 | 1252 |
| 1219 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1253 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
| 1220 } | 1254 } |
| 1221 | 1255 |
| 1222 | 1256 |
| 1223 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1257 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 1224 HValue* object, | 1258 HValue* checked_object, |
| 1225 HValue* key, | 1259 HValue* key, |
| 1226 HValue* val, | 1260 HValue* val, |
| 1227 HCheckMaps* mapcheck, | |
| 1228 bool is_js_array, | 1261 bool is_js_array, |
| 1229 ElementsKind elements_kind, | 1262 ElementsKind elements_kind, |
| 1230 bool is_store, | 1263 bool is_store, |
| 1231 LoadKeyedHoleMode load_mode, | 1264 LoadKeyedHoleMode load_mode, |
| 1232 KeyedAccessStoreMode store_mode) { | 1265 KeyedAccessStoreMode store_mode) { |
| 1233 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1266 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
| 1234 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1267 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 1235 // on a HElementsTransition instruction. The flag can also be removed if the | 1268 // on a HElementsTransition instruction. The flag can also be removed if the |
| 1236 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1269 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 1237 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1270 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 1238 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1271 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 1239 // generated store code. | 1272 // generated store code. |
| 1240 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 1273 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
| 1241 (elements_kind == FAST_ELEMENTS && is_store)) { | 1274 (elements_kind == FAST_ELEMENTS && is_store)) { |
| 1242 if (mapcheck != NULL) { | 1275 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 1243 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
| 1244 } | |
| 1245 } | 1276 } |
| 1277 |
| 1246 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1278 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
| 1247 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1279 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
| 1248 HValue* elements = AddLoadElements(object, mapcheck); | 1280 HValue* elements = AddLoadElements(checked_object); |
| 1249 if (is_store && (fast_elements || fast_smi_only_elements) && | 1281 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1250 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 1282 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 1251 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 1283 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 1252 elements, isolate()->factory()->fixed_array_map(), top_info()); | 1284 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 1253 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1285 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1254 } | 1286 } |
| 1255 HInstruction* length = NULL; | 1287 HInstruction* length = NULL; |
| 1256 if (is_js_array) { | 1288 if (is_js_array) { |
| 1257 length = Add<HLoadNamedField>(object, | 1289 length = Add<HLoadNamedField>( |
| 1258 HObjectAccess::ForArrayLength(elements_kind), mapcheck); | 1290 checked_object, HObjectAccess::ForArrayLength(elements_kind)); |
| 1259 } else { | 1291 } else { |
| 1260 length = AddLoadFixedArrayLength(elements); | 1292 length = AddLoadFixedArrayLength(elements); |
| 1261 } | 1293 } |
| 1262 length->set_type(HType::Smi()); | 1294 length->set_type(HType::Smi()); |
| 1263 HValue* checked_key = NULL; | 1295 HValue* checked_key = NULL; |
| 1264 if (IsExternalArrayElementsKind(elements_kind)) { | 1296 if (IsExternalArrayElementsKind(elements_kind)) { |
| 1265 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1297 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1266 NoObservableSideEffectsScope no_effects(this); | 1298 NoObservableSideEffectsScope no_effects(this); |
| 1267 HLoadExternalArrayPointer* external_elements = | 1299 HLoadExternalArrayPointer* external_elements = |
| 1268 Add<HLoadExternalArrayPointer>(elements); | 1300 Add<HLoadExternalArrayPointer>(elements); |
| 1269 IfBuilder length_checker(this); | 1301 IfBuilder length_checker(this); |
| 1270 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1302 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 1271 length_checker.Then(); | 1303 length_checker.Then(); |
| 1272 IfBuilder negative_checker(this); | 1304 IfBuilder negative_checker(this); |
| 1273 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1305 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 1274 key, graph()->GetConstant0(), Token::GTE); | 1306 key, graph()->GetConstant0(), Token::GTE); |
| 1275 negative_checker.Then(); | 1307 negative_checker.Then(); |
| 1276 HInstruction* result = AddExternalArrayElementAccess( | 1308 HInstruction* result = AddExternalArrayElementAccess( |
| 1277 external_elements, key, val, bounds_check, elements_kind, is_store); | 1309 external_elements, key, val, bounds_check, elements_kind, is_store); |
| 1278 negative_checker.ElseDeopt("Negative key encountered"); | 1310 negative_checker.ElseDeopt("Negative key encountered"); |
| 1279 length_checker.End(); | 1311 length_checker.End(); |
| 1280 return result; | 1312 return result; |
| 1281 } else { | 1313 } else { |
| 1282 ASSERT(store_mode == STANDARD_STORE); | 1314 ASSERT(store_mode == STANDARD_STORE); |
| 1283 checked_key = Add<HBoundsCheck>(key, length); | 1315 checked_key = Add<HBoundsCheck>(key, length); |
| 1284 HLoadExternalArrayPointer* external_elements = | 1316 HLoadExternalArrayPointer* external_elements = |
| 1285 Add<HLoadExternalArrayPointer>(elements); | 1317 Add<HLoadExternalArrayPointer>(elements); |
| 1286 return AddExternalArrayElementAccess( | 1318 return AddExternalArrayElementAccess( |
| 1287 external_elements, checked_key, val, | 1319 external_elements, checked_key, val, |
| 1288 mapcheck, elements_kind, is_store); | 1320 checked_object, elements_kind, is_store); |
| 1289 } | 1321 } |
| 1290 } | 1322 } |
| 1291 ASSERT(fast_smi_only_elements || | 1323 ASSERT(fast_smi_only_elements || |
| 1292 fast_elements || | 1324 fast_elements || |
| 1293 IsFastDoubleElementsKind(elements_kind)); | 1325 IsFastDoubleElementsKind(elements_kind)); |
| 1294 | 1326 |
| 1295 // In case val is stored into a fast smi array, assure that the value is a smi | 1327 // In case val is stored into a fast smi array, assure that the value is a smi |
| 1296 // before manipulating the backing store. Otherwise the actual store may | 1328 // before manipulating the backing store. Otherwise the actual store may |
| 1297 // deopt, leaving the backing store in an invalid state. | 1329 // deopt, leaving the backing store in an invalid state. |
| 1298 if (is_store && IsFastSmiElementsKind(elements_kind) && | 1330 if (is_store && IsFastSmiElementsKind(elements_kind) && |
| 1299 !val->type().IsSmi()) { | 1331 !val->type().IsSmi()) { |
| 1300 val = Add<HForceRepresentation>(val, Representation::Smi()); | 1332 val = Add<HForceRepresentation>(val, Representation::Smi()); |
| 1301 } | 1333 } |
| 1302 | 1334 |
| 1303 if (IsGrowStoreMode(store_mode)) { | 1335 if (IsGrowStoreMode(store_mode)) { |
| 1304 NoObservableSideEffectsScope no_effects(this); | 1336 NoObservableSideEffectsScope no_effects(this); |
| 1305 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, | 1337 elements = BuildCheckForCapacityGrow(checked_object, elements, |
| 1306 length, key, is_js_array); | 1338 elements_kind, length, key, |
| 1339 is_js_array); |
| 1307 checked_key = key; | 1340 checked_key = key; |
| 1308 } else { | 1341 } else { |
| 1309 checked_key = Add<HBoundsCheck>(key, length); | 1342 checked_key = Add<HBoundsCheck>(key, length); |
| 1310 | 1343 |
| 1311 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1344 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 1312 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1345 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
| 1313 NoObservableSideEffectsScope no_effects(this); | 1346 NoObservableSideEffectsScope no_effects(this); |
| 1314 | 1347 elements = BuildCopyElementsOnWrite(checked_object, elements, |
| 1315 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1348 elements_kind, length); |
| 1316 length); | |
| 1317 } else { | 1349 } else { |
| 1318 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 1350 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 1319 elements, isolate()->factory()->fixed_array_map(), | 1351 elements, isolate()->factory()->fixed_array_map(), |
| 1320 top_info()); | 1352 top_info()); |
| 1321 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1353 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1322 } | 1354 } |
| 1323 } | 1355 } |
| 1324 } | 1356 } |
| 1325 return AddFastElementAccess(elements, checked_key, val, mapcheck, | 1357 return AddFastElementAccess(elements, checked_key, val, checked_object, |
| 1326 elements_kind, is_store, load_mode, store_mode); | 1358 elements_kind, is_store, load_mode, store_mode); |
| 1327 } | 1359 } |
| 1328 | 1360 |
| 1329 | 1361 |
| 1330 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, | 1362 HValue* HGraphBuilder::BuildAllocateElements(ElementsKind kind, |
| 1331 HValue* capacity) { | 1363 HValue* capacity) { |
| 1332 int elements_size; | 1364 int elements_size; |
| 1333 InstanceType instance_type; | 1365 InstanceType instance_type; |
| 1334 | 1366 |
| 1335 if (IsFastDoubleElementsKind(kind)) { | 1367 if (IsFastDoubleElementsKind(kind)) { |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1488 UNREACHABLE(); | 1520 UNREACHABLE(); |
| 1489 return NULL; | 1521 return NULL; |
| 1490 } | 1522 } |
| 1491 } | 1523 } |
| 1492 // It's an element load (!is_store). | 1524 // It's an element load (!is_store). |
| 1493 return Add<HLoadKeyed>( | 1525 return Add<HLoadKeyed>( |
| 1494 elements, checked_key, load_dependency, elements_kind, load_mode); | 1526 elements, checked_key, load_dependency, elements_kind, load_mode); |
| 1495 } | 1527 } |
| 1496 | 1528 |
| 1497 | 1529 |
| 1498 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, | 1530 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { |
| 1499 HValue* typecheck) { | 1531 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); |
| 1500 return Add<HLoadNamedField>(object, | |
| 1501 HObjectAccess::ForElementsPointer(), | |
| 1502 typecheck); | |
| 1503 } | 1532 } |
| 1504 | 1533 |
| 1505 | 1534 |
| 1506 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { | 1535 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) { |
| 1507 return Add<HLoadNamedField>(object, | 1536 return Add<HLoadNamedField>(object, |
| 1508 HObjectAccess::ForFixedArrayLength()); | 1537 HObjectAccess::ForFixedArrayLength()); |
| 1509 } | 1538 } |
| 1510 | 1539 |
| 1511 | 1540 |
| 1512 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { | 1541 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1708 } | 1737 } |
| 1709 | 1738 |
| 1710 // Create an allocation site info if requested. | 1739 // Create an allocation site info if requested. |
| 1711 if (mode == TRACK_ALLOCATION_SITE) { | 1740 if (mode == TRACK_ALLOCATION_SITE) { |
| 1712 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 1741 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); |
| 1713 } | 1742 } |
| 1714 | 1743 |
| 1715 if (length > 0) { | 1744 if (length > 0) { |
| 1716 // Get hold of the elements array of the boilerplate and setup the | 1745 // Get hold of the elements array of the boilerplate and setup the |
| 1717 // elements pointer in the resulting object. | 1746 // elements pointer in the resulting object. |
| 1718 HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL); | 1747 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 1719 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); | 1748 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); |
| 1720 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 1749 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 1721 object_elements); | 1750 object_elements); |
| 1722 | 1751 |
| 1723 // Copy the elements array header. | 1752 // Copy the elements array header. |
| 1724 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { | 1753 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { |
| 1725 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); | 1754 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); |
| 1726 Add<HStoreNamedField>(object_elements, access, | 1755 Add<HStoreNamedField>(object_elements, access, |
| 1727 Add<HLoadNamedField>(boilerplate_elements, access)); | 1756 Add<HLoadNamedField>(boilerplate_elements, access)); |
| 1728 } | 1757 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1742 return object; | 1771 return object; |
| 1743 } | 1772 } |
| 1744 | 1773 |
| 1745 | 1774 |
| 1746 void HGraphBuilder::BuildCompareNil( | 1775 void HGraphBuilder::BuildCompareNil( |
| 1747 HValue* value, | 1776 HValue* value, |
| 1748 Handle<Type> type, | 1777 Handle<Type> type, |
| 1749 int position, | 1778 int position, |
| 1750 HIfContinuation* continuation) { | 1779 HIfContinuation* continuation) { |
| 1751 IfBuilder if_nil(this, position); | 1780 IfBuilder if_nil(this, position); |
| 1752 bool needs_or = false; | 1781 bool some_case_handled = false; |
| 1782 bool some_case_missing = false; |
| 1783 |
| 1753 if (type->Maybe(Type::Null())) { | 1784 if (type->Maybe(Type::Null())) { |
| 1754 if (needs_or) if_nil.Or(); | 1785 if (some_case_handled) if_nil.Or(); |
| 1755 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 1786 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| 1756 needs_or = true; | 1787 some_case_handled = true; |
| 1788 } else { |
| 1789 some_case_missing = true; |
| 1757 } | 1790 } |
| 1791 |
| 1758 if (type->Maybe(Type::Undefined())) { | 1792 if (type->Maybe(Type::Undefined())) { |
| 1759 if (needs_or) if_nil.Or(); | 1793 if (some_case_handled) if_nil.Or(); |
| 1760 if_nil.If<HCompareObjectEqAndBranch>(value, | 1794 if_nil.If<HCompareObjectEqAndBranch>(value, |
| 1761 graph()->GetConstantUndefined()); | 1795 graph()->GetConstantUndefined()); |
| 1762 needs_or = true; | 1796 some_case_handled = true; |
| 1797 } else { |
| 1798 some_case_missing = true; |
| 1763 } | 1799 } |
| 1800 |
| 1764 if (type->Maybe(Type::Undetectable())) { | 1801 if (type->Maybe(Type::Undetectable())) { |
| 1765 if (needs_or) if_nil.Or(); | 1802 if (some_case_handled) if_nil.Or(); |
| 1766 if_nil.If<HIsUndetectableAndBranch>(value); | 1803 if_nil.If<HIsUndetectableAndBranch>(value); |
| 1804 some_case_handled = true; |
| 1767 } else { | 1805 } else { |
| 1806 some_case_missing = true; |
| 1807 } |
| 1808 |
| 1809 if (some_case_missing) { |
| 1768 if_nil.Then(); | 1810 if_nil.Then(); |
| 1769 if_nil.Else(); | 1811 if_nil.Else(); |
| 1770 if (type->NumClasses() == 1) { | 1812 if (type->NumClasses() == 1) { |
| 1771 BuildCheckHeapObject(value); | 1813 BuildCheckHeapObject(value); |
| 1772 // For ICs, the map checked below is a sentinel map that gets replaced by | 1814 // For ICs, the map checked below is a sentinel map that gets replaced by |
| 1773 // the monomorphic map when the code is used as a template to generate a | 1815 // the monomorphic map when the code is used as a template to generate a |
| 1774 // new IC. For optimized functions, there is no sentinel map, the map | 1816 // new IC. For optimized functions, there is no sentinel map, the map |
| 1775 // emitted below is the actual monomorphic map. | 1817 // emitted below is the actual monomorphic map. |
| 1776 BuildCheckMap(value, type->Classes().Current()); | 1818 BuildCheckMap(value, type->Classes().Current()); |
| 1777 } else { | 1819 } else { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 constructor_function_(constructor_function) { | 1883 constructor_function_(constructor_function) { |
| 1842 } | 1884 } |
| 1843 | 1885 |
| 1844 | 1886 |
| 1845 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { | 1887 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { |
| 1846 if (kind_ == GetInitialFastElementsKind()) { | 1888 if (kind_ == GetInitialFastElementsKind()) { |
| 1847 // No need for a context lookup if the kind_ matches the initial | 1889 // No need for a context lookup if the kind_ matches the initial |
| 1848 // map, because we can just load the map in that case. | 1890 // map, because we can just load the map in that case. |
| 1849 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1891 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1850 return builder()->AddInstruction( | 1892 return builder()->AddInstruction( |
| 1851 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); | 1893 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1852 } | 1894 } |
| 1853 | 1895 |
| 1854 HInstruction* native_context = builder()->BuildGetNativeContext(); | 1896 HInstruction* native_context = builder()->BuildGetNativeContext(); |
| 1855 HInstruction* index = builder()->Add<HConstant>( | 1897 HInstruction* index = builder()->Add<HConstant>( |
| 1856 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 1898 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
| 1857 | 1899 |
| 1858 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 1900 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
| 1859 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1901 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1860 | 1902 |
| 1861 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 1903 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
| 1862 | 1904 |
| 1863 return builder()->Add<HLoadKeyed>( | 1905 return builder()->Add<HLoadKeyed>( |
| 1864 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1906 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1865 } | 1907 } |
| 1866 | 1908 |
| 1867 | 1909 |
| 1868 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { | 1910 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { |
| 1869 // Find the map near the constructor function | 1911 // Find the map near the constructor function |
| 1870 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 1912 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 1871 return builder()->AddInstruction( | 1913 return builder()->AddInstruction( |
| 1872 builder()->BuildLoadNamedField(constructor_function_, access, NULL)); | 1914 builder()->BuildLoadNamedField(constructor_function_, access)); |
| 1873 } | 1915 } |
| 1874 | 1916 |
| 1875 | 1917 |
| 1876 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( | 1918 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( |
| 1877 HValue* length_node) { | 1919 HValue* length_node) { |
| 1878 ASSERT(length_node != NULL); | 1920 ASSERT(length_node != NULL); |
| 1879 | 1921 |
| 1880 int base_size = JSArray::kSize; | 1922 int base_size = JSArray::kSize; |
| 1881 if (mode_ == TRACK_ALLOCATION_SITE) { | 1923 if (mode_ == TRACK_ALLOCATION_SITE) { |
| 1882 base_size += AllocationMemento::kSize; | 1924 base_size += AllocationMemento::kSize; |
| (...skipping 2424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4307 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4349 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
| 4308 // end, we want to quit creating allocation site info after a certain number | 4350 // end, we want to quit creating allocation site info after a certain number |
| 4309 // of GCs for a call site. | 4351 // of GCs for a call site. |
| 4310 AllocationSiteMode mode = AllocationSite::GetMode( | 4352 AllocationSiteMode mode = AllocationSite::GetMode( |
| 4311 boilerplate_elements_kind); | 4353 boilerplate_elements_kind); |
| 4312 | 4354 |
| 4313 // Check whether to use fast or slow deep-copying for boilerplate. | 4355 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4314 int data_size = 0; | 4356 int data_size = 0; |
| 4315 int pointer_size = 0; | 4357 int pointer_size = 0; |
| 4316 int max_properties = kMaxFastLiteralProperties; | 4358 int max_properties = kMaxFastLiteralProperties; |
| 4317 HCheckMaps* type_check = NULL; | |
| 4318 if (IsFastLiteral(original_boilerplate_object, | 4359 if (IsFastLiteral(original_boilerplate_object, |
| 4319 kMaxFastLiteralDepth, | 4360 kMaxFastLiteralDepth, |
| 4320 &max_properties, | 4361 &max_properties, |
| 4321 &data_size, | 4362 &data_size, |
| 4322 &pointer_size)) { | 4363 &pointer_size)) { |
| 4323 if (mode == TRACK_ALLOCATION_SITE) { | 4364 if (mode == TRACK_ALLOCATION_SITE) { |
| 4324 pointer_size += AllocationMemento::kSize; | 4365 pointer_size += AllocationMemento::kSize; |
| 4325 } | 4366 } |
| 4326 | 4367 |
| 4327 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4368 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4345 | 4386 |
| 4346 Runtime::FunctionId function_id = (expr->depth() > 1) | 4387 Runtime::FunctionId function_id = (expr->depth() > 1) |
| 4347 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4388 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
| 4348 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 4389 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 4349 Runtime::FunctionForId(function_id), | 4390 Runtime::FunctionForId(function_id), |
| 4350 3); | 4391 3); |
| 4351 | 4392 |
| 4352 // De-opt if elements kind changed from boilerplate_elements_kind. | 4393 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 4353 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4394 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
| 4354 isolate()); | 4395 isolate()); |
| 4355 type_check = Add<HCheckMaps>(literal, map, top_info()); | 4396 literal = Add<HCheckMaps>(literal, map, top_info()); |
| 4356 } | 4397 } |
| 4357 | 4398 |
| 4358 // The array is expected in the bailout environment during computation | 4399 // The array is expected in the bailout environment during computation |
| 4359 // of the property values and is the value of the entire expression. | 4400 // of the property values and is the value of the entire expression. |
| 4360 Push(literal); | 4401 Push(literal); |
| 4361 // The literal index is on the stack, too. | 4402 // The literal index is on the stack, too. |
| 4362 Push(Add<HConstant>(expr->literal_index())); | 4403 Push(Add<HConstant>(expr->literal_index())); |
| 4363 | 4404 |
| 4364 HInstruction* elements = NULL; | 4405 HInstruction* elements = NULL; |
| 4365 | 4406 |
| 4366 for (int i = 0; i < length; i++) { | 4407 for (int i = 0; i < length; i++) { |
| 4367 Expression* subexpr = subexprs->at(i); | 4408 Expression* subexpr = subexprs->at(i); |
| 4368 // If the subexpression is a literal or a simple materialized literal it | 4409 // If the subexpression is a literal or a simple materialized literal it |
| 4369 // is already set in the cloned array. | 4410 // is already set in the cloned array. |
| 4370 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 4411 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 4371 | 4412 |
| 4372 CHECK_ALIVE(VisitForValue(subexpr)); | 4413 CHECK_ALIVE(VisitForValue(subexpr)); |
| 4373 HValue* value = Pop(); | 4414 HValue* value = Pop(); |
| 4374 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); | 4415 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); |
| 4375 | 4416 |
| 4376 elements = AddLoadElements(literal, type_check); | 4417 elements = AddLoadElements(literal); |
| 4377 | 4418 |
| 4378 HValue* key = Add<HConstant>(i); | 4419 HValue* key = Add<HConstant>(i); |
| 4379 | 4420 |
| 4380 switch (boilerplate_elements_kind) { | 4421 switch (boilerplate_elements_kind) { |
| 4381 case FAST_SMI_ELEMENTS: | 4422 case FAST_SMI_ELEMENTS: |
| 4382 case FAST_HOLEY_SMI_ELEMENTS: | 4423 case FAST_HOLEY_SMI_ELEMENTS: |
| 4383 case FAST_ELEMENTS: | 4424 case FAST_ELEMENTS: |
| 4384 case FAST_HOLEY_ELEMENTS: | 4425 case FAST_HOLEY_ELEMENTS: |
| 4385 case FAST_DOUBLE_ELEMENTS: | 4426 case FAST_DOUBLE_ELEMENTS: |
| 4386 case FAST_HOLEY_DOUBLE_ELEMENTS: { | 4427 case FAST_HOLEY_DOUBLE_ELEMENTS: { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4428 | 4469 |
| 4429 | 4470 |
| 4430 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, | 4471 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, |
| 4431 Handle<Map> map) { | 4472 Handle<Map> map) { |
| 4432 BuildCheckHeapObject(object); | 4473 BuildCheckHeapObject(object); |
| 4433 return Add<HCheckMaps>(object, map, top_info()); | 4474 return Add<HCheckMaps>(object, map, top_info()); |
| 4434 } | 4475 } |
| 4435 | 4476 |
| 4436 | 4477 |
| 4437 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 4478 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
| 4438 HValue* object, | 4479 HValue* checked_object, |
| 4439 Handle<String> name, | 4480 Handle<String> name, |
| 4440 HValue* value, | 4481 HValue* value, |
| 4441 Handle<Map> map, | 4482 Handle<Map> map, |
| 4442 LookupResult* lookup) { | 4483 LookupResult* lookup) { |
| 4443 ASSERT(lookup->IsFound()); | 4484 ASSERT(lookup->IsFound()); |
| 4444 // If the property does not exist yet, we have to check that it wasn't made | 4485 // If the property does not exist yet, we have to check that it wasn't made |
| 4445 // readonly or turned into a setter by some meanwhile modifications on the | 4486 // readonly or turned into a setter by some meanwhile modifications on the |
| 4446 // prototype chain. | 4487 // prototype chain. |
| 4447 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { | 4488 if (!lookup->IsProperty() && map->prototype()->IsJSReceiver()) { |
| 4448 Object* proto = map->prototype(); | 4489 Object* proto = map->prototype(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4480 if (transition_to_field) { | 4521 if (transition_to_field) { |
| 4481 // The store requires a mutable HeapNumber to be allocated. | 4522 // The store requires a mutable HeapNumber to be allocated. |
| 4482 NoObservableSideEffectsScope no_side_effects(this); | 4523 NoObservableSideEffectsScope no_side_effects(this); |
| 4483 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); | 4524 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize); |
| 4484 HInstruction* heap_number = Add<HAllocate>(heap_number_size, | 4525 HInstruction* heap_number = Add<HAllocate>(heap_number_size, |
| 4485 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(), | 4526 HType::HeapNumber(), isolate()->heap()->GetPretenureMode(), |
| 4486 HEAP_NUMBER_TYPE); | 4527 HEAP_NUMBER_TYPE); |
| 4487 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); | 4528 AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map()); |
| 4488 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), | 4529 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), |
| 4489 value); | 4530 value); |
| 4490 instr = New<HStoreNamedField>(object, heap_number_access, | 4531 instr = New<HStoreNamedField>(checked_object->ActualValue(), |
| 4491 heap_number); | 4532 heap_number_access, |
| 4533 heap_number); |
| 4492 } else { | 4534 } else { |
| 4493 // Already holds a HeapNumber; load the box and write its value field. | 4535 // Already holds a HeapNumber; load the box and write its value field. |
| 4494 HInstruction* heap_number = Add<HLoadNamedField>(object, | 4536 HInstruction* heap_number = Add<HLoadNamedField>(checked_object, |
| 4495 heap_number_access); | 4537 heap_number_access); |
| 4496 heap_number->set_type(HType::HeapNumber()); | 4538 heap_number->set_type(HType::HeapNumber()); |
| 4497 instr = New<HStoreNamedField>(heap_number, | 4539 instr = New<HStoreNamedField>(heap_number, |
| 4498 HObjectAccess::ForHeapNumberValue(), | 4540 HObjectAccess::ForHeapNumberValue(), |
| 4499 value); | 4541 value); |
| 4500 } | 4542 } |
| 4501 } else { | 4543 } else { |
| 4502 // This is a normal store. | 4544 // This is a normal store. |
| 4503 instr = New<HStoreNamedField>(object, field_access, value); | 4545 instr = New<HStoreNamedField>(checked_object->ActualValue(), |
| 4546 field_access, |
| 4547 value); |
| 4504 } | 4548 } |
| 4505 | 4549 |
| 4506 if (transition_to_field) { | 4550 if (transition_to_field) { |
| 4507 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); | 4551 Handle<Map> transition(lookup->GetTransitionMapFromMap(*map)); |
| 4508 HConstant* transition_constant = Add<HConstant>(transition); | 4552 HConstant* transition_constant = Add<HConstant>(transition); |
| 4509 instr->SetTransition(transition_constant, top_info()); | 4553 instr->SetTransition(transition_constant, top_info()); |
| 4510 // TODO(fschneider): Record the new map type of the object in the IR to | 4554 // TODO(fschneider): Record the new map type of the object in the IR to |
| 4511 // enable elimination of redundant checks after the transition store. | 4555 // enable elimination of redundant checks after the transition store. |
| 4512 instr->SetGVNFlag(kChangesMaps); | 4556 instr->SetGVNFlag(kChangesMaps); |
| 4513 } | 4557 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4530 | 4574 |
| 4531 | 4575 |
| 4532 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( | 4576 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
| 4533 HValue* object, | 4577 HValue* object, |
| 4534 Handle<String> name, | 4578 Handle<String> name, |
| 4535 HValue* value, | 4579 HValue* value, |
| 4536 Handle<Map> map) { | 4580 Handle<Map> map) { |
| 4537 // Handle a store to a known field. | 4581 // Handle a store to a known field. |
| 4538 LookupResult lookup(isolate()); | 4582 LookupResult lookup(isolate()); |
| 4539 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 4583 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 4540 AddCheckMap(object, map); | 4584 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 4541 return BuildStoreNamedField(object, name, value, map, &lookup); | 4585 return BuildStoreNamedField(checked_object, name, value, map, &lookup); |
| 4542 } | 4586 } |
| 4543 | 4587 |
| 4544 // No luck, do a generic store. | 4588 // No luck, do a generic store. |
| 4545 return BuildStoreNamedGeneric(object, name, value); | 4589 return BuildStoreNamedGeneric(object, name, value); |
| 4546 } | 4590 } |
| 4547 | 4591 |
| 4548 | 4592 |
| 4549 static bool CanLoadPropertyFromPrototype(Handle<Map> map, | 4593 static bool CanLoadPropertyFromPrototype(Handle<Map> map, |
| 4550 Handle<Name> name, | 4594 Handle<Name> name, |
| 4551 LookupResult* lookup) { | 4595 LookupResult* lookup) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4589 // In-objectness did not match. | 4633 // In-objectness did not match. |
| 4590 break; | 4634 break; |
| 4591 } | 4635 } |
| 4592 access = access.WithRepresentation( | 4636 access = access.WithRepresentation( |
| 4593 access.representation().generalize(new_access.representation())); | 4637 access.representation().generalize(new_access.representation())); |
| 4594 } | 4638 } |
| 4595 | 4639 |
| 4596 if (count == types->length()) { | 4640 if (count == types->length()) { |
| 4597 // Everything matched; can use monomorphic load. | 4641 // Everything matched; can use monomorphic load. |
| 4598 BuildCheckHeapObject(object); | 4642 BuildCheckHeapObject(object); |
| 4599 HCheckMaps* type_check = Add<HCheckMaps>(object, types); | 4643 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); |
| 4600 return BuildLoadNamedField(object, access, type_check); | 4644 return BuildLoadNamedField(checked_object, access); |
| 4601 } | 4645 } |
| 4602 | 4646 |
| 4603 if (count != 0) return NULL; | 4647 if (count != 0) return NULL; |
| 4604 | 4648 |
| 4605 // Second chance: the property is on the prototype and all maps have the | 4649 // Second chance: the property is on the prototype and all maps have the |
| 4606 // same prototype. | 4650 // same prototype. |
| 4607 Handle<Map> map(types->at(0)); | 4651 Handle<Map> map(types->at(0)); |
| 4608 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; | 4652 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; |
| 4609 | 4653 |
| 4610 Handle<Object> prototype(map->prototype(), isolate()); | 4654 Handle<Object> prototype(map->prototype(), isolate()); |
| 4611 for (count = 1; count < types->length(); ++count) { | 4655 for (count = 1; count < types->length(); ++count) { |
| 4612 Handle<Map> test_map(types->at(count)); | 4656 Handle<Map> test_map(types->at(count)); |
| 4613 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; | 4657 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; |
| 4614 if (test_map->prototype() != *prototype) return NULL; | 4658 if (test_map->prototype() != *prototype) return NULL; |
| 4615 } | 4659 } |
| 4616 | 4660 |
| 4617 LookupInPrototypes(map, name, &lookup); | 4661 LookupInPrototypes(map, name, &lookup); |
| 4618 if (!lookup.IsField()) return NULL; | 4662 if (!lookup.IsField()) return NULL; |
| 4619 | 4663 |
| 4620 BuildCheckHeapObject(object); | 4664 BuildCheckHeapObject(object); |
| 4621 HCheckMaps* type_check = Add<HCheckMaps>(object, types); | 4665 Add<HCheckMaps>(object, types); |
| 4622 | 4666 |
| 4623 Handle<JSObject> holder(lookup.holder()); | 4667 Handle<JSObject> holder(lookup.holder()); |
| 4624 Handle<Map> holder_map(holder->map()); | 4668 Handle<Map> holder_map(holder->map()); |
| 4625 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); | 4669 HValue* checked_holder = BuildCheckPrototypeMaps( |
| 4626 HValue* holder_value = Add<HConstant>(holder); | 4670 Handle<JSObject>::cast(prototype), holder); |
| 4627 return BuildLoadNamedField(holder_value, | 4671 return BuildLoadNamedField(checked_holder, |
| 4628 HObjectAccess::ForField(holder_map, &lookup, name), type_check); | 4672 HObjectAccess::ForField(holder_map, &lookup, name)); |
| 4629 } | 4673 } |
| 4630 | 4674 |
| 4631 | 4675 |
| 4632 // Returns true if an instance of this map can never find a property with this | 4676 // Returns true if an instance of this map can never find a property with this |
| 4633 // name in its prototype chain. This means all prototypes up to the top are | 4677 // name in its prototype chain. This means all prototypes up to the top are |
| 4634 // fast and don't have the name in them. It would be good if we could optimize | 4678 // fast and don't have the name in them. It would be good if we could optimize |
| 4635 // polymorphic loads where the property is sometimes found in the prototype | 4679 // polymorphic loads where the property is sometimes found in the prototype |
| 4636 // chain. | 4680 // chain. |
| 4637 static bool PrototypeChainCanNeverResolve( | 4681 static bool PrototypeChainCanNeverResolve( |
| 4638 Handle<Map> map, Handle<String> name) { | 4682 Handle<Map> map, Handle<String> name) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4693 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4737 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4694 HCompareMap* compare = | 4738 HCompareMap* compare = |
| 4695 new(zone()) HCompareMap(object, map, if_true, if_false); | 4739 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 4696 current_block()->Finish(compare); | 4740 current_block()->Finish(compare); |
| 4697 | 4741 |
| 4698 set_current_block(if_true); | 4742 set_current_block(if_true); |
| 4699 | 4743 |
| 4700 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. | 4744 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. |
| 4701 if (lookup.IsField()) { | 4745 if (lookup.IsField()) { |
| 4702 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); | 4746 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); |
| 4703 HLoadNamedField* load = BuildLoadNamedField(object, access, compare); | 4747 HLoadNamedField* load = BuildLoadNamedField(compare, access); |
| 4704 load->set_position(expr->position()); | 4748 load->set_position(expr->position()); |
| 4705 AddInstruction(load); | 4749 AddInstruction(load); |
| 4706 if (!ast_context()->IsEffect()) Push(load); | 4750 if (!ast_context()->IsEffect()) Push(load); |
| 4707 } else if (lookup.IsConstant()) { | 4751 } else if (lookup.IsConstant()) { |
| 4708 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 4752 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
| 4709 HConstant* hconstant = Add<HConstant>(constant); | 4753 HConstant* hconstant = Add<HConstant>(constant); |
| 4710 if (!ast_context()->IsEffect()) Push(hconstant); | 4754 if (!ast_context()->IsEffect()) Push(hconstant); |
| 4711 } else { | 4755 } else { |
| 4712 ASSERT(!lookup.IsFound()); | 4756 ASSERT(!lookup.IsFound()); |
| 4713 if (map->prototype()->IsJSObject()) { | 4757 if (map->prototype()->IsJSObject()) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4793 } else if (access.IsInobject() != new_access.IsInobject()) { | 4837 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 4794 // In-objectness did not match. | 4838 // In-objectness did not match. |
| 4795 break; | 4839 break; |
| 4796 } | 4840 } |
| 4797 } | 4841 } |
| 4798 | 4842 |
| 4799 if (count != types->length()) return false; | 4843 if (count != types->length()) return false; |
| 4800 | 4844 |
| 4801 // Everything matched; can use monomorphic store. | 4845 // Everything matched; can use monomorphic store. |
| 4802 BuildCheckHeapObject(object); | 4846 BuildCheckHeapObject(object); |
| 4803 Add<HCheckMaps>(object, types); | 4847 HCheckMaps* checked_object = Add<HCheckMaps>(object, types); |
| 4804 HInstruction* store; | 4848 HInstruction* store; |
| 4805 CHECK_ALIVE_OR_RETURN( | 4849 CHECK_ALIVE_OR_RETURN( |
| 4806 store = BuildStoreNamedField( | 4850 store = BuildStoreNamedField( |
| 4807 object, name, store_value, types->at(count - 1), &lookup), | 4851 checked_object, name, store_value, types->at(count - 1), &lookup), |
| 4808 true); | 4852 true); |
| 4809 if (!ast_context()->IsEffect()) Push(result_value); | 4853 if (!ast_context()->IsEffect()) Push(result_value); |
| 4810 store->set_position(position); | 4854 store->set_position(position); |
| 4811 AddInstruction(store); | 4855 AddInstruction(store); |
| 4812 Add<HSimulate>(assignment_id); | 4856 Add<HSimulate>(assignment_id); |
| 4813 if (!ast_context()->IsEffect()) Drop(1); | 4857 if (!ast_context()->IsEffect()) Drop(1); |
| 4814 ast_context()->ReturnValue(result_value); | 4858 ast_context()->ReturnValue(result_value); |
| 4815 return true; | 4859 return true; |
| 4816 } | 4860 } |
| 4817 | 4861 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4846 ++count; | 4890 ++count; |
| 4847 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4891 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 4848 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4892 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4849 HCompareMap* compare = | 4893 HCompareMap* compare = |
| 4850 new(zone()) HCompareMap(object, map, if_true, if_false); | 4894 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 4851 current_block()->Finish(compare); | 4895 current_block()->Finish(compare); |
| 4852 | 4896 |
| 4853 set_current_block(if_true); | 4897 set_current_block(if_true); |
| 4854 HInstruction* instr; | 4898 HInstruction* instr; |
| 4855 CHECK_ALIVE(instr = BuildStoreNamedField( | 4899 CHECK_ALIVE(instr = BuildStoreNamedField( |
| 4856 object, name, store_value, map, &lookup)); | 4900 compare, name, store_value, map, &lookup)); |
| 4857 instr->set_position(position); | 4901 instr->set_position(position); |
| 4858 // Goto will add the HSimulate for the store. | 4902 // Goto will add the HSimulate for the store. |
| 4859 AddInstruction(instr); | 4903 AddInstruction(instr); |
| 4860 if (!ast_context()->IsEffect()) Push(result_value); | 4904 if (!ast_context()->IsEffect()) Push(result_value); |
| 4861 current_block()->Goto(join); | 4905 current_block()->Goto(join); |
| 4862 | 4906 |
| 4863 set_current_block(if_false); | 4907 set_current_block(if_false); |
| 4864 } | 4908 } |
| 4865 } | 4909 } |
| 4866 | 4910 |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5366 HValue* value = environment()->Pop(); | 5410 HValue* value = environment()->Pop(); |
| 5367 HThrow* instr = Add<HThrow>(value); | 5411 HThrow* instr = Add<HThrow>(value); |
| 5368 instr->set_position(expr->position()); | 5412 instr->set_position(expr->position()); |
| 5369 Add<HSimulate>(expr->id()); | 5413 Add<HSimulate>(expr->id()); |
| 5370 current_block()->FinishExit(new(zone()) HAbnormalExit); | 5414 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5371 set_current_block(NULL); | 5415 set_current_block(NULL); |
| 5372 } | 5416 } |
| 5373 | 5417 |
| 5374 | 5418 |
| 5375 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5419 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5376 HObjectAccess access, | 5420 HObjectAccess access) { |
| 5377 HValue* typecheck) { | |
| 5378 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5421 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
| 5379 // load the heap number | 5422 // load the heap number |
| 5380 HLoadNamedField* heap_number = Add<HLoadNamedField>( | 5423 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
| 5381 object, access.WithRepresentation(Representation::Tagged())); | 5424 object, access.WithRepresentation(Representation::Tagged())); |
| 5382 heap_number->set_type(HType::HeapNumber()); | 5425 heap_number->set_type(HType::HeapNumber()); |
| 5383 // load the double value from it | 5426 // load the double value from it |
| 5384 return New<HLoadNamedField>(heap_number, | 5427 return New<HLoadNamedField>( |
| 5385 HObjectAccess::ForHeapNumberValue(), | 5428 heap_number, HObjectAccess::ForHeapNumberValue()); |
| 5386 typecheck); | |
| 5387 } | 5429 } |
| 5388 return New<HLoadNamedField>(object, access, typecheck); | 5430 return New<HLoadNamedField>(object, access); |
| 5389 } | 5431 } |
| 5390 | 5432 |
| 5391 | 5433 |
| 5392 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, | 5434 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* object, |
| 5393 HValue* typecheck) { | 5435 HValue* checked_string) { |
| 5394 if (FLAG_fold_constants && object->IsConstant()) { | 5436 if (FLAG_fold_constants && object->IsConstant()) { |
| 5395 HConstant* constant = HConstant::cast(object); | 5437 HConstant* constant = HConstant::cast(object); |
| 5396 if (constant->HasStringValue()) { | 5438 if (constant->HasStringValue()) { |
| 5397 return New<HConstant>(constant->StringValue()->length()); | 5439 return New<HConstant>(constant->StringValue()->length()); |
| 5398 } | 5440 } |
| 5399 } | 5441 } |
| 5400 return BuildLoadNamedField( | 5442 return BuildLoadNamedField(checked_string, HObjectAccess::ForStringLength()); |
| 5401 object, HObjectAccess::ForStringLength(), typecheck); | |
| 5402 } | 5443 } |
| 5403 | 5444 |
| 5404 | 5445 |
| 5405 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5446 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 5406 HValue* object, | 5447 HValue* object, |
| 5407 Handle<String> name, | 5448 Handle<String> name, |
| 5408 Property* expr) { | 5449 Property* expr) { |
| 5409 if (expr->IsUninitialized()) { | 5450 if (expr->IsUninitialized()) { |
| 5410 Add<HDeoptimize>("Insufficient feedback for generic named load", | 5451 Add<HDeoptimize>("Insufficient feedback for generic named load", |
| 5411 Deoptimizer::SOFT); | 5452 Deoptimizer::SOFT); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5430 HValue* object, | 5471 HValue* object, |
| 5431 Handle<String> name, | 5472 Handle<String> name, |
| 5432 Property* expr, | 5473 Property* expr, |
| 5433 Handle<Map> map) { | 5474 Handle<Map> map) { |
| 5434 // Handle a load from a known field. | 5475 // Handle a load from a known field. |
| 5435 ASSERT(!map->is_dictionary_map()); | 5476 ASSERT(!map->is_dictionary_map()); |
| 5436 | 5477 |
| 5437 // Handle access to various length properties | 5478 // Handle access to various length properties |
| 5438 if (name->Equals(isolate()->heap()->length_string())) { | 5479 if (name->Equals(isolate()->heap()->length_string())) { |
| 5439 if (map->instance_type() == JS_ARRAY_TYPE) { | 5480 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 5440 HCheckMaps* type_check = AddCheckMap(object, map); | 5481 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5441 return New<HLoadNamedField>(object, | 5482 return New<HLoadNamedField>( |
| 5442 HObjectAccess::ForArrayLength(map->elements_kind()), type_check); | 5483 checked_object, HObjectAccess::ForArrayLength(map->elements_kind())); |
| 5443 } | 5484 } |
| 5444 } | 5485 } |
| 5445 | 5486 |
| 5446 LookupResult lookup(isolate()); | 5487 LookupResult lookup(isolate()); |
| 5447 map->LookupDescriptor(NULL, *name, &lookup); | 5488 map->LookupDescriptor(NULL, *name, &lookup); |
| 5448 if (lookup.IsField()) { | 5489 if (lookup.IsField()) { |
| 5449 HCheckMaps* type_check = AddCheckMap(object, map); | 5490 HCheckMaps* checked_object = AddCheckMap(object, map); |
| 5450 return BuildLoadNamedField(object, | 5491 return BuildLoadNamedField( |
| 5451 HObjectAccess::ForField(map, &lookup, name), type_check); | 5492 checked_object, HObjectAccess::ForField(map, &lookup, name)); |
| 5452 } | 5493 } |
| 5453 | 5494 |
| 5454 // Handle a load of a constant known function. | 5495 // Handle a load of a constant known function. |
| 5455 if (lookup.IsConstant()) { | 5496 if (lookup.IsConstant()) { |
| 5456 AddCheckMap(object, map); | 5497 AddCheckMap(object, map); |
| 5457 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); | 5498 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); |
| 5458 return New<HConstant>(constant); | 5499 return New<HConstant>(constant); |
| 5459 } | 5500 } |
| 5460 | 5501 |
| 5461 // Handle a load from a known field somewhere in the prototype chain. | 5502 // Handle a load from a known field somewhere in the prototype chain. |
| 5462 LookupInPrototypes(map, name, &lookup); | 5503 LookupInPrototypes(map, name, &lookup); |
| 5463 if (lookup.IsField()) { | 5504 if (lookup.IsField()) { |
| 5464 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5505 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 5465 Handle<JSObject> holder(lookup.holder()); | 5506 Handle<JSObject> holder(lookup.holder()); |
| 5466 Handle<Map> holder_map(holder->map()); | 5507 Handle<Map> holder_map(holder->map()); |
| 5467 HCheckMaps* type_check = AddCheckMap(object, map); | 5508 AddCheckMap(object, map); |
| 5468 BuildCheckPrototypeMaps(prototype, holder); | 5509 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder); |
| 5469 HValue* holder_value = Add<HConstant>(holder); | 5510 return BuildLoadNamedField( |
| 5470 return BuildLoadNamedField(holder_value, | 5511 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name)); |
| 5471 HObjectAccess::ForField(holder_map, &lookup, name), type_check); | |
| 5472 } | 5512 } |
| 5473 | 5513 |
| 5474 // Handle a load of a constant function somewhere in the prototype chain. | 5514 // Handle a load of a constant function somewhere in the prototype chain. |
| 5475 if (lookup.IsConstant()) { | 5515 if (lookup.IsConstant()) { |
| 5476 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 5516 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| 5477 Handle<JSObject> holder(lookup.holder()); | 5517 Handle<JSObject> holder(lookup.holder()); |
| 5478 Handle<Map> holder_map(holder->map()); | 5518 Handle<Map> holder_map(holder->map()); |
| 5479 AddCheckMap(object, map); | 5519 AddCheckMap(object, map); |
| 5480 BuildCheckPrototypeMaps(prototype, holder); | 5520 BuildCheckPrototypeMaps(prototype, holder); |
| 5481 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); | 5521 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); |
| 5482 return New<HConstant>(constant); | 5522 return New<HConstant>(constant); |
| 5483 } | 5523 } |
| 5484 | 5524 |
| 5485 // No luck, do a generic load. | 5525 // No luck, do a generic load. |
| 5486 return BuildLoadNamedGeneric(object, name, expr); | 5526 return BuildLoadNamedGeneric(object, name, expr); |
| 5487 } | 5527 } |
| 5488 | 5528 |
| 5489 | 5529 |
| 5490 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5530 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 5491 HValue* key) { | 5531 HValue* key) { |
| 5492 HValue* context = environment()->context(); | 5532 HValue* context = environment()->context(); |
| 5493 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5533 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 5494 } | 5534 } |
| 5495 | 5535 |
| 5496 | 5536 |
| 5497 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 5537 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
| 5498 HValue* object, | |
| 5499 HValue* key, | |
| 5500 HValue* val, | |
| 5501 HValue* dependency, | |
| 5502 Handle<Map> map, | |
| 5503 bool is_store, | |
| 5504 KeyedAccessStoreMode store_mode) { | |
| 5505 HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency); | |
| 5506 if (dependency) { | |
| 5507 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | |
| 5508 } | |
| 5509 | |
| 5510 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5538 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| 5511 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 5539 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
| 5512 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 5540 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
| 5513 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { | 5541 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { |
| 5514 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); | 5542 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); |
| 5515 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); | 5543 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); |
| 5516 BuildCheckPrototypeMaps(prototype, object_prototype); | 5544 BuildCheckPrototypeMaps(prototype, object_prototype); |
| 5517 load_mode = ALLOW_RETURN_HOLE; | 5545 load_mode = ALLOW_RETURN_HOLE; |
| 5518 graph()->MarkDependsOnEmptyArrayProtoElements(); | 5546 graph()->MarkDependsOnEmptyArrayProtoElements(); |
| 5519 } | 5547 } |
| 5520 | 5548 |
| 5521 return BuildUncheckedMonomorphicElementAccess( | 5549 return load_mode; |
| 5522 object, key, val, | |
| 5523 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | |
| 5524 map->elements_kind(), is_store, load_mode, store_mode); | |
| 5525 } | 5550 } |
| 5526 | 5551 |
| 5527 | 5552 |
| 5553 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
| 5554 HValue* object, |
| 5555 HValue* key, |
| 5556 HValue* val, |
| 5557 HValue* dependency, |
| 5558 Handle<Map> map, |
| 5559 bool is_store, |
| 5560 KeyedAccessStoreMode store_mode) { |
| 5561 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), |
| 5562 dependency); |
| 5563 if (dependency) { |
| 5564 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 5565 } |
| 5566 |
| 5567 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
| 5568 return BuildUncheckedMonomorphicElementAccess( |
| 5569 checked_object, key, val, |
| 5570 map->instance_type() == JS_ARRAY_TYPE, |
| 5571 map->elements_kind(), is_store, |
| 5572 load_mode, store_mode); |
| 5573 } |
| 5574 |
| 5575 |
| 5528 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 5576 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
| 5529 HValue* object, | 5577 HValue* object, |
| 5530 HValue* key, | 5578 HValue* key, |
| 5531 HValue* val, | 5579 HValue* val, |
| 5532 SmallMapList* maps) { | 5580 SmallMapList* maps) { |
| 5533 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 5581 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
| 5534 // double), always use the "worst case" code without a transition. This is | 5582 // double), always use the "worst case" code without a transition. This is |
| 5535 // much faster than transitioning the elements to the worst case, trading a | 5583 // much faster than transitioning the elements to the worst case, trading a |
| 5536 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. | 5584 // HTransitionElements for a HCheckMaps, and avoiding mutation of the array. |
| 5537 bool has_double_maps = false; | 5585 bool has_double_maps = false; |
| 5538 bool has_smi_or_object_maps = false; | 5586 bool has_smi_or_object_maps = false; |
| 5539 bool has_js_array_access = false; | 5587 bool has_js_array_access = false; |
| 5540 bool has_non_js_array_access = false; | 5588 bool has_non_js_array_access = false; |
| 5589 bool has_seen_holey_elements = false; |
| 5541 Handle<Map> most_general_consolidated_map; | 5590 Handle<Map> most_general_consolidated_map; |
| 5542 for (int i = 0; i < maps->length(); ++i) { | 5591 for (int i = 0; i < maps->length(); ++i) { |
| 5543 Handle<Map> map = maps->at(i); | 5592 Handle<Map> map = maps->at(i); |
| 5544 // Don't allow mixing of JSArrays with JSObjects. | 5593 // Don't allow mixing of JSArrays with JSObjects. |
| 5545 if (map->instance_type() == JS_ARRAY_TYPE) { | 5594 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 5546 if (has_non_js_array_access) return NULL; | 5595 if (has_non_js_array_access) return NULL; |
| 5547 has_js_array_access = true; | 5596 has_js_array_access = true; |
| 5548 } else if (has_js_array_access) { | 5597 } else if (has_js_array_access) { |
| 5549 return NULL; | 5598 return NULL; |
| 5550 } else { | 5599 } else { |
| 5551 has_non_js_array_access = true; | 5600 has_non_js_array_access = true; |
| 5552 } | 5601 } |
| 5553 // Don't allow mixed, incompatible elements kinds. | 5602 // Don't allow mixed, incompatible elements kinds. |
| 5554 if (map->has_fast_double_elements()) { | 5603 if (map->has_fast_double_elements()) { |
| 5555 if (has_smi_or_object_maps) return NULL; | 5604 if (has_smi_or_object_maps) return NULL; |
| 5556 has_double_maps = true; | 5605 has_double_maps = true; |
| 5557 } else if (map->has_fast_smi_or_object_elements()) { | 5606 } else if (map->has_fast_smi_or_object_elements()) { |
| 5558 if (has_double_maps) return NULL; | 5607 if (has_double_maps) return NULL; |
| 5559 has_smi_or_object_maps = true; | 5608 has_smi_or_object_maps = true; |
| 5560 } else { | 5609 } else { |
| 5561 return NULL; | 5610 return NULL; |
| 5562 } | 5611 } |
| 5612 // Remember if we've ever seen holey elements. |
| 5613 if (IsHoleyElementsKind(map->elements_kind())) { |
| 5614 has_seen_holey_elements = true; |
| 5615 } |
| 5563 // Remember the most general elements kind, the code for its load will | 5616 // Remember the most general elements kind, the code for its load will |
| 5564 // properly handle all of the more specific cases. | 5617 // properly handle all of the more specific cases. |
| 5565 if ((i == 0) || IsMoreGeneralElementsKindTransition( | 5618 if ((i == 0) || IsMoreGeneralElementsKindTransition( |
| 5566 most_general_consolidated_map->elements_kind(), | 5619 most_general_consolidated_map->elements_kind(), |
| 5567 map->elements_kind())) { | 5620 map->elements_kind())) { |
| 5568 most_general_consolidated_map = map; | 5621 most_general_consolidated_map = map; |
| 5569 } | 5622 } |
| 5570 } | 5623 } |
| 5571 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 5624 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
| 5572 | 5625 |
| 5573 HCheckMaps* check_maps = Add<HCheckMaps>(object, maps); | 5626 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); |
| 5627 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. |
| 5628 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. |
| 5629 ElementsKind consolidated_elements_kind = has_seen_holey_elements |
| 5630 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) |
| 5631 : most_general_consolidated_map->elements_kind(); |
| 5574 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 5632 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
| 5575 object, key, val, check_maps, | 5633 checked_object, key, val, |
| 5576 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 5634 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
| 5577 most_general_consolidated_map->elements_kind(), | 5635 consolidated_elements_kind, |
| 5578 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 5636 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 5579 return instr; | 5637 return instr; |
| 5580 } | 5638 } |
| 5581 | 5639 |
| 5582 | 5640 |
| 5583 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 5641 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 5584 HValue* object, | 5642 HValue* object, |
| 5585 HValue* key, | 5643 HValue* key, |
| 5586 HValue* val, | 5644 HValue* val, |
| 5587 Expression* prop, | 5645 Expression* prop, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5654 } else { | 5712 } else { |
| 5655 instr = BuildMonomorphicElementAccess( | 5713 instr = BuildMonomorphicElementAccess( |
| 5656 object, key, val, transition, untransitionable_map, is_store, | 5714 object, key, val, transition, untransitionable_map, is_store, |
| 5657 store_mode); | 5715 store_mode); |
| 5658 } | 5716 } |
| 5659 *has_side_effects |= instr->HasObservableSideEffects(); | 5717 *has_side_effects |= instr->HasObservableSideEffects(); |
| 5660 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5718 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
| 5661 return is_store ? NULL : instr; | 5719 return is_store ? NULL : instr; |
| 5662 } | 5720 } |
| 5663 | 5721 |
| 5664 HInstruction* checkspec = | |
| 5665 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | |
| 5666 HBasicBlock* join = graph()->CreateBasicBlock(); | 5722 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 5667 | 5723 |
| 5668 HInstruction* elements = AddLoadElements(object, checkspec); | |
| 5669 | |
| 5670 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 5724 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
| 5671 Handle<Map> map = untransitionable_maps[i]; | 5725 Handle<Map> map = untransitionable_maps[i]; |
| 5672 ElementsKind elements_kind = map->elements_kind(); | 5726 ElementsKind elements_kind = map->elements_kind(); |
| 5673 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 5727 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
| 5674 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 5728 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
| 5675 HCompareMap* mapcompare = | 5729 HCompareMap* mapcompare = |
| 5676 new(zone()) HCompareMap(object, map, this_map, other_map); | 5730 new(zone()) HCompareMap(object, map, this_map, other_map); |
| 5677 current_block()->Finish(mapcompare); | 5731 current_block()->Finish(mapcompare); |
| 5678 | 5732 |
| 5679 set_current_block(this_map); | 5733 set_current_block(this_map); |
| 5680 HInstruction* checked_key = NULL; | |
| 5681 HInstruction* access = NULL; | 5734 HInstruction* access = NULL; |
| 5682 if (IsFastElementsKind(elements_kind)) { | 5735 if (IsDictionaryElementsKind(elements_kind)) { |
| 5683 if (is_store && !IsFastDoubleElementsKind(elements_kind)) { | 5736 access = is_store |
| 5684 Add<HCheckMaps>( | 5737 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) |
| 5685 elements, isolate()->factory()->fixed_array_map(), | 5738 : AddInstruction(BuildLoadKeyedGeneric(object, key)); |
| 5686 top_info(), mapcompare); | |
| 5687 } | |
| 5688 if (map->instance_type() == JS_ARRAY_TYPE) { | |
| 5689 HInstruction* length = Add<HLoadNamedField>( | |
| 5690 object, HObjectAccess::ForArrayLength(elements_kind), mapcompare); | |
| 5691 checked_key = Add<HBoundsCheck>(key, length); | |
| 5692 } else { | |
| 5693 HInstruction* length = AddLoadFixedArrayLength(elements); | |
| 5694 checked_key = Add<HBoundsCheck>(key, length); | |
| 5695 } | |
| 5696 access = AddFastElementAccess( | |
| 5697 elements, checked_key, val, mapcompare, | |
| 5698 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE); | |
| 5699 } else if (IsDictionaryElementsKind(elements_kind)) { | |
| 5700 if (is_store) { | |
| 5701 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | |
| 5702 } else { | |
| 5703 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | |
| 5704 } | |
| 5705 } else { | 5739 } else { |
| 5706 ASSERT(IsExternalArrayElementsKind(elements_kind)); | 5740 ASSERT(IsFastElementsKind(elements_kind) || |
| 5707 HInstruction* length = AddLoadFixedArrayLength(elements); | 5741 IsExternalArrayElementsKind(elements_kind)); |
| 5708 checked_key = Add<HBoundsCheck>(key, length); | 5742 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
| 5709 HLoadExternalArrayPointer* external_elements = | 5743 // Happily, mapcompare is a checked object. |
| 5710 Add<HLoadExternalArrayPointer>(elements); | 5744 access = BuildUncheckedMonomorphicElementAccess( |
| 5711 access = AddExternalArrayElementAccess( | 5745 mapcompare, key, val, |
| 5712 external_elements, checked_key, val, | 5746 map->instance_type() == JS_ARRAY_TYPE, |
| 5713 mapcompare, elements_kind, is_store); | 5747 elements_kind, is_store, |
| 5748 load_mode, |
| 5749 store_mode); |
| 5714 } | 5750 } |
| 5715 *has_side_effects |= access->HasObservableSideEffects(); | 5751 *has_side_effects |= access->HasObservableSideEffects(); |
| 5716 // The caller will use has_side_effects and add a correct Simulate. | 5752 // The caller will use has_side_effects and add a correct Simulate. |
| 5717 access->SetFlag(HValue::kHasNoObservableSideEffects); | 5753 access->SetFlag(HValue::kHasNoObservableSideEffects); |
| 5718 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5754 if (position != RelocInfo::kNoPosition) access->set_position(position); |
| 5719 if (!is_store) { | 5755 if (!is_store) { |
| 5720 Push(access); | 5756 Push(access); |
| 5721 } | 5757 } |
| 5722 NoObservableSideEffectsScope scope(this); | 5758 NoObservableSideEffectsScope scope(this); |
| 5723 current_block()->GotoNoSimulate(join); | 5759 current_block()->GotoNoSimulate(join); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5956 Drop(1); | 5992 Drop(1); |
| 5957 } | 5993 } |
| 5958 } | 5994 } |
| 5959 return ast_context()->ReturnValue(load); | 5995 return ast_context()->ReturnValue(load); |
| 5960 } | 5996 } |
| 5961 instr->set_position(expr->position()); | 5997 instr->set_position(expr->position()); |
| 5962 return ast_context()->ReturnInstruction(instr, expr->id()); | 5998 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5963 } | 5999 } |
| 5964 | 6000 |
| 5965 | 6001 |
| 5966 void HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 6002 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
| 5967 CompilationInfo* info) { | 6003 CompilationInfo* info) { |
| 5968 HConstant* constant_value = New<HConstant>(constant); | 6004 HConstant* constant_value = New<HConstant>(constant); |
| 5969 | 6005 |
| 5970 if (constant->map()->CanOmitMapChecks()) { | 6006 if (constant->map()->CanOmitMapChecks()) { |
| 5971 constant->map()->AddDependentCompilationInfo( | 6007 constant->map()->AddDependentCompilationInfo( |
| 5972 DependentCode::kPrototypeCheckGroup, info); | 6008 DependentCode::kPrototypeCheckGroup, info); |
| 5973 return; | 6009 return constant_value; |
| 5974 } | 6010 } |
| 5975 | 6011 |
| 5976 AddInstruction(constant_value); | 6012 AddInstruction(constant_value); |
| 5977 HCheckMaps* check = | 6013 HCheckMaps* check = |
| 5978 Add<HCheckMaps>(constant_value, handle(constant->map()), info); | 6014 Add<HCheckMaps>(constant_value, handle(constant->map()), info); |
| 5979 check->ClearGVNFlag(kDependsOnElementsKind); | 6015 check->ClearGVNFlag(kDependsOnElementsKind); |
| 6016 return check; |
| 5980 } | 6017 } |
| 5981 | 6018 |
| 5982 | 6019 |
| 5983 void HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, | 6020 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
| 5984 Handle<JSObject> holder) { | 6021 Handle<JSObject> holder) { |
| 5985 BuildConstantMapCheck(prototype, top_info()); | |
| 5986 while (!prototype.is_identical_to(holder)) { | 6022 while (!prototype.is_identical_to(holder)) { |
| 6023 BuildConstantMapCheck(prototype, top_info()); |
| 5987 prototype = handle(JSObject::cast(prototype->GetPrototype())); | 6024 prototype = handle(JSObject::cast(prototype->GetPrototype())); |
| 5988 BuildConstantMapCheck(prototype, top_info()); | |
| 5989 } | 6025 } |
| 6026 |
| 6027 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info()); |
| 6028 if (!checked_object->IsLinked()) AddInstruction(checked_object); |
| 6029 return checked_object; |
| 5990 } | 6030 } |
| 5991 | 6031 |
| 5992 | 6032 |
| 5993 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6033 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 5994 Handle<Map> receiver_map) { | 6034 Handle<Map> receiver_map) { |
| 5995 if (!holder.is_null()) { | 6035 if (!holder.is_null()) { |
| 5996 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 6036 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 5997 BuildCheckPrototypeMaps(prototype, holder); | 6037 BuildCheckPrototypeMaps(prototype, holder); |
| 5998 } | 6038 } |
| 5999 } | 6039 } |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6805 HInstruction* sqrt = | 6845 HInstruction* sqrt = |
| 6806 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); | 6846 HUnaryMathOperation::New(zone(), context, left, kMathPowHalf); |
| 6807 AddInstruction(sqrt); | 6847 AddInstruction(sqrt); |
| 6808 // MathPowHalf doesn't have side effects so there's no need for | 6848 // MathPowHalf doesn't have side effects so there's no need for |
| 6809 // an environment simulation here. | 6849 // an environment simulation here. |
| 6810 ASSERT(!sqrt->HasObservableSideEffects()); | 6850 ASSERT(!sqrt->HasObservableSideEffects()); |
| 6811 result = HDiv::New(zone(), context, one, sqrt); | 6851 result = HDiv::New(zone(), context, one, sqrt); |
| 6812 } else if (exponent == 2.0) { | 6852 } else if (exponent == 2.0) { |
| 6813 result = HMul::New(zone(), context, left, left); | 6853 result = HMul::New(zone(), context, left, left); |
| 6814 } | 6854 } |
| 6815 } else if (right->EqualsInteger32Constant(2)) { | |
| 6816 result = HMul::New(zone(), context, left, left); | |
| 6817 } | 6855 } |
| 6818 | 6856 |
| 6819 if (result == NULL) { | 6857 if (result == NULL) { |
| 6820 result = HPower::New(zone(), context, left, right); | 6858 result = HPower::New(zone(), context, left, right); |
| 6821 } | 6859 } |
| 6822 ast_context()->ReturnInstruction(result, expr->id()); | 6860 ast_context()->ReturnInstruction(result, expr->id()); |
| 6823 return true; | 6861 return true; |
| 6824 } | 6862 } |
| 6825 break; | 6863 break; |
| 6826 case kMathRandom: | 6864 case kMathRandom: |
| (...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7485 } | 7523 } |
| 7486 Push(number_input); | 7524 Push(number_input); |
| 7487 } | 7525 } |
| 7488 | 7526 |
| 7489 // The addition has no side effects, so we do not need | 7527 // The addition has no side effects, so we do not need |
| 7490 // to simulate the expression stack after this instruction. | 7528 // to simulate the expression stack after this instruction. |
| 7491 // Any later failures deopt to the load of the input or earlier. | 7529 // Any later failures deopt to the load of the input or earlier. |
| 7492 HConstant* delta = (expr->op() == Token::INC) | 7530 HConstant* delta = (expr->op() == Token::INC) |
| 7493 ? graph()->GetConstant1() | 7531 ? graph()->GetConstant1() |
| 7494 : graph()->GetConstantMinus1(); | 7532 : graph()->GetConstantMinus1(); |
| 7495 HInstruction* instr = Add<HAdd>(Top(), delta); | 7533 HInstruction* instr = AddUncasted<HAdd>(Top(), delta); |
| 7534 if (instr->IsAdd()) { |
| 7535 HAdd* add = HAdd::cast(instr); |
| 7536 add->set_observed_input_representation(1, rep); |
| 7537 add->set_observed_input_representation(2, Representation::Smi()); |
| 7538 } |
| 7496 instr->SetFlag(HInstruction::kCannotBeTagged); | 7539 instr->SetFlag(HInstruction::kCannotBeTagged); |
| 7497 instr->ClearAllSideEffects(); | 7540 instr->ClearAllSideEffects(); |
| 7498 return instr; | 7541 return instr; |
| 7499 } | 7542 } |
| 7500 | 7543 |
| 7501 | 7544 |
| 7502 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7545 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 7503 ASSERT(!HasStackOverflow()); | 7546 ASSERT(!HasStackOverflow()); |
| 7504 ASSERT(current_block() != NULL); | 7547 ASSERT(current_block() != NULL); |
| 7505 ASSERT(current_block()->HasPredecessor()); | 7548 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8197 | 8240 |
| 8198 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 8241 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 8199 Expression* sub_expr, | 8242 Expression* sub_expr, |
| 8200 NilValue nil) { | 8243 NilValue nil) { |
| 8201 ASSERT(!HasStackOverflow()); | 8244 ASSERT(!HasStackOverflow()); |
| 8202 ASSERT(current_block() != NULL); | 8245 ASSERT(current_block() != NULL); |
| 8203 ASSERT(current_block()->HasPredecessor()); | 8246 ASSERT(current_block()->HasPredecessor()); |
| 8204 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 8247 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 8205 CHECK_ALIVE(VisitForValue(sub_expr)); | 8248 CHECK_ALIVE(VisitForValue(sub_expr)); |
| 8206 HValue* value = Pop(); | 8249 HValue* value = Pop(); |
| 8207 HIfContinuation continuation; | |
| 8208 if (expr->op() == Token::EQ_STRICT) { | 8250 if (expr->op() == Token::EQ_STRICT) { |
| 8209 IfBuilder if_nil(this); | 8251 HConstant* nil_constant = nil == kNullValue |
| 8210 if_nil.If<HCompareObjectEqAndBranch>( | 8252 ? graph()->GetConstantNull() |
| 8211 value, (nil == kNullValue) ? graph()->GetConstantNull() | 8253 : graph()->GetConstantUndefined(); |
| 8212 : graph()->GetConstantUndefined()); | 8254 HCompareObjectEqAndBranch* instr = |
| 8213 if_nil.Then(); | 8255 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 8214 if_nil.Else(); | 8256 instr->set_position(expr->position()); |
| 8215 if_nil.CaptureContinuation(&continuation); | 8257 return ast_context()->ReturnControl(instr, expr->id()); |
| 8258 } else { |
| 8259 ASSERT_EQ(Token::EQ, expr->op()); |
| 8260 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 8261 ? handle(Type::Any(), isolate_) |
| 8262 : expr->combined_type(); |
| 8263 HIfContinuation continuation; |
| 8264 BuildCompareNil(value, type, expr->position(), &continuation); |
| 8216 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 8265 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 8217 } | 8266 } |
| 8218 Handle<Type> type = expr->combined_type()->Is(Type::None()) | |
| 8219 ? handle(Type::Any(), isolate_) : expr->combined_type(); | |
| 8220 BuildCompareNil(value, type, expr->position(), &continuation); | |
| 8221 return ast_context()->ReturnContinuation(&continuation, expr->id()); | |
| 8222 } | 8267 } |
| 8223 | 8268 |
| 8224 | 8269 |
| 8225 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 8270 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 8226 // If we share optimized code between different closures, the | 8271 // If we share optimized code between different closures, the |
| 8227 // this-function is not a constant, except inside an inlined body. | 8272 // this-function is not a constant, except inside an inlined body. |
| 8228 if (function_state()->outer() != NULL) { | 8273 if (function_state()->outer() != NULL) { |
| 8229 return New<HConstant>( | 8274 return New<HConstant>( |
| 8230 function_state()->compilation_info()->closure()); | 8275 function_state()->compilation_info()->closure()); |
| 8231 } else { | 8276 } else { |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9550 } else { | 9595 } else { |
| 9551 CodeStub::Major major_key = info->code_stub()->MajorKey(); | 9596 CodeStub::Major major_key = info->code_stub()->MajorKey(); |
| 9552 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | 9597 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); |
| 9553 PrintStringProperty("method", "stub"); | 9598 PrintStringProperty("method", "stub"); |
| 9554 } | 9599 } |
| 9555 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); | 9600 PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); |
| 9556 } | 9601 } |
| 9557 | 9602 |
| 9558 | 9603 |
| 9559 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 9604 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
| 9560 ASSERT(!FLAG_parallel_recompilation); | 9605 ASSERT(!FLAG_concurrent_recompilation); |
| 9561 AllowHandleDereference allow_deref; | 9606 AllowHandleDereference allow_deref; |
| 9562 AllowDeferredHandleDereference allow_deferred_deref; | 9607 AllowDeferredHandleDereference allow_deferred_deref; |
| 9563 Trace(name, chunk->graph(), chunk); | 9608 Trace(name, chunk->graph(), chunk); |
| 9564 } | 9609 } |
| 9565 | 9610 |
| 9566 | 9611 |
| 9567 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 9612 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
| 9568 ASSERT(!FLAG_parallel_recompilation); | 9613 ASSERT(!FLAG_concurrent_recompilation); |
| 9569 AllowHandleDereference allow_deref; | 9614 AllowHandleDereference allow_deref; |
| 9570 AllowDeferredHandleDereference allow_deferred_deref; | 9615 AllowDeferredHandleDereference allow_deferred_deref; |
| 9571 Trace(name, graph, NULL); | 9616 Trace(name, graph, NULL); |
| 9572 } | 9617 } |
| 9573 | 9618 |
| 9574 | 9619 |
| 9575 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { | 9620 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { |
| 9576 Tag tag(this, "cfg"); | 9621 Tag tag(this, "cfg"); |
| 9577 PrintStringProperty("name", name); | 9622 PrintStringProperty("name", name); |
| 9578 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); | 9623 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9845 if (ShouldProduceTraceOutput()) { | 9890 if (ShouldProduceTraceOutput()) { |
| 9846 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9891 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9847 } | 9892 } |
| 9848 | 9893 |
| 9849 #ifdef DEBUG | 9894 #ifdef DEBUG |
| 9850 graph_->Verify(false); // No full verify. | 9895 graph_->Verify(false); // No full verify. |
| 9851 #endif | 9896 #endif |
| 9852 } | 9897 } |
| 9853 | 9898 |
| 9854 } } // namespace v8::internal | 9899 } } // namespace v8::internal |
| OLD | NEW |