OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 loop_information_(NULL), | 61 loop_information_(NULL), |
62 predecessors_(2), | 62 predecessors_(2), |
63 dominator_(NULL), | 63 dominator_(NULL), |
64 dominated_blocks_(4), | 64 dominated_blocks_(4), |
65 last_environment_(NULL), | 65 last_environment_(NULL), |
66 argument_count_(-1), | 66 argument_count_(-1), |
67 first_instruction_index_(-1), | 67 first_instruction_index_(-1), |
68 last_instruction_index_(-1), | 68 last_instruction_index_(-1), |
69 deleted_phis_(4), | 69 deleted_phis_(4), |
70 parent_loop_header_(NULL), | 70 parent_loop_header_(NULL), |
71 is_inline_return_target_(false) { } | 71 is_inline_return_target_(false), |
72 is_deoptimizing_(false) { } | |
72 | 73 |
73 | 74 |
74 void HBasicBlock::AttachLoopInformation() { | 75 void HBasicBlock::AttachLoopInformation() { |
75 ASSERT(!IsLoopHeader()); | 76 ASSERT(!IsLoopHeader()); |
76 loop_information_ = new(zone()) HLoopInformation(this); | 77 loop_information_ = new(zone()) HLoopInformation(this); |
77 } | 78 } |
78 | 79 |
79 | 80 |
80 void HBasicBlock::DetachLoopInformation() { | 81 void HBasicBlock::DetachLoopInformation() { |
81 ASSERT(IsLoopHeader()); | 82 ASSERT(IsLoopHeader()); |
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1441 | 1442 |
1442 | 1443 |
1443 bool HGlobalValueNumberer::AllowCodeMotion() { | 1444 bool HGlobalValueNumberer::AllowCodeMotion() { |
1444 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; | 1445 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; |
1445 } | 1446 } |
1446 | 1447 |
1447 | 1448 |
1448 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, | 1449 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, |
1449 HBasicBlock* loop_header) { | 1450 HBasicBlock* loop_header) { |
1450 // If we've disabled code motion, don't move any instructions. | 1451 // If we've disabled code motion, don't move any instructions. |
1451 if (!AllowCodeMotion()) return false; | 1452 if (!AllowCodeMotion()) return false; |
Kevin Millikin (Chromium)
2011/06/09 15:18:00
return AllowCodeMotion() && !instr->block()->IsDeo
fschneider
2011/06/09 15:46:47
Done.
| |
1452 | 1453 // Don't hoist code from never executed paths. |
1453 // If --aggressive-loop-invariant-motion, move everything except change | 1454 if (instr->block()->IsDeoptimizing()) return false; |
1454 // instructions. | 1455 return true; |
1455 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) { | |
1456 return true; | |
1457 } | |
1458 | |
1459 // Otherwise only move instructions that postdominate the loop header | |
1460 // (i.e. are always executed inside the loop). This is to avoid | |
1461 // unnecessary deoptimizations assuming the loop is executed at least | |
1462 // once. TODO(fschneider): Better type feedback should give us | |
1463 // information about code that was never executed. | |
1464 HBasicBlock* block = instr->block(); | |
1465 bool result = true; | |
1466 if (block != loop_header) { | |
1467 for (int i = 1; i < loop_header->predecessors()->length(); ++i) { | |
1468 bool found = false; | |
1469 HBasicBlock* pred = loop_header->predecessors()->at(i); | |
1470 while (pred != loop_header) { | |
1471 if (pred == block) found = true; | |
1472 pred = pred->dominator(); | |
1473 } | |
1474 if (!found) { | |
1475 result = false; | |
1476 break; | |
1477 } | |
1478 } | |
1479 } | |
1480 return result; | |
1481 } | 1456 } |
1482 | 1457 |
1483 | 1458 |
1484 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( | 1459 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( |
1485 HBasicBlock* dominator, HBasicBlock* dominated) { | 1460 HBasicBlock* dominator, HBasicBlock* dominated) { |
1486 int side_effects = 0; | 1461 int side_effects = 0; |
1487 for (int i = 0; i < dominated->predecessors()->length(); ++i) { | 1462 for (int i = 0; i < dominated->predecessors()->length(); ++i) { |
1488 HBasicBlock* block = dominated->predecessors()->at(i); | 1463 HBasicBlock* block = dominated->predecessors()->at(i); |
1489 if (dominator->block_id() < block->block_id() && | 1464 if (dominator->block_id() < block->block_id() && |
1490 block->block_id() < dominated->block_id() && | 1465 block->block_id() < dominated->block_id() && |
(...skipping 3352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4843 } | 4818 } |
4844 | 4819 |
4845 | 4820 |
4846 void HGraphBuilder::VisitSub(UnaryOperation* expr) { | 4821 void HGraphBuilder::VisitSub(UnaryOperation* expr) { |
4847 CHECK_ALIVE(VisitForValue(expr->expression())); | 4822 CHECK_ALIVE(VisitForValue(expr->expression())); |
4848 HValue* value = Pop(); | 4823 HValue* value = Pop(); |
4849 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); | 4824 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); |
4850 TypeInfo info = oracle()->UnaryType(expr); | 4825 TypeInfo info = oracle()->UnaryType(expr); |
4851 if (info.IsUninitialized()) { | 4826 if (info.IsUninitialized()) { |
4852 AddInstruction(new(zone()) HSoftDeoptimize); | 4827 AddInstruction(new(zone()) HSoftDeoptimize); |
4828 current_block()->MarkAsDeoptimizing(); | |
4853 info = TypeInfo::Unknown(); | 4829 info = TypeInfo::Unknown(); |
4854 } | 4830 } |
4855 Representation rep = ToRepresentation(info); | 4831 Representation rep = ToRepresentation(info); |
4856 TraceRepresentation(expr->op(), info, instr, rep); | 4832 TraceRepresentation(expr->op(), info, instr, rep); |
4857 instr->AssumeRepresentation(rep); | 4833 instr->AssumeRepresentation(rep); |
4858 ast_context()->ReturnInstruction(instr, expr->id()); | 4834 ast_context()->ReturnInstruction(instr, expr->id()); |
4859 } | 4835 } |
4860 | 4836 |
4861 | 4837 |
4862 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 4838 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
4863 CHECK_ALIVE(VisitForValue(expr->expression())); | 4839 CHECK_ALIVE(VisitForValue(expr->expression())); |
4864 HValue* value = Pop(); | 4840 HValue* value = Pop(); |
4865 TypeInfo info = oracle()->UnaryType(expr); | 4841 TypeInfo info = oracle()->UnaryType(expr); |
4866 if (info.IsUninitialized()) { | 4842 if (info.IsUninitialized()) { |
4867 AddInstruction(new(zone()) HSoftDeoptimize); | 4843 AddInstruction(new(zone()) HSoftDeoptimize); |
4844 current_block()->MarkAsDeoptimizing(); | |
4868 } | 4845 } |
4869 HInstruction* instr = new(zone()) HBitNot(value); | 4846 HInstruction* instr = new(zone()) HBitNot(value); |
4870 ast_context()->ReturnInstruction(instr, expr->id()); | 4847 ast_context()->ReturnInstruction(instr, expr->id()); |
4871 } | 4848 } |
4872 | 4849 |
4873 | 4850 |
4874 void HGraphBuilder::VisitNot(UnaryOperation* expr) { | 4851 void HGraphBuilder::VisitNot(UnaryOperation* expr) { |
4875 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. | 4852 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. |
4876 if (ast_context()->IsTest()) { | 4853 if (ast_context()->IsTest()) { |
4877 TestContext* context = TestContext::cast(ast_context()); | 4854 TestContext* context = TestContext::cast(ast_context()); |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5093 return new(zone()) HStringCharCodeAt(string, checked_index); | 5070 return new(zone()) HStringCharCodeAt(string, checked_index); |
5094 } | 5071 } |
5095 | 5072 |
5096 | 5073 |
5097 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 5074 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
5098 HValue* left, | 5075 HValue* left, |
5099 HValue* right) { | 5076 HValue* right) { |
5100 TypeInfo info = oracle()->BinaryType(expr); | 5077 TypeInfo info = oracle()->BinaryType(expr); |
5101 if (info.IsUninitialized()) { | 5078 if (info.IsUninitialized()) { |
5102 AddInstruction(new(zone()) HSoftDeoptimize); | 5079 AddInstruction(new(zone()) HSoftDeoptimize); |
5080 current_block()->MarkAsDeoptimizing(); | |
5103 info = TypeInfo::Unknown(); | 5081 info = TypeInfo::Unknown(); |
5104 } | 5082 } |
5105 HInstruction* instr = NULL; | 5083 HInstruction* instr = NULL; |
5106 switch (expr->op()) { | 5084 switch (expr->op()) { |
5107 case Token::ADD: | 5085 case Token::ADD: |
5108 if (info.IsString()) { | 5086 if (info.IsString()) { |
5109 AddInstruction(new(zone()) HCheckNonSmi(left)); | 5087 AddInstruction(new(zone()) HCheckNonSmi(left)); |
5110 AddInstruction(HCheckInstanceType::NewIsString(left)); | 5088 AddInstruction(HCheckInstanceType::NewIsString(left)); |
5111 AddInstruction(new(zone()) HCheckNonSmi(right)); | 5089 AddInstruction(new(zone()) HCheckNonSmi(right)); |
5112 AddInstruction(HCheckInstanceType::NewIsString(right)); | 5090 AddInstruction(HCheckInstanceType::NewIsString(right)); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5362 Handle<String>::cast(right_literal->handle())); | 5340 Handle<String>::cast(right_literal->handle())); |
5363 instr->set_position(expr->position()); | 5341 instr->set_position(expr->position()); |
5364 ast_context()->ReturnInstruction(instr, expr->id()); | 5342 ast_context()->ReturnInstruction(instr, expr->id()); |
5365 return; | 5343 return; |
5366 } | 5344 } |
5367 | 5345 |
5368 TypeInfo type_info = oracle()->CompareType(expr); | 5346 TypeInfo type_info = oracle()->CompareType(expr); |
5369 // Check if this expression was ever executed according to type feedback. | 5347 // Check if this expression was ever executed according to type feedback. |
5370 if (type_info.IsUninitialized()) { | 5348 if (type_info.IsUninitialized()) { |
5371 AddInstruction(new(zone()) HSoftDeoptimize); | 5349 AddInstruction(new(zone()) HSoftDeoptimize); |
5350 current_block()->MarkAsDeoptimizing(); | |
5372 type_info = TypeInfo::Unknown(); | 5351 type_info = TypeInfo::Unknown(); |
5373 } | 5352 } |
5374 | 5353 |
5375 CHECK_ALIVE(VisitForValue(expr->left())); | 5354 CHECK_ALIVE(VisitForValue(expr->left())); |
5376 CHECK_ALIVE(VisitForValue(expr->right())); | 5355 CHECK_ALIVE(VisitForValue(expr->right())); |
5377 | 5356 |
5378 HValue* right = Pop(); | 5357 HValue* right = Pop(); |
5379 HValue* left = Pop(); | 5358 HValue* left = Pop(); |
5380 Token::Value op = expr->op(); | 5359 Token::Value op = expr->op(); |
5381 | 5360 |
(...skipping 1023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6405 } | 6384 } |
6406 } | 6385 } |
6407 | 6386 |
6408 #ifdef DEBUG | 6387 #ifdef DEBUG |
6409 if (graph_ != NULL) graph_->Verify(); | 6388 if (graph_ != NULL) graph_->Verify(); |
6410 if (allocator_ != NULL) allocator_->Verify(); | 6389 if (allocator_ != NULL) allocator_->Verify(); |
6411 #endif | 6390 #endif |
6412 } | 6391 } |
6413 | 6392 |
6414 } } // namespace v8::internal | 6393 } } // namespace v8::internal |
OLD | NEW |