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 17 matching lines...) Expand all Loading... |
28 // Specifies whether environment binding methods should attach frame state | 28 // Specifies whether environment binding methods should attach frame state |
29 // inputs to nodes representing the value being bound. This is done because | 29 // inputs to nodes representing the value being bound. This is done because |
30 // the {OutputFrameStateCombine} is closely related to the binding method. | 30 // the {OutputFrameStateCombine} is closely related to the binding method. |
31 enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState }; | 31 enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState }; |
32 | 32 |
33 int parameter_count() const { return parameter_count_; } | 33 int parameter_count() const { return parameter_count_; } |
34 int register_count() const { return register_count_; } | 34 int register_count() const { return register_count_; } |
35 | 35 |
36 Node* LookupAccumulator() const; | 36 Node* LookupAccumulator() const; |
37 Node* LookupRegister(interpreter::Register the_register) const; | 37 Node* LookupRegister(interpreter::Register the_register) const; |
38 void MarkAllRegistersLive(); | |
39 | 38 |
40 void BindAccumulator(Node* node, | 39 void BindAccumulator(Node* node, |
41 FrameStateAttachmentMode mode = kDontAttachFrameState); | 40 FrameStateAttachmentMode mode = kDontAttachFrameState); |
42 void BindRegister(interpreter::Register the_register, Node* node, | 41 void BindRegister(interpreter::Register the_register, Node* node, |
43 FrameStateAttachmentMode mode = kDontAttachFrameState); | 42 FrameStateAttachmentMode mode = kDontAttachFrameState); |
44 void BindRegistersToProjections( | 43 void BindRegistersToProjections( |
45 interpreter::Register first_reg, Node* node, | 44 interpreter::Register first_reg, Node* node, |
46 FrameStateAttachmentMode mode = kDontAttachFrameState); | 45 FrameStateAttachmentMode mode = kDontAttachFrameState); |
47 void RecordAfterState(Node* node, | 46 void RecordAfterState(Node* node, |
48 FrameStateAttachmentMode mode = kDontAttachFrameState); | 47 FrameStateAttachmentMode mode = kDontAttachFrameState); |
49 | 48 |
50 // Effect dependency tracked by this environment. | 49 // Effect dependency tracked by this environment. |
51 Node* GetEffectDependency() { return effect_dependency_; } | 50 Node* GetEffectDependency() { return effect_dependency_; } |
52 void UpdateEffectDependency(Node* dependency) { | 51 void UpdateEffectDependency(Node* dependency) { |
53 effect_dependency_ = dependency; | 52 effect_dependency_ = dependency; |
54 } | 53 } |
55 | 54 |
56 // Preserve a checkpoint of the environment for the IR graph. Any | 55 // Preserve a checkpoint of the environment for the IR graph. Any |
57 // further mutation of the environment will not affect checkpoints. | 56 // further mutation of the environment will not affect checkpoints. |
58 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine, | 57 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine, |
59 bool owner_has_exception); | 58 bool owner_has_exception, const BitVector* liveness); |
60 | 59 |
61 // Control dependency tracked by this environment. | 60 // Control dependency tracked by this environment. |
62 Node* GetControlDependency() const { return control_dependency_; } | 61 Node* GetControlDependency() const { return control_dependency_; } |
63 void UpdateControlDependency(Node* dependency) { | 62 void UpdateControlDependency(Node* dependency) { |
64 control_dependency_ = dependency; | 63 control_dependency_ = dependency; |
65 } | 64 } |
66 | 65 |
67 Node* Context() const { return context_; } | 66 Node* Context() const { return context_; } |
68 void SetContext(Node* new_context) { context_ = new_context; } | 67 void SetContext(Node* new_context) { context_ = new_context; } |
69 | 68 |
70 Environment* CopyForConditional(); | 69 Environment* CopyForConditional(); |
71 Environment* CopyForLoop(); | 70 Environment* CopyForLoop(); |
72 Environment* CopyForOsrEntry(); | 71 Environment* CopyForOsrEntry(); |
73 void Merge(Environment* other); | 72 void Merge(Environment* other); |
74 void PrepareForOsrEntry(); | 73 void PrepareForOsrEntry(); |
75 | 74 |
76 void PrepareForLoopExit(Node* loop); | 75 void PrepareForLoopExit(Node* loop); |
77 | 76 |
78 private: | 77 private: |
79 Environment(const Environment* copy, LivenessAnalyzerBlock* liveness_block); | 78 explicit Environment(const Environment* copy); |
80 void PrepareForLoop(); | 79 void PrepareForLoop(); |
81 | 80 |
82 bool StateValuesRequireUpdate(Node** state_values, int offset, int count); | 81 bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); |
83 void UpdateStateValues(Node** state_values, int offset, int count); | 82 void UpdateStateValues(Node** state_values, Node** values, int count); |
| 83 void UpdateStateValuesWithCache(Node** state_values, Node** values, |
| 84 int count); |
84 | 85 |
85 int RegisterToValuesIndex(interpreter::Register the_register) const; | 86 int RegisterToValuesIndex(interpreter::Register the_register) const; |
86 | 87 |
87 bool IsLivenessBlockConsistent() const; | |
88 | |
89 Zone* zone() const { return builder_->local_zone(); } | 88 Zone* zone() const { return builder_->local_zone(); } |
90 Graph* graph() const { return builder_->graph(); } | 89 Graph* graph() const { return builder_->graph(); } |
91 CommonOperatorBuilder* common() const { return builder_->common(); } | 90 CommonOperatorBuilder* common() const { return builder_->common(); } |
92 BytecodeGraphBuilder* builder() const { return builder_; } | 91 BytecodeGraphBuilder* builder() const { return builder_; } |
93 LivenessAnalyzerBlock* liveness_block() const { return liveness_block_; } | |
94 const NodeVector* values() const { return &values_; } | 92 const NodeVector* values() const { return &values_; } |
95 NodeVector* values() { return &values_; } | 93 NodeVector* values() { return &values_; } |
96 int register_base() const { return register_base_; } | 94 int register_base() const { return register_base_; } |
97 int accumulator_base() const { return accumulator_base_; } | 95 int accumulator_base() const { return accumulator_base_; } |
98 | 96 |
99 BytecodeGraphBuilder* builder_; | 97 BytecodeGraphBuilder* builder_; |
100 int register_count_; | 98 int register_count_; |
101 int parameter_count_; | 99 int parameter_count_; |
102 LivenessAnalyzerBlock* liveness_block_; | |
103 Node* context_; | 100 Node* context_; |
104 Node* control_dependency_; | 101 Node* control_dependency_; |
105 Node* effect_dependency_; | 102 Node* effect_dependency_; |
106 NodeVector values_; | 103 NodeVector values_; |
107 Node* parameters_state_values_; | 104 Node* parameters_state_values_; |
108 Node* registers_state_values_; | 105 Node* registers_state_values_; |
109 Node* accumulator_state_values_; | 106 Node* accumulator_state_values_; |
110 int register_base_; | 107 int register_base_; |
111 int accumulator_base_; | 108 int accumulator_base_; |
| 109 |
| 110 // A working area for writing maybe-dead values to when updating the state |
| 111 // values for registers. |
| 112 NodeVector state_value_working_area_; |
112 }; | 113 }; |
113 | 114 |
114 | 115 |
115 // Issues: | 116 // Issues: |
116 // - Scopes - intimately tied to AST. Need to eval what is needed. | 117 // - Scopes - intimately tied to AST. Need to eval what is needed. |
117 // - Need to resolve closure parameter treatment. | 118 // - Need to resolve closure parameter treatment. |
118 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, | 119 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, |
119 int register_count, | 120 int register_count, |
120 int parameter_count, | 121 int parameter_count, |
121 Node* control_dependency, | 122 Node* control_dependency, |
122 Node* context) | 123 Node* context) |
123 : builder_(builder), | 124 : builder_(builder), |
124 register_count_(register_count), | 125 register_count_(register_count), |
125 parameter_count_(parameter_count), | 126 parameter_count_(parameter_count), |
126 liveness_block_(builder->is_liveness_analysis_enabled_ | |
127 ? builder_->liveness_analyzer()->NewBlock() | |
128 : nullptr), | |
129 context_(context), | 127 context_(context), |
130 control_dependency_(control_dependency), | 128 control_dependency_(control_dependency), |
131 effect_dependency_(control_dependency), | 129 effect_dependency_(control_dependency), |
132 values_(builder->local_zone()), | 130 values_(builder->local_zone()), |
133 parameters_state_values_(nullptr), | 131 parameters_state_values_(nullptr), |
134 registers_state_values_(nullptr), | 132 registers_state_values_(nullptr), |
135 accumulator_state_values_(nullptr) { | 133 accumulator_state_values_(nullptr), |
| 134 state_value_working_area_(builder->local_zone()) { |
136 // The layout of values_ is: | 135 // The layout of values_ is: |
137 // | 136 // |
138 // [receiver] [parameters] [registers] [accumulator] | 137 // [receiver] [parameters] [registers] [accumulator] |
139 // | 138 // |
140 // parameter[0] is the receiver (this), parameters 1..N are the | 139 // parameter[0] is the receiver (this), parameters 1..N are the |
141 // parameters supplied to the method (arg0..argN-1). The accumulator | 140 // parameters supplied to the method (arg0..argN-1). The accumulator |
142 // is stored separately. | 141 // is stored separately. |
143 | 142 |
144 // Parameters including the receiver | 143 // Parameters including the receiver |
145 for (int i = 0; i < parameter_count; i++) { | 144 for (int i = 0; i < parameter_count; i++) { |
146 const char* debug_name = (i == 0) ? "%this" : nullptr; | 145 const char* debug_name = (i == 0) ? "%this" : nullptr; |
147 const Operator* op = common()->Parameter(i, debug_name); | 146 const Operator* op = common()->Parameter(i, debug_name); |
148 Node* parameter = builder->graph()->NewNode(op, graph()->start()); | 147 Node* parameter = builder->graph()->NewNode(op, graph()->start()); |
149 values()->push_back(parameter); | 148 values()->push_back(parameter); |
150 } | 149 } |
151 | 150 |
152 // Registers | 151 // Registers |
153 register_base_ = static_cast<int>(values()->size()); | 152 register_base_ = static_cast<int>(values()->size()); |
154 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 153 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
155 values()->insert(values()->end(), register_count, undefined_constant); | 154 values()->insert(values()->end(), register_count, undefined_constant); |
156 | 155 |
157 // Accumulator | 156 // Accumulator |
158 accumulator_base_ = static_cast<int>(values()->size()); | 157 accumulator_base_ = static_cast<int>(values()->size()); |
159 values()->push_back(undefined_constant); | 158 values()->push_back(undefined_constant); |
| 159 |
| 160 state_value_working_area_.resize(register_count_); |
160 } | 161 } |
161 | 162 |
162 BytecodeGraphBuilder::Environment::Environment( | 163 BytecodeGraphBuilder::Environment::Environment( |
163 const BytecodeGraphBuilder::Environment* other, | 164 const BytecodeGraphBuilder::Environment* other) |
164 LivenessAnalyzerBlock* liveness_block) | |
165 : builder_(other->builder_), | 165 : builder_(other->builder_), |
166 register_count_(other->register_count_), | 166 register_count_(other->register_count_), |
167 parameter_count_(other->parameter_count_), | 167 parameter_count_(other->parameter_count_), |
168 liveness_block_(liveness_block), | |
169 context_(other->context_), | 168 context_(other->context_), |
170 control_dependency_(other->control_dependency_), | 169 control_dependency_(other->control_dependency_), |
171 effect_dependency_(other->effect_dependency_), | 170 effect_dependency_(other->effect_dependency_), |
172 values_(other->zone()), | 171 values_(other->zone()), |
173 parameters_state_values_(nullptr), | 172 parameters_state_values_(nullptr), |
174 registers_state_values_(nullptr), | 173 registers_state_values_(nullptr), |
175 accumulator_state_values_(nullptr), | 174 accumulator_state_values_(nullptr), |
176 register_base_(other->register_base_), | 175 register_base_(other->register_base_), |
177 accumulator_base_(other->accumulator_base_) { | 176 accumulator_base_(other->accumulator_base_), |
| 177 // Environments can share their working area. |
| 178 state_value_working_area_(other->state_value_working_area_) { |
178 values_ = other->values_; | 179 values_ = other->values_; |
179 } | 180 } |
180 | 181 |
181 | 182 |
182 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( | 183 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( |
183 interpreter::Register the_register) const { | 184 interpreter::Register the_register) const { |
184 if (the_register.is_parameter()) { | 185 if (the_register.is_parameter()) { |
185 return the_register.ToParameterIndex(parameter_count()); | 186 return the_register.ToParameterIndex(parameter_count()); |
186 } else { | 187 } else { |
187 return the_register.index() + register_base(); | 188 return the_register.index() + register_base(); |
188 } | 189 } |
189 } | 190 } |
190 | 191 |
191 bool BytecodeGraphBuilder::Environment::IsLivenessBlockConsistent() const { | |
192 return !builder_->IsLivenessAnalysisEnabled() == | |
193 (liveness_block() == nullptr); | |
194 } | |
195 | |
196 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { | 192 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { |
197 DCHECK(IsLivenessBlockConsistent()); | |
198 if (liveness_block() != nullptr) { | |
199 liveness_block()->LookupAccumulator(); | |
200 } | |
201 return values()->at(accumulator_base_); | 193 return values()->at(accumulator_base_); |
202 } | 194 } |
203 | 195 |
204 | 196 |
205 Node* BytecodeGraphBuilder::Environment::LookupRegister( | 197 Node* BytecodeGraphBuilder::Environment::LookupRegister( |
206 interpreter::Register the_register) const { | 198 interpreter::Register the_register) const { |
207 if (the_register.is_current_context()) { | 199 if (the_register.is_current_context()) { |
208 return Context(); | 200 return Context(); |
209 } else if (the_register.is_function_closure()) { | 201 } else if (the_register.is_function_closure()) { |
210 return builder()->GetFunctionClosure(); | 202 return builder()->GetFunctionClosure(); |
211 } else if (the_register.is_new_target()) { | 203 } else if (the_register.is_new_target()) { |
212 return builder()->GetNewTarget(); | 204 return builder()->GetNewTarget(); |
213 } else { | 205 } else { |
214 int values_index = RegisterToValuesIndex(the_register); | 206 int values_index = RegisterToValuesIndex(the_register); |
215 if (liveness_block() != nullptr && !the_register.is_parameter()) { | |
216 DCHECK(IsLivenessBlockConsistent()); | |
217 liveness_block()->Lookup(the_register.index()); | |
218 } | |
219 return values()->at(values_index); | 207 return values()->at(values_index); |
220 } | 208 } |
221 } | 209 } |
222 | 210 |
223 void BytecodeGraphBuilder::Environment::MarkAllRegistersLive() { | |
224 DCHECK(IsLivenessBlockConsistent()); | |
225 if (liveness_block() != nullptr) { | |
226 for (int i = 0; i < register_count(); ++i) { | |
227 liveness_block()->Lookup(i); | |
228 } | |
229 } | |
230 } | |
231 | |
232 void BytecodeGraphBuilder::Environment::BindAccumulator( | 211 void BytecodeGraphBuilder::Environment::BindAccumulator( |
233 Node* node, FrameStateAttachmentMode mode) { | 212 Node* node, FrameStateAttachmentMode mode) { |
234 if (mode == FrameStateAttachmentMode::kAttachFrameState) { | 213 if (mode == FrameStateAttachmentMode::kAttachFrameState) { |
235 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); | 214 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); |
236 } | 215 } |
237 DCHECK(IsLivenessBlockConsistent()); | |
238 if (liveness_block() != nullptr) { | |
239 liveness_block()->BindAccumulator(); | |
240 } | |
241 values()->at(accumulator_base_) = node; | 216 values()->at(accumulator_base_) = node; |
242 } | 217 } |
243 | 218 |
244 void BytecodeGraphBuilder::Environment::BindRegister( | 219 void BytecodeGraphBuilder::Environment::BindRegister( |
245 interpreter::Register the_register, Node* node, | 220 interpreter::Register the_register, Node* node, |
246 FrameStateAttachmentMode mode) { | 221 FrameStateAttachmentMode mode) { |
247 int values_index = RegisterToValuesIndex(the_register); | 222 int values_index = RegisterToValuesIndex(the_register); |
248 if (mode == FrameStateAttachmentMode::kAttachFrameState) { | 223 if (mode == FrameStateAttachmentMode::kAttachFrameState) { |
249 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( | 224 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( |
250 accumulator_base_ - values_index)); | 225 accumulator_base_ - values_index)); |
251 } | 226 } |
252 values()->at(values_index) = node; | 227 values()->at(values_index) = node; |
253 if (liveness_block() != nullptr && !the_register.is_parameter()) { | |
254 DCHECK(IsLivenessBlockConsistent()); | |
255 liveness_block()->Bind(the_register.index()); | |
256 } | |
257 } | 228 } |
258 | 229 |
259 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( | 230 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( |
260 interpreter::Register first_reg, Node* node, | 231 interpreter::Register first_reg, Node* node, |
261 FrameStateAttachmentMode mode) { | 232 FrameStateAttachmentMode mode) { |
262 int values_index = RegisterToValuesIndex(first_reg); | 233 int values_index = RegisterToValuesIndex(first_reg); |
263 if (mode == FrameStateAttachmentMode::kAttachFrameState) { | 234 if (mode == FrameStateAttachmentMode::kAttachFrameState) { |
264 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( | 235 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( |
265 accumulator_base_ - values_index)); | 236 accumulator_base_ - values_index)); |
266 } | 237 } |
267 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { | 238 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { |
268 values()->at(values_index + i) = | 239 values()->at(values_index + i) = |
269 builder()->NewNode(common()->Projection(i), node); | 240 builder()->NewNode(common()->Projection(i), node); |
270 } | 241 } |
271 } | 242 } |
272 | 243 |
273 void BytecodeGraphBuilder::Environment::RecordAfterState( | 244 void BytecodeGraphBuilder::Environment::RecordAfterState( |
274 Node* node, FrameStateAttachmentMode mode) { | 245 Node* node, FrameStateAttachmentMode mode) { |
275 if (mode == FrameStateAttachmentMode::kAttachFrameState) { | 246 if (mode == FrameStateAttachmentMode::kAttachFrameState) { |
276 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); | 247 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); |
277 } | 248 } |
278 } | 249 } |
279 | 250 |
280 | 251 |
281 BytecodeGraphBuilder::Environment* | 252 BytecodeGraphBuilder::Environment* |
282 BytecodeGraphBuilder::Environment::CopyForLoop() { | 253 BytecodeGraphBuilder::Environment::CopyForLoop() { |
283 PrepareForLoop(); | 254 PrepareForLoop(); |
284 if (liveness_block() != nullptr) { | 255 return new (zone()) Environment(this); |
285 // Finish the current block before copying. | |
286 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); | |
287 } | |
288 return new (zone()) Environment(this, liveness_block()); | |
289 } | 256 } |
290 | 257 |
291 BytecodeGraphBuilder::Environment* | 258 BytecodeGraphBuilder::Environment* |
292 BytecodeGraphBuilder::Environment::CopyForOsrEntry() { | 259 BytecodeGraphBuilder::Environment::CopyForOsrEntry() { |
293 return new (zone()) | 260 return new (zone()) Environment(this); |
294 Environment(this, builder_->liveness_analyzer()->NewBlock()); | |
295 } | 261 } |
296 | 262 |
297 BytecodeGraphBuilder::Environment* | 263 BytecodeGraphBuilder::Environment* |
298 BytecodeGraphBuilder::Environment::CopyForConditional() { | 264 BytecodeGraphBuilder::Environment::CopyForConditional() { |
299 LivenessAnalyzerBlock* copy_liveness_block = nullptr; | 265 return new (zone()) Environment(this); |
300 if (liveness_block() != nullptr) { | |
301 copy_liveness_block = | |
302 builder_->liveness_analyzer()->NewBlock(liveness_block()); | |
303 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block()); | |
304 } | |
305 return new (zone()) Environment(this, copy_liveness_block); | |
306 } | 266 } |
307 | 267 |
308 | 268 |
309 void BytecodeGraphBuilder::Environment::Merge( | 269 void BytecodeGraphBuilder::Environment::Merge( |
310 BytecodeGraphBuilder::Environment* other) { | 270 BytecodeGraphBuilder::Environment* other) { |
311 if (builder_->is_liveness_analysis_enabled_) { | |
312 if (GetControlDependency()->opcode() != IrOpcode::kLoop) { | |
313 liveness_block_ = | |
314 builder()->liveness_analyzer()->NewBlock(liveness_block()); | |
315 } | |
316 liveness_block()->AddPredecessor(other->liveness_block()); | |
317 } | |
318 | |
319 // Create a merge of the control dependencies of both environments and update | 271 // Create a merge of the control dependencies of both environments and update |
320 // the current environment's control dependency accordingly. | 272 // the current environment's control dependency accordingly. |
321 Node* control = builder()->MergeControl(GetControlDependency(), | 273 Node* control = builder()->MergeControl(GetControlDependency(), |
322 other->GetControlDependency()); | 274 other->GetControlDependency()); |
323 UpdateControlDependency(control); | 275 UpdateControlDependency(control); |
324 | 276 |
325 // Create a merge of the effect dependencies of both environments and update | 277 // Create a merge of the effect dependencies of both environments and update |
326 // the current environment's effect dependency accordingly. | 278 // the current environment's effect dependency accordingly. |
327 Node* effect = builder()->MergeEffect(GetEffectDependency(), | 279 Node* effect = builder()->MergeEffect(GetEffectDependency(), |
328 other->GetEffectDependency(), control); | 280 other->GetEffectDependency(), control); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 int size = static_cast<int>(values()->size()); | 328 int size = static_cast<int>(values()->size()); |
377 for (int i = 0; i < size; i++) { | 329 for (int i = 0; i < size; i++) { |
378 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. | 330 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. |
379 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; | 331 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; |
380 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; | 332 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; |
381 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); | 333 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); |
382 } | 334 } |
383 | 335 |
384 BailoutId loop_id(builder_->bytecode_iterator().current_offset()); | 336 BailoutId loop_id(builder_->bytecode_iterator().current_offset()); |
385 Node* frame_state = | 337 Node* frame_state = |
386 Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false); | 338 Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false, nullptr); |
387 Node* checkpoint = | 339 Node* checkpoint = |
388 graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry); | 340 graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry); |
389 UpdateEffectDependency(checkpoint); | 341 UpdateEffectDependency(checkpoint); |
390 | 342 |
391 // Create the OSR guard nodes. | 343 // Create the OSR guard nodes. |
392 const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized); | 344 const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized); |
393 Node* effect = checkpoint; | 345 Node* effect = checkpoint; |
394 for (int i = 0; i < size; i++) { | 346 for (int i = 0; i < size; i++) { |
395 values()->at(i) = effect = | 347 values()->at(i) = effect = |
396 graph()->NewNode(guard_op, values()->at(i), effect, entry); | 348 graph()->NewNode(guard_op, values()->at(i), effect, entry); |
397 } | 349 } |
398 Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry); | 350 Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry); |
399 SetContext(context); | 351 SetContext(context); |
400 UpdateEffectDependency(effect); | 352 UpdateEffectDependency(effect); |
401 } | 353 } |
402 | 354 |
403 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( | 355 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( |
404 Node** state_values, int offset, int count) { | 356 Node** state_values, Node** values, int count) { |
405 if (*state_values == nullptr) { | 357 if (*state_values == nullptr) { |
406 return true; | 358 return true; |
407 } | 359 } |
408 DCHECK_EQ((*state_values)->InputCount(), count); | 360 DCHECK_EQ((*state_values)->InputCount(), count); |
409 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); | |
410 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); | |
411 for (int i = 0; i < count; i++) { | 361 for (int i = 0; i < count; i++) { |
412 if ((*state_values)->InputAt(i) != env_values[i]) { | 362 if ((*state_values)->InputAt(i) != values[i]) { |
413 return true; | 363 return true; |
414 } | 364 } |
415 } | 365 } |
416 return false; | 366 return false; |
417 } | 367 } |
418 | 368 |
419 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { | 369 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { |
420 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); | 370 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); |
421 | 371 |
422 Node* control = GetControlDependency(); | 372 Node* control = GetControlDependency(); |
(...skipping 13 matching lines...) Expand all Loading... |
436 | 386 |
437 // Rename the environmnent values. | 387 // Rename the environmnent values. |
438 for (size_t i = 0; i < values_.size(); i++) { | 388 for (size_t i = 0; i < values_.size(); i++) { |
439 Node* rename = | 389 Node* rename = |
440 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); | 390 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); |
441 values_[i] = rename; | 391 values_[i] = rename; |
442 } | 392 } |
443 } | 393 } |
444 | 394 |
445 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, | 395 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
446 int offset, | 396 Node** values, |
447 int count) { | 397 int count) { |
448 if (StateValuesRequireUpdate(state_values, offset, count)) { | 398 if (StateValuesRequireUpdate(state_values, values, count)) { |
449 const Operator* op = common()->StateValues(count); | 399 const Operator* op = common()->StateValues(count); |
450 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); | 400 (*state_values) = graph()->NewNode(op, count, values); |
451 } | 401 } |
452 } | 402 } |
453 | 403 |
| 404 void BytecodeGraphBuilder::Environment::UpdateStateValuesWithCache( |
| 405 Node** state_values, Node** values, int count) { |
| 406 *state_values = builder_->state_values_cache_.GetNodeForValues( |
| 407 values, static_cast<size_t>(count)); |
| 408 } |
| 409 |
454 Node* BytecodeGraphBuilder::Environment::Checkpoint( | 410 Node* BytecodeGraphBuilder::Environment::Checkpoint( |
455 BailoutId bailout_id, OutputFrameStateCombine combine, | 411 BailoutId bailout_id, OutputFrameStateCombine combine, |
456 bool owner_has_exception) { | 412 bool owner_has_exception, const BitVector* liveness) { |
457 UpdateStateValues(¶meters_state_values_, 0, parameter_count()); | 413 UpdateStateValues(¶meters_state_values_, &values()->at(0), |
458 UpdateStateValues(®isters_state_values_, register_base(), | 414 parameter_count()); |
459 register_count()); | 415 |
460 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); | 416 if (liveness) { |
| 417 Node* optimized_out = builder()->jsgraph()->OptimizedOutConstant(); |
| 418 |
| 419 for (int i = 0; i < register_count(); ++i) { |
| 420 state_value_working_area_[i] = liveness->Contains(i) |
| 421 ? values()->at(register_base() + i) |
| 422 : optimized_out; |
| 423 } |
| 424 |
| 425 Node* accumulator_value = liveness->Contains(register_count()) |
| 426 ? values()->at(accumulator_base()) |
| 427 : optimized_out; |
| 428 |
| 429 UpdateStateValuesWithCache(®isters_state_values_, |
| 430 state_value_working_area_.data(), |
| 431 register_count()); |
| 432 |
| 433 UpdateStateValues(&accumulator_state_values_, &accumulator_value, 1); |
| 434 } else { |
| 435 UpdateStateValuesWithCache(®isters_state_values_, |
| 436 &values()->at(register_base()), |
| 437 register_count()); |
| 438 UpdateStateValues(&accumulator_state_values_, |
| 439 &values()->at(accumulator_base()), 1); |
| 440 } |
461 | 441 |
462 const Operator* op = common()->FrameState( | 442 const Operator* op = common()->FrameState( |
463 bailout_id, combine, builder()->frame_state_function_info()); | 443 bailout_id, combine, builder()->frame_state_function_info()); |
464 Node* result = graph()->NewNode( | 444 Node* result = graph()->NewNode( |
465 op, parameters_state_values_, registers_state_values_, | 445 op, parameters_state_values_, registers_state_values_, |
466 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), | 446 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), |
467 builder()->graph()->start()); | 447 builder()->graph()->start()); |
468 | 448 |
469 if (liveness_block() != nullptr) { | |
470 // If the owning node has an exception, register the checkpoint to the | |
471 // predecessor so that the checkpoint is used for both the normal and the | |
472 // exceptional paths. Yes, this is a terrible hack and we might want | |
473 // to use an explicit frame state for the exceptional path. | |
474 if (owner_has_exception) { | |
475 liveness_block()->GetPredecessor()->Checkpoint(result); | |
476 } else { | |
477 liveness_block()->Checkpoint(result); | |
478 } | |
479 } | |
480 | |
481 return result; | 449 return result; |
482 } | 450 } |
483 | 451 |
484 BytecodeGraphBuilder::BytecodeGraphBuilder( | 452 BytecodeGraphBuilder::BytecodeGraphBuilder( |
485 Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, | 453 Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, |
486 float invocation_frequency, SourcePositionTable* source_positions, | 454 float invocation_frequency, SourcePositionTable* source_positions, |
487 int inlining_id) | 455 int inlining_id) |
488 : local_zone_(local_zone), | 456 : local_zone_(local_zone), |
489 jsgraph_(jsgraph), | 457 jsgraph_(jsgraph), |
490 invocation_frequency_(invocation_frequency), | 458 invocation_frequency_(invocation_frequency), |
491 bytecode_array_(handle(info->shared_info()->bytecode_array())), | 459 bytecode_array_(handle(info->shared_info()->bytecode_array())), |
492 exception_handler_table_( | 460 exception_handler_table_( |
493 handle(HandlerTable::cast(bytecode_array()->handler_table()))), | 461 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
494 feedback_vector_(handle(info->closure()->feedback_vector())), | 462 feedback_vector_(handle(info->closure()->feedback_vector())), |
495 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 463 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
496 FrameStateType::kInterpretedFunction, | 464 FrameStateType::kInterpretedFunction, |
497 bytecode_array()->parameter_count(), | 465 bytecode_array()->parameter_count(), |
498 bytecode_array()->register_count(), info->shared_info())), | 466 bytecode_array()->register_count(), info->shared_info())), |
499 osr_ast_id_(info->osr_ast_id()), | 467 osr_ast_id_(info->osr_ast_id()), |
500 merge_environments_(local_zone), | 468 merge_environments_(local_zone), |
501 exception_handlers_(local_zone), | 469 exception_handlers_(local_zone), |
502 current_exception_handler_(0), | 470 current_exception_handler_(0), |
503 input_buffer_size_(0), | 471 input_buffer_size_(0), |
504 input_buffer_(nullptr), | 472 input_buffer_(nullptr), |
505 exit_controls_(local_zone), | 473 exit_controls_(local_zone), |
506 is_liveness_analysis_enabled_(FLAG_analyze_environment_liveness), | 474 is_liveness_analysis_enabled_(FLAG_analyze_environment_liveness), |
507 state_values_cache_(jsgraph), | 475 state_values_cache_(jsgraph), |
508 liveness_analyzer_( | |
509 static_cast<size_t>(bytecode_array()->register_count()), true, | |
510 local_zone), | |
511 source_positions_(source_positions), | 476 source_positions_(source_positions), |
512 start_position_(info->shared_info()->start_position(), inlining_id) { | 477 start_position_(info->shared_info()->start_position(), inlining_id) { |
513 // Bytecode graph builder assumes deoptimziation is enabled. | 478 // Bytecode graph builder assumes deoptimziation is enabled. |
514 DCHECK(info->is_deoptimization_enabled()); | 479 DCHECK(info->is_deoptimization_enabled()); |
515 } | 480 } |
516 | 481 |
517 Node* BytecodeGraphBuilder::GetNewTarget() { | 482 Node* BytecodeGraphBuilder::GetNewTarget() { |
518 if (!new_target_.is_set()) { | 483 if (!new_target_.is_set()) { |
519 int params = bytecode_array()->parameter_count(); | 484 int params = bytecode_array()->parameter_count(); |
520 int index = Linkage::GetJSCallNewTargetParamIndex(params); | 485 int index = Linkage::GetJSCallNewTargetParamIndex(params); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 | 546 |
582 VisitBytecodes(stack_check); | 547 VisitBytecodes(stack_check); |
583 | 548 |
584 // Finish the basic structure of the graph. | 549 // Finish the basic structure of the graph. |
585 DCHECK_NE(0u, exit_controls_.size()); | 550 DCHECK_NE(0u, exit_controls_.size()); |
586 int const input_count = static_cast<int>(exit_controls_.size()); | 551 int const input_count = static_cast<int>(exit_controls_.size()); |
587 Node** const inputs = &exit_controls_.front(); | 552 Node** const inputs = &exit_controls_.front(); |
588 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 553 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
589 graph()->SetEnd(end); | 554 graph()->SetEnd(end); |
590 | 555 |
591 ClearNonLiveSlotsInFrameStates(); | |
592 | |
593 return true; | 556 return true; |
594 } | 557 } |
595 | 558 |
596 void BytecodeGraphBuilder::PrepareEagerCheckpoint() { | 559 void BytecodeGraphBuilder::PrepareEagerCheckpoint() { |
597 if (environment()->GetEffectDependency()->opcode() != IrOpcode::kCheckpoint) { | 560 if (environment()->GetEffectDependency()->opcode() != IrOpcode::kCheckpoint) { |
598 // Create an explicit checkpoint node for before the operation. This only | 561 // Create an explicit checkpoint node for before the operation. This only |
599 // needs to happen if we aren't effect-dominated by a {Checkpoint} already. | 562 // needs to happen if we aren't effect-dominated by a {Checkpoint} already. |
600 Node* node = NewNode(common()->Checkpoint()); | 563 Node* node = NewNode(common()->Checkpoint()); |
601 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 564 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
602 DCHECK_EQ(IrOpcode::kDead, | 565 DCHECK_EQ(IrOpcode::kDead, |
603 NodeProperties::GetFrameStateInput(node)->opcode()); | 566 NodeProperties::GetFrameStateInput(node)->opcode()); |
604 BailoutId bailout_id(bytecode_iterator().current_offset()); | 567 BailoutId bailout_id(bytecode_iterator().current_offset()); |
| 568 |
| 569 const BitVector* liveness_before = bytecode_analysis()->GetInLivenessFor( |
| 570 bytecode_iterator().current_offset()); |
| 571 |
605 Node* frame_state_before = environment()->Checkpoint( | 572 Node* frame_state_before = environment()->Checkpoint( |
606 bailout_id, OutputFrameStateCombine::Ignore(), false); | 573 bailout_id, OutputFrameStateCombine::Ignore(), false, liveness_before); |
607 NodeProperties::ReplaceFrameStateInput(node, frame_state_before); | 574 NodeProperties::ReplaceFrameStateInput(node, frame_state_before); |
608 } | 575 } |
609 } | 576 } |
610 | 577 |
611 void BytecodeGraphBuilder::PrepareFrameState(Node* node, | 578 void BytecodeGraphBuilder::PrepareFrameState(Node* node, |
612 OutputFrameStateCombine combine) { | 579 OutputFrameStateCombine combine) { |
613 if (OperatorProperties::HasFrameStateInput(node->op())) { | 580 if (OperatorProperties::HasFrameStateInput(node->op())) { |
614 // Add the frame state for after the operation. The node in question has | 581 // Add the frame state for after the operation. The node in question has |
615 // already been created and had a {Dead} frame state input up until now. | 582 // already been created and had a {Dead} frame state input up until now. |
616 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 583 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
617 DCHECK_EQ(IrOpcode::kDead, | 584 DCHECK_EQ(IrOpcode::kDead, |
618 NodeProperties::GetFrameStateInput(node)->opcode()); | 585 NodeProperties::GetFrameStateInput(node)->opcode()); |
619 BailoutId bailout_id(bytecode_iterator().current_offset()); | 586 BailoutId bailout_id(bytecode_iterator().current_offset()); |
620 bool has_exception = NodeProperties::IsExceptionalCall(node); | 587 bool has_exception = NodeProperties::IsExceptionalCall(node); |
621 Node* frame_state_after = | 588 |
622 environment()->Checkpoint(bailout_id, combine, has_exception); | 589 const BitVector* liveness_after = bytecode_analysis()->GetOutLivenessFor( |
| 590 bytecode_iterator().current_offset()); |
| 591 |
| 592 Node* frame_state_after = environment()->Checkpoint( |
| 593 bailout_id, combine, has_exception, liveness_after); |
623 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); | 594 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); |
624 } | 595 } |
625 } | 596 } |
626 | 597 |
627 void BytecodeGraphBuilder::ClearNonLiveSlotsInFrameStates() { | |
628 if (!IsLivenessAnalysisEnabled()) { | |
629 return; | |
630 } | |
631 NonLiveFrameStateSlotReplacer replacer( | |
632 &state_values_cache_, jsgraph()->OptimizedOutConstant(), | |
633 liveness_analyzer()->local_count(), true, local_zone()); | |
634 liveness_analyzer()->Run(&replacer); | |
635 if (FLAG_trace_environment_liveness) { | |
636 OFStream os(stdout); | |
637 liveness_analyzer()->Print(os); | |
638 } | |
639 } | |
640 | |
641 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { | 598 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { |
642 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone()); | 599 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(), |
| 600 FLAG_analyze_environment_liveness); |
643 bytecode_analysis.Analyze(); | 601 bytecode_analysis.Analyze(); |
644 set_bytecode_analysis(&bytecode_analysis); | 602 set_bytecode_analysis(&bytecode_analysis); |
645 | 603 |
646 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 604 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
647 set_bytecode_iterator(&iterator); | 605 set_bytecode_iterator(&iterator); |
648 SourcePositionTableIterator source_position_iterator( | 606 SourcePositionTableIterator source_position_iterator( |
649 bytecode_array()->source_position_table()); | 607 bytecode_array()->source_position_table()); |
650 | 608 |
| 609 if (FLAG_trace_environment_liveness) { |
| 610 OFStream of(stdout); |
| 611 |
| 612 bytecode_analysis.PrintLivenessTo(of); |
| 613 } |
| 614 |
651 BuildOSRNormalEntryPoint(); | 615 BuildOSRNormalEntryPoint(); |
| 616 |
652 for (; !iterator.done(); iterator.Advance()) { | 617 for (; !iterator.done(); iterator.Advance()) { |
653 int current_offset = iterator.current_offset(); | 618 int current_offset = iterator.current_offset(); |
654 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); | 619 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); |
655 EnterAndExitExceptionHandlers(current_offset); | 620 EnterAndExitExceptionHandlers(current_offset); |
656 SwitchToMergeEnvironment(current_offset); | 621 SwitchToMergeEnvironment(current_offset); |
657 if (environment() != nullptr) { | 622 if (environment() != nullptr) { |
658 BuildLoopHeaderEnvironment(current_offset); | 623 BuildLoopHeaderEnvironment(current_offset); |
659 BuildOSRLoopEntryPoint(current_offset); | 624 BuildOSRLoopEntryPoint(current_offset); |
660 | 625 |
661 // Skip the first stack check if stack_check is false | 626 // Skip the first stack check if stack_check is false |
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 Node* control = | 1727 Node* control = |
1763 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); | 1728 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); |
1764 MergeControlToLeaveFunction(control); | 1729 MergeControlToLeaveFunction(control); |
1765 } | 1730 } |
1766 | 1731 |
1767 void BytecodeGraphBuilder::VisitDebugger() { | 1732 void BytecodeGraphBuilder::VisitDebugger() { |
1768 PrepareEagerCheckpoint(); | 1733 PrepareEagerCheckpoint(); |
1769 Node* call = | 1734 Node* call = |
1770 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); | 1735 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); |
1771 environment()->BindAccumulator(call, Environment::kAttachFrameState); | 1736 environment()->BindAccumulator(call, Environment::kAttachFrameState); |
1772 environment()->MarkAllRegistersLive(); | |
1773 } | 1737 } |
1774 | 1738 |
1775 // We cannot create a graph from the debugger copy of the bytecode array. | 1739 // We cannot create a graph from the debugger copy of the bytecode array. |
1776 #define DEBUG_BREAK(Name, ...) \ | 1740 #define DEBUG_BREAK(Name, ...) \ |
1777 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } | 1741 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } |
1778 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); | 1742 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); |
1779 #undef DEBUG_BREAK | 1743 #undef DEBUG_BREAK |
1780 | 1744 |
1781 void BytecodeGraphBuilder::BuildForInPrepare() { | 1745 void BytecodeGraphBuilder::BuildForInPrepare() { |
1782 PrepareEagerCheckpoint(); | 1746 PrepareEagerCheckpoint(); |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 it->source_position().ScriptOffset(), start_position_.InliningId())); | 2192 it->source_position().ScriptOffset(), start_position_.InliningId())); |
2229 it->Advance(); | 2193 it->Advance(); |
2230 } else { | 2194 } else { |
2231 DCHECK_GT(it->code_offset(), offset); | 2195 DCHECK_GT(it->code_offset(), offset); |
2232 } | 2196 } |
2233 } | 2197 } |
2234 | 2198 |
2235 } // namespace compiler | 2199 } // namespace compiler |
2236 } // namespace internal | 2200 } // namespace internal |
2237 } // namespace v8 | 2201 } // namespace v8 |
OLD | NEW |