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