OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 next_block_id_(0), | 867 next_block_id_(0), |
868 entry_block_(NULL), | 868 entry_block_(NULL), |
869 blocks_(8, info->zone()), | 869 blocks_(8, info->zone()), |
870 values_(16, info->zone()), | 870 values_(16, info->zone()), |
871 phi_list_(NULL), | 871 phi_list_(NULL), |
872 uint32_instructions_(NULL), | 872 uint32_instructions_(NULL), |
873 info_(info), | 873 info_(info), |
874 zone_(info->zone()), | 874 zone_(info->zone()), |
875 is_recursive_(false), | 875 is_recursive_(false), |
876 use_optimistic_licm_(false), | 876 use_optimistic_licm_(false), |
| 877 has_soft_deoptimize_(false), |
877 type_change_checksum_(0) { | 878 type_change_checksum_(0) { |
878 if (info->IsStub()) { | 879 if (info->IsStub()) { |
879 start_environment_ = | 880 start_environment_ = |
880 new(zone_) HEnvironment(zone_); | 881 new(zone_) HEnvironment(zone_); |
881 } else { | 882 } else { |
882 start_environment_ = | 883 start_environment_ = |
883 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); | 884 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); |
884 } | 885 } |
885 start_environment_->set_ast_id(BailoutId::FunctionEntry()); | 886 start_environment_->set_ast_id(BailoutId::FunctionEntry()); |
886 entry_block_ = CreateBasicBlock(); | 887 entry_block_ = CreateBasicBlock(); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1234 block->AssignCommonDominator(block->predecessors()->first()); | 1235 block->AssignCommonDominator(block->predecessors()->first()); |
1235 block->AssignLoopSuccessorDominators(); | 1236 block->AssignLoopSuccessorDominators(); |
1236 } else { | 1237 } else { |
1237 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { | 1238 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { |
1238 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 1239 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
1239 } | 1240 } |
1240 } | 1241 } |
1241 } | 1242 } |
1242 } | 1243 } |
1243 | 1244 |
| 1245 |
1244 // Mark all blocks that are dominated by an unconditional soft deoptimize to | 1246 // Mark all blocks that are dominated by an unconditional soft deoptimize to |
1245 // prevent code motion across those blocks. | 1247 // prevent code motion across those blocks. |
1246 void HGraph::PropagateDeoptimizingMark() { | 1248 void HGraph::PropagateDeoptimizingMark() { |
1247 HPhase phase("H_Propagate deoptimizing mark", this); | 1249 HPhase phase("H_Propagate deoptimizing mark", this); |
| 1250 // Skip this phase if there is nothing to be done anyway. |
| 1251 if (!has_soft_deoptimize()) return; |
1248 MarkAsDeoptimizingRecursively(entry_block()); | 1252 MarkAsDeoptimizingRecursively(entry_block()); |
| 1253 NullifyUnreachableInstructions(); |
1249 } | 1254 } |
1250 | 1255 |
| 1256 |
1251 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { | 1257 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { |
1252 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | 1258 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
1253 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 1259 HBasicBlock* dominated = block->dominated_blocks()->at(i); |
1254 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); | 1260 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); |
1255 MarkAsDeoptimizingRecursively(dominated); | 1261 MarkAsDeoptimizingRecursively(dominated); |
1256 } | 1262 } |
1257 } | 1263 } |
1258 | 1264 |
| 1265 |
| 1266 void HGraph::NullifyUnreachableInstructions() { |
| 1267 int block_count = blocks_.length(); |
| 1268 for (int i = 0; i < block_count; ++i) { |
| 1269 HBasicBlock* block = blocks_.at(i); |
| 1270 bool nullify = false; |
| 1271 const ZoneList<HBasicBlock*>* predecessors = block->predecessors(); |
| 1272 int predecessors_length = predecessors->length(); |
| 1273 bool all_predecessors_deoptimizing = (predecessors_length > 0); |
| 1274 for (int j = 0; j < predecessors_length; ++j) { |
| 1275 if (!predecessors->at(j)->IsDeoptimizing()) { |
| 1276 all_predecessors_deoptimizing = false; |
| 1277 break; |
| 1278 } |
| 1279 } |
| 1280 if (all_predecessors_deoptimizing) nullify = true; |
| 1281 for (HInstruction* instr = block->first(); instr != NULL; |
| 1282 instr = instr->next()) { |
| 1283 // Leave the basic structure of the graph intact. |
| 1284 if (instr->IsBlockEntry()) continue; |
| 1285 if (instr->IsControlInstruction()) continue; |
| 1286 if (instr->IsSimulate()) continue; |
| 1287 if (instr->IsEnterInlined()) continue; |
| 1288 if (instr->IsLeaveInlined()) continue; |
| 1289 if (nullify) { |
| 1290 HInstruction* last_dummy = NULL; |
| 1291 for (int j = 0; j < instr->OperandCount(); ++j) { |
| 1292 HValue* operand = instr->OperandAt(j); |
| 1293 // Insert an HDummyUse for each operand, unless the operand |
| 1294 // is an HDummyUse itself. If it's even from the same block, |
| 1295 // remember it as a potential replacement for the instruction. |
| 1296 if (operand->IsDummyUse()) { |
| 1297 if (operand->block() == instr->block() && |
| 1298 last_dummy == NULL) { |
| 1299 last_dummy = HInstruction::cast(operand); |
| 1300 } |
| 1301 continue; |
| 1302 } |
| 1303 HDummyUse* dummy = new(zone()) HDummyUse(operand); |
| 1304 dummy->InsertBefore(instr); |
| 1305 last_dummy = dummy; |
| 1306 } |
| 1307 if (last_dummy == NULL) last_dummy = GetConstant1(); |
| 1308 instr->DeleteAndReplaceWith(last_dummy); |
| 1309 continue; |
| 1310 } |
| 1311 if (instr->IsSoftDeoptimize()) { |
| 1312 ASSERT(block->IsDeoptimizing()); |
| 1313 nullify = true; |
| 1314 } |
| 1315 } |
| 1316 } |
| 1317 } |
| 1318 |
| 1319 |
1259 void HGraph::EliminateRedundantPhis() { | 1320 void HGraph::EliminateRedundantPhis() { |
1260 HPhase phase("H_Redundant phi elimination", this); | 1321 HPhase phase("H_Redundant phi elimination", this); |
1261 | 1322 |
1262 // Worklist of phis that can potentially be eliminated. Initialized with | 1323 // Worklist of phis that can potentially be eliminated. Initialized with |
1263 // all phi nodes. When elimination of a phi node modifies another phi node | 1324 // all phi nodes. When elimination of a phi node modifies another phi node |
1264 // the modified phi node is added to the worklist. | 1325 // the modified phi node is added to the worklist. |
1265 ZoneList<HPhi*> worklist(blocks_.length(), zone()); | 1326 ZoneList<HPhi*> worklist(blocks_.length(), zone()); |
1266 for (int i = 0; i < blocks_.length(); ++i) { | 1327 for (int i = 0; i < blocks_.length(); ++i) { |
1267 worklist.AddAll(*blocks_[i]->phis(), zone()); | 1328 worklist.AddAll(*blocks_[i]->phis(), zone()); |
1268 } | 1329 } |
(...skipping 2681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3950 current_block()->AddPhi(instr); | 4011 current_block()->AddPhi(instr); |
3951 } | 4012 } |
3952 | 4013 |
3953 | 4014 |
3954 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 4015 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
3955 Push(instr); | 4016 Push(instr); |
3956 AddInstruction(instr); | 4017 AddInstruction(instr); |
3957 } | 4018 } |
3958 | 4019 |
3959 | 4020 |
| 4021 void HOptimizedGraphBuilder::AddSoftDeoptimize() { |
| 4022 if (FLAG_always_opt) return; |
| 4023 if (current_block()->IsDeoptimizing()) return; |
| 4024 AddInstruction(new(zone()) HSoftDeoptimize()); |
| 4025 current_block()->MarkAsDeoptimizing(); |
| 4026 graph()->set_has_soft_deoptimize(true); |
| 4027 } |
| 4028 |
| 4029 |
3960 template <class Instruction> | 4030 template <class Instruction> |
3961 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 4031 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
3962 int count = call->argument_count(); | 4032 int count = call->argument_count(); |
3963 ZoneList<HValue*> arguments(count, zone()); | 4033 ZoneList<HValue*> arguments(count, zone()); |
3964 for (int i = 0; i < count; ++i) { | 4034 for (int i = 0; i < count; ++i) { |
3965 arguments.Add(Pop(), zone()); | 4035 arguments.Add(Pop(), zone()); |
3966 } | 4036 } |
3967 | 4037 |
3968 while (!arguments.is_empty()) { | 4038 while (!arguments.is_empty()) { |
3969 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); | 4039 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
(...skipping 2149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6119 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 6189 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
6120 return new(zone()) HLoadNamedField(object, false, offset); | 6190 return new(zone()) HLoadNamedField(object, false, offset); |
6121 } | 6191 } |
6122 } | 6192 } |
6123 | 6193 |
6124 | 6194 |
6125 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6195 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
6126 HValue* object, | 6196 HValue* object, |
6127 Handle<String> name, | 6197 Handle<String> name, |
6128 Property* expr) { | 6198 Property* expr) { |
6129 if (expr->IsUninitialized() && !FLAG_always_opt) { | 6199 if (expr->IsUninitialized()) { |
6130 AddInstruction(new(zone()) HSoftDeoptimize); | 6200 AddSoftDeoptimize(); |
6131 current_block()->MarkAsDeoptimizing(); | |
6132 } | 6201 } |
6133 HValue* context = environment()->LookupContext(); | 6202 HValue* context = environment()->LookupContext(); |
6134 return new(zone()) HLoadNamedGeneric(context, object, name); | 6203 return new(zone()) HLoadNamedGeneric(context, object, name); |
6135 } | 6204 } |
6136 | 6205 |
6137 | 6206 |
6138 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 6207 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
6139 HValue* object, | 6208 HValue* object, |
6140 Handle<Map> map, | 6209 Handle<Map> map, |
6141 Handle<JSFunction> getter, | 6210 Handle<JSFunction> getter, |
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8013 | 8082 |
8014 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 8083 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
8015 CHECK_ALIVE(VisitForValue(expr->expression())); | 8084 CHECK_ALIVE(VisitForValue(expr->expression())); |
8016 HValue* value = Pop(); | 8085 HValue* value = Pop(); |
8017 HValue* context = environment()->LookupContext(); | 8086 HValue* context = environment()->LookupContext(); |
8018 HInstruction* instr = | 8087 HInstruction* instr = |
8019 new(zone()) HMul(context, value, graph()->GetConstantMinus1()); | 8088 new(zone()) HMul(context, value, graph()->GetConstantMinus1()); |
8020 TypeInfo info = oracle()->UnaryType(expr); | 8089 TypeInfo info = oracle()->UnaryType(expr); |
8021 Representation rep = ToRepresentation(info); | 8090 Representation rep = ToRepresentation(info); |
8022 if (info.IsUninitialized()) { | 8091 if (info.IsUninitialized()) { |
8023 AddInstruction(new(zone()) HSoftDeoptimize); | 8092 AddSoftDeoptimize(); |
8024 current_block()->MarkAsDeoptimizing(); | |
8025 info = TypeInfo::Unknown(); | 8093 info = TypeInfo::Unknown(); |
8026 } | 8094 } |
8027 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); | 8095 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); |
8028 return ast_context()->ReturnInstruction(instr, expr->id()); | 8096 return ast_context()->ReturnInstruction(instr, expr->id()); |
8029 } | 8097 } |
8030 | 8098 |
8031 | 8099 |
8032 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 8100 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
8033 CHECK_ALIVE(VisitForValue(expr->expression())); | 8101 CHECK_ALIVE(VisitForValue(expr->expression())); |
8034 HValue* value = Pop(); | 8102 HValue* value = Pop(); |
8035 TypeInfo info = oracle()->UnaryType(expr); | 8103 TypeInfo info = oracle()->UnaryType(expr); |
8036 if (info.IsUninitialized()) { | 8104 if (info.IsUninitialized()) { |
8037 AddInstruction(new(zone()) HSoftDeoptimize); | 8105 AddSoftDeoptimize(); |
8038 current_block()->MarkAsDeoptimizing(); | |
8039 } | 8106 } |
8040 HInstruction* instr = new(zone()) HBitNot(value); | 8107 HInstruction* instr = new(zone()) HBitNot(value); |
8041 return ast_context()->ReturnInstruction(instr, expr->id()); | 8108 return ast_context()->ReturnInstruction(instr, expr->id()); |
8042 } | 8109 } |
8043 | 8110 |
8044 | 8111 |
8045 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 8112 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
8046 if (ast_context()->IsTest()) { | 8113 if (ast_context()->IsTest()) { |
8047 TestContext* context = TestContext::cast(ast_context()); | 8114 TestContext* context = TestContext::cast(ast_context()); |
8048 VisitForControl(expr->expression(), | 8115 VisitForControl(expr->expression(), |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8384 HValue* right) { | 8451 HValue* right) { |
8385 HValue* context = environment()->LookupContext(); | 8452 HValue* context = environment()->LookupContext(); |
8386 TypeInfo left_info, right_info, result_info, combined_info; | 8453 TypeInfo left_info, right_info, result_info, combined_info; |
8387 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); | 8454 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); |
8388 Representation left_rep = ToRepresentation(left_info); | 8455 Representation left_rep = ToRepresentation(left_info); |
8389 Representation right_rep = ToRepresentation(right_info); | 8456 Representation right_rep = ToRepresentation(right_info); |
8390 Representation result_rep = ToRepresentation(result_info); | 8457 Representation result_rep = ToRepresentation(result_info); |
8391 if (left_info.IsUninitialized()) { | 8458 if (left_info.IsUninitialized()) { |
8392 // Can't have initialized one but not the other. | 8459 // Can't have initialized one but not the other. |
8393 ASSERT(right_info.IsUninitialized()); | 8460 ASSERT(right_info.IsUninitialized()); |
8394 AddInstruction(new(zone()) HSoftDeoptimize); | 8461 AddSoftDeoptimize(); |
8395 current_block()->MarkAsDeoptimizing(); | |
8396 left_info = right_info = TypeInfo::Unknown(); | 8462 left_info = right_info = TypeInfo::Unknown(); |
8397 } | 8463 } |
8398 HInstruction* instr = NULL; | 8464 HInstruction* instr = NULL; |
8399 switch (expr->op()) { | 8465 switch (expr->op()) { |
8400 case Token::ADD: | 8466 case Token::ADD: |
8401 if (left_info.IsString() && right_info.IsString()) { | 8467 if (left_info.IsString() && right_info.IsString()) { |
8402 AddInstruction(new(zone()) HCheckNonSmi(left)); | 8468 AddInstruction(new(zone()) HCheckNonSmi(left)); |
8403 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 8469 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
8404 AddInstruction(new(zone()) HCheckNonSmi(right)); | 8470 AddInstruction(new(zone()) HCheckNonSmi(right)); |
8405 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 8471 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8699 } | 8765 } |
8700 | 8766 |
8701 TypeInfo left_type, right_type, overall_type_info; | 8767 TypeInfo left_type, right_type, overall_type_info; |
8702 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); | 8768 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); |
8703 Representation combined_rep = ToRepresentation(overall_type_info); | 8769 Representation combined_rep = ToRepresentation(overall_type_info); |
8704 Representation left_rep = ToRepresentation(left_type); | 8770 Representation left_rep = ToRepresentation(left_type); |
8705 Representation right_rep = ToRepresentation(right_type); | 8771 Representation right_rep = ToRepresentation(right_type); |
8706 // Check if this expression was ever executed according to type feedback. | 8772 // Check if this expression was ever executed according to type feedback. |
8707 // Note that for the special typeof/null/undefined cases we get unknown here. | 8773 // Note that for the special typeof/null/undefined cases we get unknown here. |
8708 if (overall_type_info.IsUninitialized()) { | 8774 if (overall_type_info.IsUninitialized()) { |
8709 AddInstruction(new(zone()) HSoftDeoptimize); | 8775 AddSoftDeoptimize(); |
8710 current_block()->MarkAsDeoptimizing(); | |
8711 overall_type_info = left_type = right_type = TypeInfo::Unknown(); | 8776 overall_type_info = left_type = right_type = TypeInfo::Unknown(); |
8712 } | 8777 } |
8713 | 8778 |
8714 CHECK_ALIVE(VisitForValue(expr->left())); | 8779 CHECK_ALIVE(VisitForValue(expr->left())); |
8715 CHECK_ALIVE(VisitForValue(expr->right())); | 8780 CHECK_ALIVE(VisitForValue(expr->right())); |
8716 | 8781 |
8717 HValue* context = environment()->LookupContext(); | 8782 HValue* context = environment()->LookupContext(); |
8718 HValue* right = Pop(); | 8783 HValue* right = Pop(); |
8719 HValue* left = Pop(); | 8784 HValue* left = Pop(); |
8720 Token::Value op = expr->op(); | 8785 Token::Value op = expr->op(); |
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10170 } | 10235 } |
10171 } | 10236 } |
10172 | 10237 |
10173 #ifdef DEBUG | 10238 #ifdef DEBUG |
10174 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10239 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10175 if (allocator_ != NULL) allocator_->Verify(); | 10240 if (allocator_ != NULL) allocator_->Verify(); |
10176 #endif | 10241 #endif |
10177 } | 10242 } |
10178 | 10243 |
10179 } } // namespace v8::internal | 10244 } } // namespace v8::internal |
OLD | NEW |