| 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 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 } | 424 } |
| 425 #endif | 425 #endif |
| 426 | 426 |
| 427 | 427 |
| 428 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { | 428 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { |
| 429 this->back_edges_.Add(block, block->zone()); | 429 this->back_edges_.Add(block, block->zone()); |
| 430 AddBlock(block); | 430 AddBlock(block); |
| 431 } | 431 } |
| 432 | 432 |
| 433 | 433 |
| 434 void HLoopInformation::ProcessEdge(HBasicBlock* destination) { |
| 435 HLoopInformation* target_loop = destination->current_loop(); |
| 436 if (IsNestedInThisLoop(target_loop)) return; |
| 437 |
| 438 HLoopInformation* current_loop = this; |
| 439 // TODO(mmassi) When we will support try..catch we will need to break out of |
| 440 // this loop when we meet the catch block. |
| 441 // From a correctness PoV we're safe anyway, but unnecessarily marking loops |
| 442 // as having additional exits could prevent hoisting of bounds checks. |
| 443 while (current_loop != NULL) { |
| 444 if (target_loop == current_loop) return; |
| 445 current_loop->exits_count_++; |
| 446 current_loop = current_loop->parent_loop(); |
| 447 } |
| 448 } |
| 449 |
| 450 |
| 451 void HLoopInformation::ProcessThrow() { |
| 452 HLoopInformation* current_loop = this; |
| 453 while (current_loop != NULL) { |
| 454 current_loop->exits_count_++; |
| 455 current_loop = current_loop->parent_loop(); |
| 456 } |
| 457 } |
| 458 |
| 459 |
| 434 HBasicBlock* HLoopInformation::GetLastBackEdge() const { | 460 HBasicBlock* HLoopInformation::GetLastBackEdge() const { |
| 435 int max_id = -1; | 461 int max_id = -1; |
| 436 HBasicBlock* result = NULL; | 462 HBasicBlock* result = NULL; |
| 437 for (int i = 0; i < back_edges_.length(); ++i) { | 463 for (int i = 0; i < back_edges_.length(); ++i) { |
| 438 HBasicBlock* cur = back_edges_[i]; | 464 HBasicBlock* cur = back_edges_[i]; |
| 439 if (cur->block_id() > max_id) { | 465 if (cur->block_id() > max_id) { |
| 440 max_id = cur->block_id(); | 466 max_id = cur->block_id(); |
| 441 result = cur; | 467 result = cur; |
| 442 } | 468 } |
| 443 } | 469 } |
| (...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 HGraph::HGraph(CompilationInfo* info) | 2118 HGraph::HGraph(CompilationInfo* info) |
| 2093 : isolate_(info->isolate()), | 2119 : isolate_(info->isolate()), |
| 2094 next_block_id_(0), | 2120 next_block_id_(0), |
| 2095 entry_block_(NULL), | 2121 entry_block_(NULL), |
| 2096 blocks_(8, info->zone()), | 2122 blocks_(8, info->zone()), |
| 2097 values_(16, info->zone()), | 2123 values_(16, info->zone()), |
| 2098 phi_list_(NULL), | 2124 phi_list_(NULL), |
| 2099 uint32_instructions_(NULL), | 2125 uint32_instructions_(NULL), |
| 2100 info_(info), | 2126 info_(info), |
| 2101 zone_(info->zone()), | 2127 zone_(info->zone()), |
| 2128 evaluated_relations_table_(info->zone()), |
| 2102 is_recursive_(false), | 2129 is_recursive_(false), |
| 2103 use_optimistic_licm_(false), | 2130 use_optimistic_licm_(false), |
| 2104 has_soft_deoptimize_(false), | 2131 has_soft_deoptimize_(false), |
| 2105 depends_on_empty_array_proto_elements_(false), | 2132 depends_on_empty_array_proto_elements_(false), |
| 2106 type_change_checksum_(0) { | 2133 type_change_checksum_(0) { |
| 2107 if (info->IsStub()) { | 2134 if (info->IsStub()) { |
| 2108 HydrogenCodeStub* stub = info->code_stub(); | 2135 HydrogenCodeStub* stub = info->code_stub(); |
| 2109 CodeStubInterfaceDescriptor* descriptor = | 2136 CodeStubInterfaceDescriptor* descriptor = |
| 2110 stub->GetInterfaceDescriptor(isolate_); | 2137 stub->GetInterfaceDescriptor(isolate_); |
| 2111 start_environment_ = | 2138 start_environment_ = |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2457 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); | 2484 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); |
| 2458 while (postorder != NULL) { | 2485 while (postorder != NULL) { |
| 2459 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); | 2486 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); |
| 2460 } | 2487 } |
| 2461 blocks_.Rewind(0); | 2488 blocks_.Rewind(0); |
| 2462 int index = 0; | 2489 int index = 0; |
| 2463 for (int i = reverse_result.length() - 1; i >= 0; --i) { | 2490 for (int i = reverse_result.length() - 1; i >= 0; --i) { |
| 2464 HBasicBlock* b = reverse_result[i]; | 2491 HBasicBlock* b = reverse_result[i]; |
| 2465 blocks_.Add(b, zone()); | 2492 blocks_.Add(b, zone()); |
| 2466 b->set_block_id(index++); | 2493 b->set_block_id(index++); |
| 2494 |
| 2495 HLoopInformation* loop = b->current_loop(); |
| 2496 if (loop != NULL) { |
| 2497 for (int i = 0; i < b->end()->SuccessorCount(); i++) { |
| 2498 HBasicBlock* successor = b->end()->SuccessorAt(i); |
| 2499 loop->ProcessEdge(successor); |
| 2500 } |
| 2501 |
| 2502 for (HInstruction* instruction = b->first(); |
| 2503 instruction != NULL; |
| 2504 instruction = instruction->next()) { |
| 2505 if (instruction->IsThrow()) { |
| 2506 loop->ProcessThrow(); |
| 2507 } |
| 2508 } |
| 2509 } |
| 2467 } | 2510 } |
| 2468 } | 2511 } |
| 2469 | 2512 |
| 2470 | 2513 |
| 2471 void HGraph::AssignDominators() { | 2514 void HGraph::AssignDominators() { |
| 2472 HPhase phase("H_Assign dominators", this); | 2515 HPhase phase("H_Assign dominators", this); |
| 2473 for (int i = 0; i < blocks_.length(); ++i) { | 2516 for (int i = 0; i < blocks_.length(); ++i) { |
| 2474 HBasicBlock* block = blocks_[i]; | 2517 HBasicBlock* block = blocks_[i]; |
| 2475 if (block->IsLoopHeader()) { | 2518 if (block->IsLoopHeader()) { |
| 2476 // Only the first predecessor of a loop header is from outside the loop. | 2519 // Only the first predecessor of a loop header is from outside the loop. |
| (...skipping 2438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4915 HRangeAnalysis rangeAnalysis(this); | 4958 HRangeAnalysis rangeAnalysis(this); |
| 4916 rangeAnalysis.Analyze(); | 4959 rangeAnalysis.Analyze(); |
| 4917 } | 4960 } |
| 4918 ComputeMinusZeroChecks(); | 4961 ComputeMinusZeroChecks(); |
| 4919 | 4962 |
| 4920 // Eliminate redundant stack checks on backwards branches. | 4963 // Eliminate redundant stack checks on backwards branches. |
| 4921 HStackCheckEliminator sce(this); | 4964 HStackCheckEliminator sce(this); |
| 4922 sce.Process(); | 4965 sce.Process(); |
| 4923 | 4966 |
| 4924 if (FLAG_idefs) SetupInformativeDefinitions(); | 4967 if (FLAG_idefs) SetupInformativeDefinitions(); |
| 4925 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { | 4968 if (FLAG_array_bounds_checks_elimination) { |
| 4926 EliminateRedundantBoundsChecks(); | 4969 EliminateRedundantBoundsChecks(); |
| 4927 } | 4970 } |
| 4928 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); | 4971 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); |
| 4972 RestoreActualValues(); |
| 4973 |
| 4929 if (FLAG_dead_code_elimination) { | 4974 if (FLAG_dead_code_elimination) { |
| 4930 DeadCodeElimination("H_Eliminate late dead code"); | 4975 DeadCodeElimination("H_Eliminate late dead code"); |
| 4931 } | 4976 } |
| 4932 | 4977 |
| 4933 RestoreActualValues(); | |
| 4934 | 4978 |
| 4935 return true; | 4979 return true; |
| 4936 } | 4980 } |
| 4937 | 4981 |
| 4938 | 4982 |
| 4939 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { | 4983 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { |
| 4940 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { | 4984 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { |
| 4941 HPhi* phi = block->phis()->at(phi_index); | 4985 HPhi* phi = block->phis()->at(phi_index); |
| 4942 phi->AddInformativeDefinitions(); | 4986 phi->AddInformativeDefinitions(); |
| 4943 phi->SetFlag(HValue::kIDefsProcessingDone); | 4987 phi->SetFlag(HValue::kIDefsProcessingDone); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4955 | 4999 |
| 4956 // This method is recursive, so if its stack frame is large it could | 5000 // This method is recursive, so if its stack frame is large it could |
| 4957 // cause a stack overflow. | 5001 // cause a stack overflow. |
| 4958 // To keep the individual stack frames small we do the actual work inside | 5002 // To keep the individual stack frames small we do the actual work inside |
| 4959 // SetupInformativeDefinitionsInBlock(); | 5003 // SetupInformativeDefinitionsInBlock(); |
| 4960 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { | 5004 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { |
| 4961 SetupInformativeDefinitionsInBlock(block); | 5005 SetupInformativeDefinitionsInBlock(block); |
| 4962 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { | 5006 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { |
| 4963 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); | 5007 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); |
| 4964 } | 5008 } |
| 4965 | |
| 4966 for (HInstruction* i = block->first(); i != NULL; i = i->next()) { | |
| 4967 if (i->IsBoundsCheck()) { | |
| 4968 HBoundsCheck* check = HBoundsCheck::cast(i); | |
| 4969 check->ApplyIndexChange(); | |
| 4970 } | |
| 4971 } | |
| 4972 } | 5009 } |
| 4973 | 5010 |
| 4974 | 5011 |
| 4975 void HGraph::SetupInformativeDefinitions() { | 5012 void HGraph::SetupInformativeDefinitions() { |
| 4976 HPhase phase("H_Setup informative definitions", this); | 5013 HPhase phase("H_Setup informative definitions", this); |
| 4977 SetupInformativeDefinitionsRecursively(entry_block()); | 5014 SetupInformativeDefinitionsRecursively(entry_block()); |
| 4978 } | 5015 } |
| 4979 | 5016 |
| 4980 | 5017 |
| 4981 // We try to "factor up" HBoundsCheck instructions towards the root of the | 5018 // We try to "factor up" HBoundsCheck instructions towards the root of the |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5250 void Delete(BoundsCheckKey* key) { | 5287 void Delete(BoundsCheckKey* key) { |
| 5251 Remove(key, key->Hash()); | 5288 Remove(key, key->Hash()); |
| 5252 } | 5289 } |
| 5253 | 5290 |
| 5254 explicit BoundsCheckTable(Zone* zone) | 5291 explicit BoundsCheckTable(Zone* zone) |
| 5255 : ZoneHashMap(BoundsCheckKeyMatch, ZoneHashMap::kDefaultHashMapCapacity, | 5292 : ZoneHashMap(BoundsCheckKeyMatch, ZoneHashMap::kDefaultHashMapCapacity, |
| 5256 ZoneAllocationPolicy(zone)) { } | 5293 ZoneAllocationPolicy(zone)) { } |
| 5257 }; | 5294 }; |
| 5258 | 5295 |
| 5259 | 5296 |
| 5297 void HGraph::EliminateRedundantBoundsChecksUsingIdefs(HBasicBlock* bb) { |
| 5298 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { |
| 5299 if (i->IsBoundsCheck()) { |
| 5300 HBoundsCheck* check = HBoundsCheck::cast(i); |
| 5301 if (check->index()->TryGuaranteeRange(check->length(), bb)) { |
| 5302 check->set_skip_check(); |
| 5303 } |
| 5304 } |
| 5305 } |
| 5306 |
| 5307 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) { |
| 5308 EliminateRedundantBoundsChecksUsingIdefs(bb->dominated_blocks()->at(i)); |
| 5309 } |
| 5310 } |
| 5311 |
| 5312 |
| 5313 void HGraph::ApplyBoundsChecksIndexChanges(HBasicBlock* bb) { |
| 5314 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { |
| 5315 if (i->IsBoundsCheck()) { |
| 5316 HBoundsCheck* check = HBoundsCheck::cast(i); |
| 5317 check->ApplyIndexChange(); |
| 5318 } |
| 5319 } |
| 5320 |
| 5321 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) { |
| 5322 ApplyBoundsChecksIndexChanges(bb->dominated_blocks()->at(i)); |
| 5323 } |
| 5324 } |
| 5325 |
| 5326 |
| 5260 // Eliminates checks in bb and recursively in the dominated blocks. | 5327 // Eliminates checks in bb and recursively in the dominated blocks. |
| 5261 // Also replace the results of check instructions with the original value, if | 5328 // Also replace the results of check instructions with the original value, if |
| 5262 // the result is used. This is safe now, since we don't do code motion after | 5329 // the result is used. This is safe now, since we don't do code motion after |
| 5263 // this point. It enables better register allocation since the value produced | 5330 // this point. It enables better register allocation since the value produced |
| 5264 // by check instructions is really a copy of the original value. | 5331 // by check instructions is really a copy of the original value. |
| 5265 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, | 5332 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, |
| 5266 BoundsCheckTable* table) { | 5333 BoundsCheckTable* table) { |
| 5267 BoundsCheckBbData* bb_data_list = NULL; | 5334 BoundsCheckBbData* bb_data_list = NULL; |
| 5268 | 5335 |
| 5269 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { | 5336 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5323 table->Insert(data->Key(), data->FatherInDominatorTree(), zone()); | 5390 table->Insert(data->Key(), data->FatherInDominatorTree(), zone()); |
| 5324 } else { | 5391 } else { |
| 5325 table->Delete(data->Key()); | 5392 table->Delete(data->Key()); |
| 5326 } | 5393 } |
| 5327 } | 5394 } |
| 5328 } | 5395 } |
| 5329 | 5396 |
| 5330 | 5397 |
| 5331 void HGraph::EliminateRedundantBoundsChecks() { | 5398 void HGraph::EliminateRedundantBoundsChecks() { |
| 5332 HPhase phase("H_Eliminate bounds checks", this); | 5399 HPhase phase("H_Eliminate bounds checks", this); |
| 5333 BoundsCheckTable checks_table(zone()); | 5400 if (FLAG_idefs) { |
| 5334 EliminateRedundantBoundsChecks(entry_block(), &checks_table); | 5401 EliminateRedundantBoundsChecksUsingIdefs(entry_block()); |
| 5402 ApplyBoundsChecksIndexChanges(entry_block()); |
| 5403 } else { |
| 5404 BoundsCheckTable checks_table(zone()); |
| 5405 EliminateRedundantBoundsChecks(entry_block(), &checks_table); |
| 5406 } |
| 5335 } | 5407 } |
| 5336 | 5408 |
| 5337 | 5409 |
| 5338 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { | 5410 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { |
| 5339 HValue* index = array_operation->GetKey()->ActualValue(); | 5411 HValue* index = array_operation->GetKey()->ActualValue(); |
| 5340 if (!index->representation().IsInteger32()) return; | 5412 if (!index->representation().IsInteger32()) return; |
| 5341 | 5413 |
| 5342 HConstant* constant; | 5414 HConstant* constant; |
| 5343 HValue* subexpression; | 5415 HValue* subexpression; |
| 5344 int32_t sign; | 5416 int32_t sign; |
| (...skipping 7124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12469 } | 12541 } |
| 12470 } | 12542 } |
| 12471 | 12543 |
| 12472 #ifdef DEBUG | 12544 #ifdef DEBUG |
| 12473 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 12545 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 12474 if (allocator_ != NULL) allocator_->Verify(); | 12546 if (allocator_ != NULL) allocator_->Verify(); |
| 12475 #endif | 12547 #endif |
| 12476 } | 12548 } |
| 12477 | 12549 |
| 12478 } } // namespace v8::internal | 12550 } } // namespace v8::internal |
| OLD | NEW |