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/compiler-source-position-table.h" | 10 #include "src/compiler/compiler-source-position-table.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 // Control dependency tracked by this environment. | 62 // Control dependency tracked by this environment. |
63 Node* GetControlDependency() const { return control_dependency_; } | 63 Node* GetControlDependency() const { return control_dependency_; } |
64 void UpdateControlDependency(Node* dependency) { | 64 void UpdateControlDependency(Node* dependency) { |
65 control_dependency_ = dependency; | 65 control_dependency_ = dependency; |
66 } | 66 } |
67 | 67 |
68 Node* Context() const { return context_; } | 68 Node* Context() const { return context_; } |
69 void SetContext(Node* new_context) { context_ = new_context; } | 69 void SetContext(Node* new_context) { context_ = new_context; } |
70 | 70 |
71 Environment* CopyForConditional(); | 71 Environment* Copy(); |
72 Environment* CopyForLoop(); | |
73 Environment* CopyForOsrEntry(); | |
74 void Merge(Environment* other); | 72 void Merge(Environment* other); |
| 73 |
75 void PrepareForOsrEntry(); | 74 void PrepareForOsrEntry(); |
76 | 75 void PrepareForLoop(const BytecodeLoopAssignments& assignments); |
77 void PrepareForLoopExit(Node* loop); | 76 void PrepareForLoopExit(Node* loop, |
| 77 const BytecodeLoopAssignments& assignments); |
78 | 78 |
79 private: | 79 private: |
80 explicit Environment(const Environment* copy); | 80 explicit Environment(const Environment* copy); |
81 void PrepareForLoop(); | |
82 | 81 |
83 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); | 82 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); |
84 void UpdateStateValues(Node** state_values, Node** values, int count); | 83 void UpdateStateValues(Node** state_values, Node** values, int count); |
85 void UpdateStateValuesWithCache(Node** state_values, Node** values, | 84 void UpdateStateValuesWithCache(Node** state_values, Node** values, |
86 int count); | 85 int count); |
87 | 86 |
88 int RegisterToValuesIndex(interpreter::Register the_register) const; | 87 int RegisterToValuesIndex(interpreter::Register the_register) const; |
89 | 88 |
90 Zone* zone() const { return builder_->local_zone(); } | 89 Zone* zone() const { return builder_->local_zone(); } |
91 Graph* graph() const { return builder_->graph(); } | 90 Graph* graph() const { return builder_->graph(); } |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } | 242 } |
244 } | 243 } |
245 | 244 |
246 void BytecodeGraphBuilder::Environment::RecordAfterState( | 245 void BytecodeGraphBuilder::Environment::RecordAfterState( |
247 Node* node, FrameStateAttachmentMode mode) { | 246 Node* node, FrameStateAttachmentMode mode) { |
248 if (mode == FrameStateAttachmentMode::kAttachFrameState) { | 247 if (mode == FrameStateAttachmentMode::kAttachFrameState) { |
249 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); | 248 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); |
250 } | 249 } |
251 } | 250 } |
252 | 251 |
253 | 252 BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() { |
254 BytecodeGraphBuilder::Environment* | |
255 BytecodeGraphBuilder::Environment::CopyForLoop() { | |
256 PrepareForLoop(); | |
257 return new (zone()) Environment(this); | 253 return new (zone()) Environment(this); |
258 } | 254 } |
259 | 255 |
260 BytecodeGraphBuilder::Environment* | |
261 BytecodeGraphBuilder::Environment::CopyForOsrEntry() { | |
262 return new (zone()) Environment(this); | |
263 } | |
264 | |
265 BytecodeGraphBuilder::Environment* | |
266 BytecodeGraphBuilder::Environment::CopyForConditional() { | |
267 return new (zone()) Environment(this); | |
268 } | |
269 | |
270 | 256 |
271 void BytecodeGraphBuilder::Environment::Merge( | 257 void BytecodeGraphBuilder::Environment::Merge( |
272 BytecodeGraphBuilder::Environment* other) { | 258 BytecodeGraphBuilder::Environment* other) { |
273 // Create a merge of the control dependencies of both environments and update | 259 // Create a merge of the control dependencies of both environments and update |
274 // the current environment's control dependency accordingly. | 260 // the current environment's control dependency accordingly. |
275 Node* control = builder()->MergeControl(GetControlDependency(), | 261 Node* control = builder()->MergeControl(GetControlDependency(), |
276 other->GetControlDependency()); | 262 other->GetControlDependency()); |
277 UpdateControlDependency(control); | 263 UpdateControlDependency(control); |
278 | 264 |
279 // Create a merge of the effect dependencies of both environments and update | 265 // Create a merge of the effect dependencies of both environments and update |
280 // the current environment's effect dependency accordingly. | 266 // the current environment's effect dependency accordingly. |
281 Node* effect = builder()->MergeEffect(GetEffectDependency(), | 267 Node* effect = builder()->MergeEffect(GetEffectDependency(), |
282 other->GetEffectDependency(), control); | 268 other->GetEffectDependency(), control); |
283 UpdateEffectDependency(effect); | 269 UpdateEffectDependency(effect); |
284 | 270 |
285 // Introduce Phi nodes for values that have differing input at merge points, | 271 // Introduce Phi nodes for values that have differing input at merge points, |
286 // potentially extending an existing Phi node if possible. | 272 // potentially extending an existing Phi node if possible. |
287 context_ = builder()->MergeValue(context_, other->context_, control); | 273 context_ = builder()->MergeValue(context_, other->context_, control); |
288 for (size_t i = 0; i < values_.size(); i++) { | 274 for (size_t i = 0; i < values_.size(); i++) { |
289 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); | 275 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); |
290 } | 276 } |
291 } | 277 } |
292 | 278 |
293 | 279 void BytecodeGraphBuilder::Environment::PrepareForLoop( |
294 void BytecodeGraphBuilder::Environment::PrepareForLoop() { | 280 const BytecodeLoopAssignments& assignments) { |
295 // Create a control node for the loop header. | 281 // Create a control node for the loop header. |
296 Node* control = builder()->NewLoop(); | 282 Node* control = builder()->NewLoop(); |
297 | 283 |
298 // Create a Phi for external effects. | 284 // Create a Phi for external effects. |
299 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); | 285 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); |
300 UpdateEffectDependency(effect); | 286 UpdateEffectDependency(effect); |
301 | 287 |
302 // Assume everything in the loop is updated. | 288 // Create Phis for any values that may be updated by the end of the loop. |
303 context_ = builder()->NewPhi(1, context_, control); | 289 context_ = builder()->NewPhi(1, context_, control); |
304 int size = static_cast<int>(values()->size()); | 290 for (int i = 0; i < parameter_count(); i++) { |
305 for (int i = 0; i < size; i++) { | 291 if (assignments.ContainsParameter(i)) { |
306 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); | 292 values_[i] = builder()->NewPhi(1, values_[i], control); |
| 293 } |
| 294 } |
| 295 for (int i = 0; i < register_count(); i++) { |
| 296 if (assignments.ContainsLocal(i)) { |
| 297 int index = register_base() + i; |
| 298 values_[index] = builder()->NewPhi(1, values_[index], control); |
| 299 } |
| 300 } |
| 301 |
| 302 if (assignments.ContainsAccumulator()) { |
| 303 values_[accumulator_base()] = |
| 304 builder()->NewPhi(1, values_[accumulator_base()], control); |
307 } | 305 } |
308 | 306 |
309 // Connect to the loop end. | 307 // Connect to the loop end. |
310 Node* terminate = builder()->graph()->NewNode( | 308 Node* terminate = builder()->graph()->NewNode( |
311 builder()->common()->Terminate(), effect, control); | 309 builder()->common()->Terminate(), effect, control); |
312 builder()->exit_controls_.push_back(terminate); | 310 builder()->exit_controls_.push_back(terminate); |
313 } | 311 } |
314 | 312 |
315 void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() { | 313 void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() { |
316 DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode()); | 314 DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 } | 359 } |
362 DCHECK_EQ((*state_values)->InputCount(), count); | 360 DCHECK_EQ((*state_values)->InputCount(), count); |
363 for (int i = 0; i < count; i++) { | 361 for (int i = 0; i < count; i++) { |
364 if ((*state_values)->InputAt(i) != values[i]) { | 362 if ((*state_values)->InputAt(i) != values[i]) { |
365 return true; | 363 return true; |
366 } | 364 } |
367 } | 365 } |
368 return false; | 366 return false; |
369 } | 367 } |
370 | 368 |
371 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { | 369 void BytecodeGraphBuilder::Environment::PrepareForLoopExit( |
| 370 Node* loop, const BytecodeLoopAssignments& assignments) { |
372 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); | 371 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); |
373 | 372 |
374 Node* control = GetControlDependency(); | 373 Node* control = GetControlDependency(); |
375 | 374 |
376 // Create the loop exit node. | 375 // Create the loop exit node. |
377 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); | 376 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); |
378 UpdateControlDependency(loop_exit); | 377 UpdateControlDependency(loop_exit); |
379 | 378 |
380 // Rename the effect. | 379 // Rename the effect. |
381 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), | 380 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), |
382 GetEffectDependency(), loop_exit); | 381 GetEffectDependency(), loop_exit); |
383 UpdateEffectDependency(effect_rename); | 382 UpdateEffectDependency(effect_rename); |
384 | 383 |
385 // TODO(jarin) We should also rename context here. However, uncoditional | 384 // TODO(jarin) We should also rename context here. However, unconditional |
386 // renaming confuses global object and native context specialization. | 385 // renaming confuses global object and native context specialization. |
387 // We should only rename if the context is assigned in the loop. | 386 // We should only rename if the context is assigned in the loop. |
388 | 387 |
389 // Rename the environmnent values. | 388 // Rename the environment values if they were assigned in the loop. |
390 for (size_t i = 0; i < values_.size(); i++) { | 389 for (int i = 0; i < parameter_count(); i++) { |
391 Node* rename = | 390 if (assignments.ContainsParameter(i)) { |
392 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); | 391 Node* rename = |
393 values_[i] = rename; | 392 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); |
| 393 values_[i] = rename; |
| 394 } |
| 395 } |
| 396 for (int i = 0; i < register_count(); i++) { |
| 397 if (assignments.ContainsLocal(i)) { |
| 398 Node* rename = graph()->NewNode(common()->LoopExitValue(), |
| 399 values_[register_base() + i], loop_exit); |
| 400 values_[register_base() + i] = rename; |
| 401 } |
| 402 } |
| 403 |
| 404 if (assignments.ContainsAccumulator()) { |
| 405 Node* rename = graph()->NewNode(common()->LoopExitValue(), |
| 406 values_[accumulator_base()], loop_exit); |
| 407 values_[accumulator_base()] = rename; |
394 } | 408 } |
395 } | 409 } |
396 | 410 |
397 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, | 411 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
398 Node** values, | 412 Node** values, |
399 int count) { | 413 int count) { |
400 if (StateValuesRequireUpdate(state_values, values, count)) { | 414 if (StateValuesRequireUpdate(state_values, values, count)) { |
401 const Operator* op = common()->StateValues(count); | 415 const Operator* op = common()->StateValues(count); |
402 (*state_values) = graph()->NewNode(op, count, values); | 416 (*state_values) = graph()->NewNode(op, count, values); |
403 } | 417 } |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 | 612 |
599 Node* frame_state_after = environment()->Checkpoint( | 613 Node* frame_state_after = environment()->Checkpoint( |
600 bailout_id, combine, has_exception, liveness_after); | 614 bailout_id, combine, has_exception, liveness_after); |
601 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); | 615 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); |
602 } | 616 } |
603 } | 617 } |
604 | 618 |
605 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { | 619 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { |
606 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(), | 620 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(), |
607 FLAG_analyze_environment_liveness); | 621 FLAG_analyze_environment_liveness); |
608 bytecode_analysis.Analyze(); | 622 bytecode_analysis.Analyze(osr_ast_id_); |
609 set_bytecode_analysis(&bytecode_analysis); | 623 set_bytecode_analysis(&bytecode_analysis); |
610 | 624 |
611 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 625 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
612 set_bytecode_iterator(&iterator); | 626 set_bytecode_iterator(&iterator); |
613 SourcePositionTableIterator source_position_iterator( | 627 SourcePositionTableIterator source_position_iterator( |
614 bytecode_array()->source_position_table()); | 628 bytecode_array()->source_position_table()); |
615 | 629 |
616 if (FLAG_trace_environment_liveness) { | 630 if (FLAG_trace_environment_liveness) { |
617 OFStream of(stdout); | 631 OFStream of(stdout); |
618 | 632 |
619 bytecode_analysis.PrintLivenessTo(of); | 633 bytecode_analysis.PrintLivenessTo(of); |
620 } | 634 } |
621 | 635 |
622 BuildOSRNormalEntryPoint(); | 636 BuildOSRNormalEntryPoint(); |
623 | 637 |
624 for (; !iterator.done(); iterator.Advance()) { | 638 for (; !iterator.done(); iterator.Advance()) { |
625 int current_offset = iterator.current_offset(); | 639 int current_offset = iterator.current_offset(); |
626 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); | 640 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); |
627 EnterAndExitExceptionHandlers(current_offset); | 641 EnterAndExitExceptionHandlers(current_offset); |
628 SwitchToMergeEnvironment(current_offset); | 642 SwitchToMergeEnvironment(current_offset); |
629 if (environment() != nullptr) { | 643 if (environment() != nullptr) { |
630 BuildLoopHeaderEnvironment(current_offset); | 644 BuildLoopHeaderEnvironment(current_offset); |
631 BuildOSRLoopEntryPoint(current_offset); | |
632 | 645 |
633 // Skip the first stack check if stack_check is false | 646 // Skip the first stack check if stack_check is false |
634 if (!stack_check && | 647 if (!stack_check && |
635 iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) { | 648 iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) { |
636 stack_check = true; | 649 stack_check = true; |
637 continue; | 650 continue; |
638 } | 651 } |
639 | 652 |
640 switch (iterator.current_bytecode()) { | 653 switch (iterator.current_bytecode()) { |
641 #define BYTECODE_CASE(name, ...) \ | 654 #define BYTECODE_CASE(name, ...) \ |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 // the same scope as the variable itself has no way of shadowing it. | 861 // the same scope as the variable itself has no way of shadowing it. |
849 for (uint32_t d = 0; d < depth; d++) { | 862 for (uint32_t d = 0; d < depth; d++) { |
850 Node* extension_slot = | 863 Node* extension_slot = |
851 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false)); | 864 NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false)); |
852 | 865 |
853 Node* check_no_extension = | 866 Node* check_no_extension = |
854 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), | 867 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), |
855 extension_slot, jsgraph()->TheHoleConstant()); | 868 extension_slot, jsgraph()->TheHoleConstant()); |
856 | 869 |
857 NewBranch(check_no_extension); | 870 NewBranch(check_no_extension); |
858 Environment* true_environment = environment()->CopyForConditional(); | 871 Environment* true_environment = environment()->Copy(); |
859 | 872 |
860 { | 873 { |
861 NewIfFalse(); | 874 NewIfFalse(); |
862 // If there is an extension, merge into the slow path. | 875 // If there is an extension, merge into the slow path. |
863 if (slow_environment == nullptr) { | 876 if (slow_environment == nullptr) { |
864 slow_environment = environment(); | 877 slow_environment = environment(); |
865 NewMerge(); | 878 NewMerge(); |
866 } else { | 879 } else { |
867 slow_environment->Merge(environment()); | 880 slow_environment->Merge(environment()); |
868 } | 881 } |
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1894 if (it != merge_environments_.end()) { | 1907 if (it != merge_environments_.end()) { |
1895 if (environment() != nullptr) { | 1908 if (environment() != nullptr) { |
1896 it->second->Merge(environment()); | 1909 it->second->Merge(environment()); |
1897 } | 1910 } |
1898 set_environment(it->second); | 1911 set_environment(it->second); |
1899 } | 1912 } |
1900 } | 1913 } |
1901 | 1914 |
1902 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { | 1915 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
1903 if (bytecode_analysis()->IsLoopHeader(current_offset)) { | 1916 if (bytecode_analysis()->IsLoopHeader(current_offset)) { |
1904 // Add loop header and store a copy so we can connect merged back | 1917 const LoopInfo& loop_info = |
1905 // edge inputs to the loop header. | 1918 bytecode_analysis()->GetLoopInfoFor(current_offset); |
1906 merge_environments_[current_offset] = environment()->CopyForLoop(); | 1919 |
| 1920 // Add loop header. |
| 1921 environment()->PrepareForLoop(loop_info.assignments()); |
| 1922 |
| 1923 BuildOSRLoopEntryPoint(current_offset); |
| 1924 |
| 1925 // Store a copy of the environment so we can connect merged back edge inputs |
| 1926 // to the loop header. |
| 1927 merge_environments_[current_offset] = environment()->Copy(); |
1907 } | 1928 } |
1908 } | 1929 } |
1909 | 1930 |
1910 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { | 1931 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
1911 BuildLoopExitsForBranch(target_offset); | 1932 BuildLoopExitsForBranch(target_offset); |
1912 Environment*& merge_environment = merge_environments_[target_offset]; | 1933 Environment*& merge_environment = merge_environments_[target_offset]; |
1913 if (merge_environment == nullptr) { | 1934 if (merge_environment == nullptr) { |
1914 // Append merge nodes to the environment. We may merge here with another | 1935 // Append merge nodes to the environment. We may merge here with another |
1915 // environment. So add a place holder for merge nodes. We may add redundant | 1936 // environment. So add a place holder for merge nodes. We may add redundant |
1916 // but will be eliminated in a later pass. | 1937 // but will be eliminated in a later pass. |
1917 // TODO(mstarzinger): Be smarter about this! | 1938 // TODO(mstarzinger): Be smarter about this! |
1918 NewMerge(); | 1939 NewMerge(); |
1919 merge_environment = environment(); | 1940 merge_environment = environment(); |
1920 } else { | 1941 } else { |
1921 merge_environment->Merge(environment()); | 1942 merge_environment->Merge(environment()); |
1922 } | 1943 } |
1923 set_environment(nullptr); | 1944 set_environment(nullptr); |
1924 } | 1945 } |
1925 | 1946 |
1926 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1947 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
1927 exit_controls_.push_back(exit); | 1948 exit_controls_.push_back(exit); |
1928 set_environment(nullptr); | 1949 set_environment(nullptr); |
1929 } | 1950 } |
1930 | 1951 |
1931 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { | 1952 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
| 1953 DCHECK(bytecode_analysis()->IsLoopHeader(current_offset)); |
| 1954 |
1932 if (!osr_ast_id_.IsNone() && osr_loop_offset_ == current_offset) { | 1955 if (!osr_ast_id_.IsNone() && osr_loop_offset_ == current_offset) { |
1933 // For OSR add a special {OsrLoopEntry} node into the current loop header. | 1956 // For OSR add a special {OsrLoopEntry} node into the current loop header. |
1934 // It will be turned into a usable entry by the OSR deconstruction. | 1957 // It will be turned into a usable entry by the OSR deconstruction. |
1935 Environment* loop_env = merge_environments_[current_offset]; | 1958 Environment* osr_env = environment()->Copy(); |
1936 Environment* osr_env = loop_env->CopyForOsrEntry(); | |
1937 osr_env->PrepareForOsrEntry(); | 1959 osr_env->PrepareForOsrEntry(); |
1938 loop_env->Merge(osr_env); | 1960 environment()->Merge(osr_env); |
1939 } | 1961 } |
1940 } | 1962 } |
1941 | 1963 |
1942 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { | 1964 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { |
1943 if (!osr_ast_id_.IsNone()) { | 1965 if (!osr_ast_id_.IsNone()) { |
1944 // For OSR add an {OsrNormalEntry} as the the top-level environment start. | 1966 // For OSR add an {OsrNormalEntry} as the the top-level environment start. |
1945 // It will be replaced with {Dead} by the OSR deconstruction. | 1967 // It will be replaced with {Dead} by the OSR deconstruction. |
1946 NewNode(common()->OsrNormalEntry()); | 1968 NewNode(common()->OsrNormalEntry()); |
1947 // Translate the offset of the jump instruction to the jump target offset of | 1969 // Translate the offset of the jump instruction to the jump target offset of |
1948 // that instruction so that the derived BailoutId points to the loop header. | 1970 // that instruction so that the derived BailoutId points to the loop header. |
(...skipping 10 matching lines...) Expand all Loading... |
1959 BuildLoopExitsUntilLoop( | 1981 BuildLoopExitsUntilLoop( |
1960 bytecode_analysis()->GetLoopOffsetFor(target_offset)); | 1982 bytecode_analysis()->GetLoopOffsetFor(target_offset)); |
1961 } | 1983 } |
1962 } | 1984 } |
1963 | 1985 |
1964 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { | 1986 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { |
1965 int origin_offset = bytecode_iterator().current_offset(); | 1987 int origin_offset = bytecode_iterator().current_offset(); |
1966 int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset); | 1988 int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset); |
1967 while (loop_offset < current_loop) { | 1989 while (loop_offset < current_loop) { |
1968 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); | 1990 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); |
1969 environment()->PrepareForLoopExit(loop_node); | 1991 const LoopInfo& loop_info = |
1970 current_loop = bytecode_analysis()->GetParentLoopFor(current_loop); | 1992 bytecode_analysis()->GetLoopInfoFor(current_loop); |
| 1993 environment()->PrepareForLoopExit(loop_node, loop_info.assignments()); |
| 1994 current_loop = loop_info.parent_offset(); |
1971 } | 1995 } |
1972 } | 1996 } |
1973 | 1997 |
1974 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { | 1998 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { |
1975 BuildLoopExitsUntilLoop(-1); | 1999 BuildLoopExitsUntilLoop(-1); |
1976 } | 2000 } |
1977 | 2001 |
1978 void BytecodeGraphBuilder::BuildJump() { | 2002 void BytecodeGraphBuilder::BuildJump() { |
1979 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 2003 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1980 } | 2004 } |
1981 | 2005 |
1982 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { | 2006 void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { |
1983 NewBranch(condition); | 2007 NewBranch(condition); |
1984 Environment* if_false_environment = environment()->CopyForConditional(); | 2008 Environment* if_false_environment = environment()->Copy(); |
1985 NewIfTrue(); | 2009 NewIfTrue(); |
1986 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 2010 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1987 set_environment(if_false_environment); | 2011 set_environment(if_false_environment); |
1988 NewIfFalse(); | 2012 NewIfFalse(); |
1989 } | 2013 } |
1990 | 2014 |
1991 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { | 2015 void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { |
1992 NewBranch(condition); | 2016 NewBranch(condition); |
1993 Environment* if_true_environment = environment()->CopyForConditional(); | 2017 Environment* if_true_environment = environment()->Copy(); |
1994 NewIfFalse(); | 2018 NewIfFalse(); |
1995 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 2019 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1996 set_environment(if_true_environment); | 2020 set_environment(if_true_environment); |
1997 NewIfTrue(); | 2021 NewIfTrue(); |
1998 } | 2022 } |
1999 | 2023 |
2000 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { | 2024 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { |
2001 Node* accumulator = environment()->LookupAccumulator(); | 2025 Node* accumulator = environment()->LookupAccumulator(); |
2002 Node* condition = | 2026 Node* condition = |
2003 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), | 2027 NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2121 } | 2145 } |
2122 // Update the current effect dependency for effect-producing nodes. | 2146 // Update the current effect dependency for effect-producing nodes. |
2123 if (result->op()->EffectOutputCount() > 0) { | 2147 if (result->op()->EffectOutputCount() > 0) { |
2124 environment()->UpdateEffectDependency(result); | 2148 environment()->UpdateEffectDependency(result); |
2125 } | 2149 } |
2126 // Add implicit exception continuation for throwing nodes. | 2150 // Add implicit exception continuation for throwing nodes. |
2127 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { | 2151 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { |
2128 int handler_offset = exception_handlers_.top().handler_offset_; | 2152 int handler_offset = exception_handlers_.top().handler_offset_; |
2129 int context_index = exception_handlers_.top().context_register_; | 2153 int context_index = exception_handlers_.top().context_register_; |
2130 interpreter::Register context_register(context_index); | 2154 interpreter::Register context_register(context_index); |
2131 Environment* success_env = environment()->CopyForConditional(); | 2155 Environment* success_env = environment()->Copy(); |
2132 const Operator* op = common()->IfException(); | 2156 const Operator* op = common()->IfException(); |
2133 Node* effect = environment()->GetEffectDependency(); | 2157 Node* effect = environment()->GetEffectDependency(); |
2134 Node* on_exception = graph()->NewNode(op, effect, result); | 2158 Node* on_exception = graph()->NewNode(op, effect, result); |
2135 Node* context = environment()->LookupRegister(context_register); | 2159 Node* context = environment()->LookupRegister(context_register); |
2136 environment()->UpdateControlDependency(on_exception); | 2160 environment()->UpdateControlDependency(on_exception); |
2137 environment()->UpdateEffectDependency(on_exception); | 2161 environment()->UpdateEffectDependency(on_exception); |
2138 environment()->BindAccumulator(on_exception); | 2162 environment()->BindAccumulator(on_exception); |
2139 environment()->SetContext(context); | 2163 environment()->SetContext(context); |
2140 MergeIntoSuccessorEnvironment(handler_offset); | 2164 MergeIntoSuccessorEnvironment(handler_offset); |
2141 set_environment(success_env); | 2165 set_environment(success_env); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2236 it->source_position().ScriptOffset(), start_position_.InliningId())); | 2260 it->source_position().ScriptOffset(), start_position_.InliningId())); |
2237 it->Advance(); | 2261 it->Advance(); |
2238 } else { | 2262 } else { |
2239 DCHECK_GT(it->code_offset(), offset); | 2263 DCHECK_GT(it->code_offset(), offset); |
2240 } | 2264 } |
2241 } | 2265 } |
2242 | 2266 |
2243 } // namespace compiler | 2267 } // namespace compiler |
2244 } // namespace internal | 2268 } // namespace internal |
2245 } // namespace v8 | 2269 } // namespace v8 |
OLD | NEW |