• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "src/interpreter/control-flow-builders.h"
6 #include "src/objects-inl.h"
7 
8 namespace v8 {
9 namespace internal {
10 namespace interpreter {
11 
12 
~BreakableControlFlowBuilder()13 BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
14   DCHECK(break_labels_.empty() || break_labels_.is_bound());
15 }
16 
BindBreakTarget()17 void BreakableControlFlowBuilder::BindBreakTarget() {
18   break_labels_.Bind(builder());
19 }
20 
EmitJump(BytecodeLabels * sites)21 void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
22   builder()->Jump(sites->New());
23 }
24 
EmitJumpIfTrue(BytecodeLabels * sites)25 void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) {
26   builder()->JumpIfTrue(sites->New());
27 }
28 
EmitJumpIfFalse(BytecodeLabels * sites)29 void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) {
30   builder()->JumpIfFalse(sites->New());
31 }
32 
EmitJumpIfUndefined(BytecodeLabels * sites)33 void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
34   builder()->JumpIfUndefined(sites->New());
35 }
36 
EmitJumpIfNull(BytecodeLabels * sites)37 void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
38   builder()->JumpIfNull(sites->New());
39 }
40 
41 
EndBlock()42 void BlockBuilder::EndBlock() {
43   builder()->Bind(&block_end_);
44   BindBreakTarget();
45 }
46 
~LoopBuilder()47 LoopBuilder::~LoopBuilder() {
48   DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
49   DCHECK(header_labels_.empty() || header_labels_.is_bound());
50 }
51 
LoopHeader(ZoneVector<BytecodeLabel> * additional_labels)52 void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) {
53   // Jumps from before the loop header into the loop violate ordering
54   // requirements of bytecode basic blocks. The only entry into a loop
55   // must be the loop header. Surely breaks is okay? Not if nested
56   // and misplaced between the headers.
57   DCHECK(break_labels_.empty() && continue_labels_.empty());
58   builder()->Bind(&loop_header_);
59   if (additional_labels != nullptr) {
60     for (auto& label : *additional_labels) {
61       builder()->Bind(&label);
62     }
63   }
64 }
65 
JumpToHeader(int loop_depth)66 void LoopBuilder::JumpToHeader(int loop_depth) {
67   // Pass the proper loop nesting level to the backwards branch, to trigger
68   // on-stack replacement when armed for the given loop nesting depth.
69   int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
70   // Loop must have closed form, i.e. all loop elements are within the loop,
71   // the loop header precedes the body and next elements in the loop.
72   DCHECK(loop_header_.is_bound());
73   builder()->JumpLoop(&loop_header_, level);
74 }
75 
EndLoop()76 void LoopBuilder::EndLoop() {
77   BindBreakTarget();
78   header_labels_.BindToLabel(builder(), loop_header_);
79 }
80 
BindContinueTarget()81 void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
82 
~SwitchBuilder()83 SwitchBuilder::~SwitchBuilder() {
84 #ifdef DEBUG
85   for (auto site : case_sites_) {
86     DCHECK(site.is_bound());
87   }
88 #endif
89 }
90 
91 
SetCaseTarget(int index)92 void SwitchBuilder::SetCaseTarget(int index) {
93   BytecodeLabel& site = case_sites_.at(index);
94   builder()->Bind(&site);
95 }
96 
97 
BeginTry(Register context)98 void TryCatchBuilder::BeginTry(Register context) {
99   builder()->MarkTryBegin(handler_id_, context);
100 }
101 
102 
EndTry()103 void TryCatchBuilder::EndTry() {
104   builder()->MarkTryEnd(handler_id_);
105   builder()->Jump(&exit_);
106   builder()->Bind(&handler_);
107   builder()->MarkHandler(handler_id_, catch_prediction_);
108 }
109 
110 
EndCatch()111 void TryCatchBuilder::EndCatch() { builder()->Bind(&exit_); }
112 
113 
BeginTry(Register context)114 void TryFinallyBuilder::BeginTry(Register context) {
115   builder()->MarkTryBegin(handler_id_, context);
116 }
117 
118 
LeaveTry()119 void TryFinallyBuilder::LeaveTry() {
120   builder()->Jump(finalization_sites_.New());
121 }
122 
123 
EndTry()124 void TryFinallyBuilder::EndTry() {
125   builder()->MarkTryEnd(handler_id_);
126 }
127 
128 
BeginHandler()129 void TryFinallyBuilder::BeginHandler() {
130   builder()->Bind(&handler_);
131   builder()->MarkHandler(handler_id_, catch_prediction_);
132 }
133 
BeginFinally()134 void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); }
135 
EndFinally()136 void TryFinallyBuilder::EndFinally() {
137   // Nothing to be done here.
138 }
139 
140 }  // namespace interpreter
141 }  // namespace internal
142 }  // namespace v8
143