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()); | |
414 DCHECK_EQ(1, GetControlDependency()->InputCount()); | |
Michael Starzinger
2016/09/29 14:29:32
Please preserve these two asserts inside {BuildOSR
Jarin
2016/09/29 14:32:54
Done.
| |
415 Node* start = graph()->start(); | 420 Node* start = graph()->start(); |
416 | 421 |
417 // Create a control node for the OSR entry point and merge it into the loop | 422 // Create a control node for the OSR entry point and update the current |
418 // header. Update the current environment's control dependency accordingly. | 423 // environment's dependencies accordingly. |
419 Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start); | 424 Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start); |
420 Node* control = builder()->MergeControl(GetControlDependency(), entry); | 425 UpdateControlDependency(entry); |
421 UpdateControlDependency(control); | 426 UpdateEffectDependency(entry); |
422 | 427 |
423 // Create a merge of the effect from the OSR entry and the existing effect | 428 // Create OSR values for each environment value. |
424 // dependency. Update the current environment's effect dependency accordingly. | 429 SetContext(graph()->NewNode( |
425 Node* effect = builder()->MergeEffect(GetEffectDependency(), entry, control); | 430 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()); | 431 int size = static_cast<int>(values()->size()); |
434 for (int i = 0; i < size; i++) { | 432 for (int i = 0; i < size; i++) { |
435 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. | 433 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. |
436 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; | 434 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; |
437 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; | 435 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; |
438 Node* osr_value = graph()->NewNode(common()->OsrValue(idx), entry); | 436 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); |
439 values_[i] = builder()->MergeValue(values_[i], osr_value, control); | |
440 } | 437 } |
441 } | 438 } |
442 | 439 |
443 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( | 440 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( |
444 Node** state_values, int offset, int count) { | 441 Node** state_values, int offset, int count) { |
445 if (*state_values == nullptr) { | 442 if (*state_values == nullptr) { |
446 return true; | 443 return true; |
447 } | 444 } |
448 DCHECK_EQ((*state_values)->InputCount(), count); | 445 DCHECK_EQ((*state_values)->InputCount(), count); |
449 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); | 446 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1905 | 1902 |
1906 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1903 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
1907 exit_controls_.push_back(exit); | 1904 exit_controls_.push_back(exit); |
1908 set_environment(nullptr); | 1905 set_environment(nullptr); |
1909 } | 1906 } |
1910 | 1907 |
1911 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { | 1908 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
1912 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { | 1909 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { |
1913 // For OSR add a special {OsrLoopEntry} node into the current loop header. | 1910 // 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. | 1911 // It will be turned into a usable entry by the OSR deconstruction. |
1915 environment()->PrepareForOsr(); | 1912 Environment* loop_env = merge_environments_[current_offset]; |
1913 Environment* osr_env = loop_env->CopyForOsrEntry(); | |
1914 osr_env->PrepareForOsrEntry(); | |
1915 loop_env->Merge(osr_env); | |
1916 } | 1916 } |
1917 } | 1917 } |
1918 | 1918 |
1919 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { | 1919 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { |
1920 if (!osr_ast_id_.IsNone()) { | 1920 if (!osr_ast_id_.IsNone()) { |
1921 // For OSR add an {OsrNormalEntry} as the the top-level environment start. | 1921 // For OSR add an {OsrNormalEntry} as the the top-level environment start. |
1922 // It will be replaced with {Dead} by the OSR deconstruction. | 1922 // It will be replaced with {Dead} by the OSR deconstruction. |
1923 NewNode(common()->OsrNormalEntry()); | 1923 NewNode(common()->OsrNormalEntry()); |
1924 // Note that the requested OSR entry point must be the target of a backward | 1924 // 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. | 1925 // 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. | 2191 // Phi does not exist yet, introduce one. |
2192 value = NewPhi(inputs, value, control); | 2192 value = NewPhi(inputs, value, control); |
2193 value->ReplaceInput(inputs - 1, other); | 2193 value->ReplaceInput(inputs - 1, other); |
2194 } | 2194 } |
2195 return value; | 2195 return value; |
2196 } | 2196 } |
2197 | 2197 |
2198 } // namespace compiler | 2198 } // namespace compiler |
2199 } // namespace internal | 2199 } // namespace internal |
2200 } // namespace v8 | 2200 } // namespace v8 |
OLD | NEW |