| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler/bytecode-branch-analysis.h" | 10 #include "src/compiler/bytecode-branch-analysis.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 Node* GetControlDependency() const { return control_dependency_; } | 58 Node* GetControlDependency() const { return control_dependency_; } |
| 59 void UpdateControlDependency(Node* dependency) { | 59 void UpdateControlDependency(Node* dependency) { |
| 60 control_dependency_ = dependency; | 60 control_dependency_ = dependency; |
| 61 } | 61 } |
| 62 | 62 |
| 63 Node* Context() const { return context_; } | 63 Node* Context() const { return context_; } |
| 64 void SetContext(Node* new_context) { context_ = new_context; } | 64 void SetContext(Node* new_context) { context_ = new_context; } |
| 65 | 65 |
| 66 Environment* CopyForConditional(); | 66 Environment* CopyForConditional(); |
| 67 Environment* CopyForLoop(); | 67 Environment* CopyForLoop(); |
| 68 Environment* CopyForOsrEntry(); |
| 68 void Merge(Environment* other); | 69 void Merge(Environment* other); |
| 69 void PrepareForOsr(); | 70 void PrepareForOsrEntry(); |
| 70 | 71 |
| 71 void PrepareForLoopExit(Node* loop); | 72 void PrepareForLoopExit(Node* loop); |
| 72 | 73 |
| 73 private: | 74 private: |
| 74 Environment(const Environment* copy, LivenessAnalyzerBlock* liveness_block); | 75 Environment(const Environment* copy, LivenessAnalyzerBlock* liveness_block); |
| 75 void PrepareForLoop(); | 76 void PrepareForLoop(); |
| 76 | 77 |
| 77 enum { kNotCached, kCached }; | 78 enum { kNotCached, kCached }; |
| 78 | 79 |
| 79 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, | 80 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 BytecodeGraphBuilder::Environment::CopyForLoop() { | 340 BytecodeGraphBuilder::Environment::CopyForLoop() { |
| 340 PrepareForLoop(); | 341 PrepareForLoop(); |
| 341 if (liveness_block() != nullptr) { | 342 if (liveness_block() != nullptr) { |
| 342 // Finish the current block before copying. | 343 // Finish the current block before copying. |
| 343 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); | 344 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); |
| 344 } | 345 } |
| 345 return new (zone()) Environment(this, liveness_block()); | 346 return new (zone()) Environment(this, liveness_block()); |
| 346 } | 347 } |
| 347 | 348 |
| 348 BytecodeGraphBuilder::Environment* | 349 BytecodeGraphBuilder::Environment* |
| 350 BytecodeGraphBuilder::Environment::CopyForOsrEntry() { |
| 351 return new (zone()) |
| 352 Environment(this, builder_->liveness_analyzer()->NewBlock()); |
| 353 } |
| 354 |
| 355 BytecodeGraphBuilder::Environment* |
| 349 BytecodeGraphBuilder::Environment::CopyForConditional() { | 356 BytecodeGraphBuilder::Environment::CopyForConditional() { |
| 350 LivenessAnalyzerBlock* copy_liveness_block = nullptr; | 357 LivenessAnalyzerBlock* copy_liveness_block = nullptr; |
| 351 if (liveness_block() != nullptr) { | 358 if (liveness_block() != nullptr) { |
| 352 copy_liveness_block = | 359 copy_liveness_block = |
| 353 builder_->liveness_analyzer()->NewBlock(liveness_block()); | 360 builder_->liveness_analyzer()->NewBlock(liveness_block()); |
| 354 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); | 361 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); |
| 355 } | 362 } |
| 356 return new (zone()) Environment(this, copy_liveness_block); | 363 return new (zone()) Environment(this, copy_liveness_block); |
| 357 } | 364 } |
| 358 | 365 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 for (int i = 0; i < size; i++) { | 409 for (int i = 0; i < size; i++) { |
| 403 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); | 410 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); |
| 404 } | 411 } |
| 405 | 412 |
| 406 // Connect to the loop end. | 413 // Connect to the loop end. |
| 407 Node* terminate = builder()->graph()->NewNode( | 414 Node* terminate = builder()->graph()->NewNode( |
| 408 builder()->common()->Terminate(), effect, control); | 415 builder()->common()->Terminate(), effect, control); |
| 409 builder()->exit_controls_.push_back(terminate); | 416 builder()->exit_controls_.push_back(terminate); |
| 410 } | 417 } |
| 411 | 418 |
| 412 void BytecodeGraphBuilder::Environment::PrepareForOsr() { | 419 void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() { |
| 413 DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode()); | 420 DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode()); |
| 414 DCHECK_EQ(1, GetControlDependency()->InputCount()); | 421 DCHECK_EQ(1, GetControlDependency()->InputCount()); |
| 422 |
| 415 Node* start = graph()->start(); | 423 Node* start = graph()->start(); |
| 416 | 424 |
| 417 // Create a control node for the OSR entry point and merge it into the loop | 425 // Create a control node for the OSR entry point and update the current |
| 418 // header. Update the current environment's control dependency accordingly. | 426 // environment's dependencies accordingly. |
| 419 Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start); | 427 Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start); |
| 420 Node* control = builder()->MergeControl(GetControlDependency(), entry); | 428 UpdateControlDependency(entry); |
| 421 UpdateControlDependency(control); | 429 UpdateEffectDependency(entry); |
| 422 | 430 |
| 423 // Create a merge of the effect from the OSR entry and the existing effect | 431 // Create OSR values for each environment value. |
| 424 // dependency. Update the current environment's effect dependency accordingly. | 432 SetContext(graph()->NewNode( |
| 425 Node* effect = builder()->MergeEffect(GetEffectDependency(), entry, control); | 433 common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry)); |
| 426 UpdateEffectDependency(effect); | |
| 427 | |
| 428 // Rename all values in the environment which will extend or introduce Phi | |
| 429 // nodes to contain the OSR values available at the entry point. | |
| 430 Node* osr_context = graph()->NewNode( | |
| 431 common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry); | |
| 432 context_ = builder()->MergeValue(context_, osr_context, control); | |
| 433 int size = static_cast<int>(values()->size()); | 434 int size = static_cast<int>(values()->size()); |
| 434 for (int i = 0; i < size; i++) { | 435 for (int i = 0; i < size; i++) { |
| 435 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. | 436 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. |
| 436 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; | 437 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; |
| 437 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; | 438 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; |
| 438 Node* osr_value = graph()->NewNode(common()->OsrValue(idx), entry); | 439 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); |
| 439 values_[i] = builder()->MergeValue(values_[i], osr_value, control); | |
| 440 } | 440 } |
| 441 } | 441 } |
| 442 | 442 |
| 443 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( | 443 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( |
| 444 Node** state_values, int offset, int count) { | 444 Node** state_values, int offset, int count) { |
| 445 if (*state_values == nullptr) { | 445 if (*state_values == nullptr) { |
| 446 return true; | 446 return true; |
| 447 } | 447 } |
| 448 DCHECK_EQ((*state_values)->InputCount(), count); | 448 DCHECK_EQ((*state_values)->InputCount(), count); |
| 449 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); | 449 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); |
| (...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 | 1905 |
| 1906 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1906 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
| 1907 exit_controls_.push_back(exit); | 1907 exit_controls_.push_back(exit); |
| 1908 set_environment(nullptr); | 1908 set_environment(nullptr); |
| 1909 } | 1909 } |
| 1910 | 1910 |
| 1911 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { | 1911 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
| 1912 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { | 1912 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { |
| 1913 // For OSR add a special {OsrLoopEntry} node into the current loop header. | 1913 // For OSR add a special {OsrLoopEntry} node into the current loop header. |
| 1914 // It will be turned into a usable entry by the OSR deconstruction. | 1914 // It will be turned into a usable entry by the OSR deconstruction. |
| 1915 environment()->PrepareForOsr(); | 1915 Environment* loop_env = merge_environments_[current_offset]; |
| 1916 Environment* osr_env = loop_env->CopyForOsrEntry(); |
| 1917 osr_env->PrepareForOsrEntry(); |
| 1918 loop_env->Merge(osr_env); |
| 1916 } | 1919 } |
| 1917 } | 1920 } |
| 1918 | 1921 |
| 1919 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { | 1922 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { |
| 1920 if (!osr_ast_id_.IsNone()) { | 1923 if (!osr_ast_id_.IsNone()) { |
| 1921 // For OSR add an {OsrNormalEntry} as the the top-level environment start. | 1924 // For OSR add an {OsrNormalEntry} as the the top-level environment start. |
| 1922 // It will be replaced with {Dead} by the OSR deconstruction. | 1925 // It will be replaced with {Dead} by the OSR deconstruction. |
| 1923 NewNode(common()->OsrNormalEntry()); | 1926 NewNode(common()->OsrNormalEntry()); |
| 1924 // Note that the requested OSR entry point must be the target of a backward | 1927 // Note that the requested OSR entry point must be the target of a backward |
| 1925 // branch, otherwise there will not be a proper loop header available. | 1928 // branch, otherwise there will not be a proper loop header available. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 // Phi does not exist yet, introduce one. | 2194 // Phi does not exist yet, introduce one. |
| 2192 value = NewPhi(inputs, value, control); | 2195 value = NewPhi(inputs, value, control); |
| 2193 value->ReplaceInput(inputs - 1, other); | 2196 value->ReplaceInput(inputs - 1, other); |
| 2194 } | 2197 } |
| 2195 return value; | 2198 return value; |
| 2196 } | 2199 } |
| 2197 | 2200 |
| 2198 } // namespace compiler | 2201 } // namespace compiler |
| 2199 } // namespace internal | 2202 } // namespace internal |
| 2200 } // namespace v8 | 2203 } // namespace v8 |
| OLD | NEW |