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 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 } | 1036 } |
1037 builder_->GotoNoSimulate(current->block_, merge_block); | 1037 builder_->GotoNoSimulate(current->block_, merge_block); |
1038 } | 1038 } |
1039 current = current->next_; | 1039 current = current->next_; |
1040 } | 1040 } |
1041 | 1041 |
1042 // Merge deopt blocks, padding when necessary. | 1042 // Merge deopt blocks, padding when necessary. |
1043 current = merge_at_join_blocks_; | 1043 current = merge_at_join_blocks_; |
1044 while (current != NULL) { | 1044 while (current != NULL) { |
1045 if (current->deopt_ && current->block_ != NULL) { | 1045 if (current->deopt_ && current->block_ != NULL) { |
1046 builder_->PadEnvironmentForContinuation(current->block_, | 1046 current->block_->FinishExit( |
1047 merge_block); | 1047 HAbnormalExit::New(builder_->zone(), NULL), RelocInfo::kNoPosition); |
1048 builder_->GotoNoSimulate(current->block_, merge_block); | |
1049 } | 1048 } |
1050 current = current->next_; | 1049 current = current->next_; |
1051 } | 1050 } |
1052 builder_->set_current_block(merge_block); | 1051 builder_->set_current_block(merge_block); |
1053 } | 1052 } |
1054 | 1053 |
1055 | 1054 |
1056 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 1055 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
1057 HValue* context, | 1056 HValue* context, |
1058 LoopBuilder::Direction direction) | 1057 LoopBuilder::Direction direction) |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1244 return header; | 1243 return header; |
1245 } | 1244 } |
1246 | 1245 |
1247 | 1246 |
1248 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1247 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1249 if (obj->type().IsHeapObject()) return obj; | 1248 if (obj->type().IsHeapObject()) return obj; |
1250 return Add<HCheckHeapObject>(obj); | 1249 return Add<HCheckHeapObject>(obj); |
1251 } | 1250 } |
1252 | 1251 |
1253 | 1252 |
1254 void HGraphBuilder::FinishExitWithHardDeoptimization( | 1253 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { |
1255 const char* reason, HBasicBlock* continuation) { | |
1256 PadEnvironmentForContinuation(current_block(), continuation); | |
1257 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1254 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1258 if (graph()->IsInsideNoSideEffectsScope()) { | 1255 FinishExitCurrentBlock(New<HAbnormalExit>()); |
1259 GotoNoSimulate(continuation); | |
1260 } else { | |
1261 Goto(continuation); | |
1262 } | |
1263 } | 1256 } |
1264 | 1257 |
1265 | 1258 |
1266 void HGraphBuilder::PadEnvironmentForContinuation( | |
1267 HBasicBlock* from, | |
1268 HBasicBlock* continuation) { | |
1269 if (continuation->last_environment() != NULL) { | |
1270 // When merging from a deopt block to a continuation, resolve differences in | |
1271 // environment by pushing constant 0 and popping extra values so that the | |
1272 // environments match during the join. Push 0 since it has the most specific | |
1273 // representation, and will not influence representation inference of the | |
1274 // phi. | |
1275 int continuation_env_length = continuation->last_environment()->length(); | |
1276 while (continuation_env_length != from->last_environment()->length()) { | |
1277 if (continuation_env_length > from->last_environment()->length()) { | |
1278 from->last_environment()->Push(graph()->GetConstant0()); | |
1279 } else { | |
1280 from->last_environment()->Pop(); | |
1281 } | |
1282 } | |
1283 } else { | |
1284 ASSERT(continuation->predecessors()->length() == 0); | |
1285 } | |
1286 } | |
1287 | |
1288 | |
1289 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { | 1259 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { |
1290 return Add<HCheckMaps>(obj, map, top_info()); | 1260 return Add<HCheckMaps>(obj, map, top_info()); |
1291 } | 1261 } |
1292 | 1262 |
1293 | 1263 |
1294 HValue* HGraphBuilder::BuildCheckString(HValue* string) { | 1264 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
1295 if (!string->type().IsString()) { | 1265 if (!string->type().IsString()) { |
1296 ASSERT(!string->IsConstant() || | 1266 ASSERT(!string->IsConstant() || |
1297 !HConstant::cast(string)->HasStringValue()); | 1267 !HConstant::cast(string)->HasStringValue()); |
1298 BuildCheckHeapObject(string); | 1268 BuildCheckHeapObject(string); |
(...skipping 4396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5695 } | 5665 } |
5696 | 5666 |
5697 if (current_block() != NULL) Goto(join); | 5667 if (current_block() != NULL) Goto(join); |
5698 set_current_block(if_false); | 5668 set_current_block(if_false); |
5699 } | 5669 } |
5700 | 5670 |
5701 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5671 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
5702 // know about and do not want to handle ones we've never seen. Otherwise | 5672 // know about and do not want to handle ones we've never seen. Otherwise |
5703 // use a generic IC. | 5673 // use a generic IC. |
5704 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5674 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
5705 // Because the deopt may be the only path in the polymorphic load, make sure | 5675 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); |
5706 // that the environment stack matches the depth on deopt that it otherwise | |
5707 // would have had after a successful load. | |
5708 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | |
5709 FinishExitWithHardDeoptimization("Uknown map in polymorphic access", join); | |
5710 } else { | 5676 } else { |
5711 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); | 5677 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); |
5712 AddInstruction(instr); | 5678 AddInstruction(instr); |
5713 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 5679 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
5714 | 5680 |
5715 if (join != NULL) { | 5681 if (join != NULL) { |
5716 Goto(join); | 5682 Goto(join); |
5717 } else { | 5683 } else { |
5718 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5684 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5719 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5685 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6421 // The caller will use has_side_effects and add a correct Simulate. | 6387 // The caller will use has_side_effects and add a correct Simulate. |
6422 access->SetFlag(HValue::kHasNoObservableSideEffects); | 6388 access->SetFlag(HValue::kHasNoObservableSideEffects); |
6423 if (access_type == LOAD) { | 6389 if (access_type == LOAD) { |
6424 Push(access); | 6390 Push(access); |
6425 } | 6391 } |
6426 NoObservableSideEffectsScope scope(this); | 6392 NoObservableSideEffectsScope scope(this); |
6427 GotoNoSimulate(join); | 6393 GotoNoSimulate(join); |
6428 set_current_block(other_map); | 6394 set_current_block(other_map); |
6429 } | 6395 } |
6430 | 6396 |
| 6397 // Ensure that we visited at least one map above that goes to join. This is |
| 6398 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
| 6399 // rather than joining the join block. If this becomes an issue, insert a |
| 6400 // generic access in the case length() == 0. |
| 6401 ASSERT(join->predecessors()->length() > 0); |
6431 // Deopt if none of the cases matched. | 6402 // Deopt if none of the cases matched. |
6432 NoObservableSideEffectsScope scope(this); | 6403 NoObservableSideEffectsScope scope(this); |
6433 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", | 6404 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); |
6434 join); | |
6435 set_current_block(join); | 6405 set_current_block(join); |
6436 return access_type == STORE ? NULL : Pop(); | 6406 return access_type == STORE ? NULL : Pop(); |
6437 } | 6407 } |
6438 | 6408 |
6439 | 6409 |
6440 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6410 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
6441 HValue* obj, | 6411 HValue* obj, |
6442 HValue* key, | 6412 HValue* key, |
6443 HValue* val, | 6413 HValue* val, |
6444 Expression* expr, | 6414 Expression* expr, |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6912 } | 6882 } |
6913 | 6883 |
6914 if (current_block() != NULL) Goto(join); | 6884 if (current_block() != NULL) Goto(join); |
6915 set_current_block(if_false); | 6885 set_current_block(if_false); |
6916 } | 6886 } |
6917 | 6887 |
6918 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6888 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6919 // know about and do not want to handle ones we've never seen. Otherwise | 6889 // know about and do not want to handle ones we've never seen. Otherwise |
6920 // use a generic IC. | 6890 // use a generic IC. |
6921 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6891 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6922 // Because the deopt may be the only path in the polymorphic call, make sure | 6892 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); |
6923 // that the environment stack matches the depth on deopt that it otherwise | |
6924 // would have had after a successful call. | |
6925 Drop(1); // Drop receiver. | |
6926 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | |
6927 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | |
6928 } else { | 6893 } else { |
6929 Property* prop = expr->expression()->AsProperty(); | 6894 Property* prop = expr->expression()->AsProperty(); |
6930 HInstruction* function = BuildNamedGeneric( | 6895 HInstruction* function = BuildNamedGeneric( |
6931 LOAD, receiver, name, NULL, prop->IsUninitialized()); | 6896 LOAD, receiver, name, NULL, prop->IsUninitialized()); |
6932 AddInstruction(function); | 6897 AddInstruction(function); |
6933 Push(function); | 6898 Push(function); |
6934 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 6899 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
6935 | 6900 |
6936 environment()->SetExpressionStackAt(1, function); | 6901 environment()->SetExpressionStackAt(1, function); |
6937 environment()->SetExpressionStackAt(0, receiver); | 6902 environment()->SetExpressionStackAt(0, receiver); |
(...skipping 4249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11187 if (ShouldProduceTraceOutput()) { | 11152 if (ShouldProduceTraceOutput()) { |
11188 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11153 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11189 } | 11154 } |
11190 | 11155 |
11191 #ifdef DEBUG | 11156 #ifdef DEBUG |
11192 graph_->Verify(false); // No full verify. | 11157 graph_->Verify(false); // No full verify. |
11193 #endif | 11158 #endif |
11194 } | 11159 } |
11195 | 11160 |
11196 } } // namespace v8::internal | 11161 } } // namespace v8::internal |
OLD | NEW |