Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(531)

Side by Side Diff: src/compiler/bytecode-graph-builder.cc

Issue 2523893003: Reland of [ignition/turbo] Perform liveness analysis on the bytecodes (Closed)
Patch Set: Export handler table for tests Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/bytecode-liveness-map.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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(&parameters_state_values_, 0, parameter_count()); 413 UpdateStateValues(&parameters_state_values_, &values()->at(0),
458 UpdateStateValues(&registers_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(&registers_state_values_,
430 state_value_working_area_.data(),
431 register_count());
432
433 UpdateStateValues(&accumulator_state_values_, &accumulator_value, 1);
434 } else {
435 UpdateStateValuesWithCache(&registers_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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/bytecode-liveness-map.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698