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

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: 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
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 NodeVector tmp_values_;
Jarin 2016/11/24 12:47:17 Nit: Could we give this a more descriptive name (c
Leszek Swirski 2016/11/25 17:31:27 Done.
112 }; 111 };
113 112
114 113
115 // Issues: 114 // Issues:
116 // - Scopes - intimately tied to AST. Need to eval what is needed. 115 // - Scopes - intimately tied to AST. Need to eval what is needed.
117 // - Need to resolve closure parameter treatment. 116 // - Need to resolve closure parameter treatment.
118 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, 117 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
119 int register_count, 118 int register_count,
120 int parameter_count, 119 int parameter_count,
121 Node* control_dependency, 120 Node* control_dependency,
122 Node* context) 121 Node* context)
123 : builder_(builder), 122 : builder_(builder),
124 register_count_(register_count), 123 register_count_(register_count),
125 parameter_count_(parameter_count), 124 parameter_count_(parameter_count),
126 liveness_block_(builder->is_liveness_analysis_enabled_
127 ? builder_->liveness_analyzer()->NewBlock()
128 : nullptr),
129 context_(context), 125 context_(context),
130 control_dependency_(control_dependency), 126 control_dependency_(control_dependency),
131 effect_dependency_(control_dependency), 127 effect_dependency_(control_dependency),
132 values_(builder->local_zone()), 128 values_(builder->local_zone()),
133 parameters_state_values_(nullptr), 129 parameters_state_values_(nullptr),
134 registers_state_values_(nullptr), 130 registers_state_values_(nullptr),
135 accumulator_state_values_(nullptr) { 131 accumulator_state_values_(nullptr),
132 tmp_values_(builder->local_zone()) {
136 // The layout of values_ is: 133 // The layout of values_ is:
137 // 134 //
138 // [receiver] [parameters] [registers] [accumulator] 135 // [receiver] [parameters] [registers] [accumulator]
139 // 136 //
140 // parameter[0] is the receiver (this), parameters 1..N are the 137 // parameter[0] is the receiver (this), parameters 1..N are the
141 // parameters supplied to the method (arg0..argN-1). The accumulator 138 // parameters supplied to the method (arg0..argN-1). The accumulator
142 // is stored separately. 139 // is stored separately.
143 140
144 // Parameters including the receiver 141 // Parameters including the receiver
145 for (int i = 0; i < parameter_count; i++) { 142 for (int i = 0; i < parameter_count; i++) {
146 const char* debug_name = (i == 0) ? "%this" : nullptr; 143 const char* debug_name = (i == 0) ? "%this" : nullptr;
147 const Operator* op = common()->Parameter(i, debug_name); 144 const Operator* op = common()->Parameter(i, debug_name);
148 Node* parameter = builder->graph()->NewNode(op, graph()->start()); 145 Node* parameter = builder->graph()->NewNode(op, graph()->start());
149 values()->push_back(parameter); 146 values()->push_back(parameter);
150 } 147 }
151 148
152 // Registers 149 // Registers
153 register_base_ = static_cast<int>(values()->size()); 150 register_base_ = static_cast<int>(values()->size());
154 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 151 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
155 values()->insert(values()->end(), register_count, undefined_constant); 152 values()->insert(values()->end(), register_count, undefined_constant);
156 153
157 // Accumulator 154 // Accumulator
158 accumulator_base_ = static_cast<int>(values()->size()); 155 accumulator_base_ = static_cast<int>(values()->size());
159 values()->push_back(undefined_constant); 156 values()->push_back(undefined_constant);
157
158 tmp_values_.resize(register_count_);
160 } 159 }
161 160
162 BytecodeGraphBuilder::Environment::Environment( 161 BytecodeGraphBuilder::Environment::Environment(
163 const BytecodeGraphBuilder::Environment* other, 162 const BytecodeGraphBuilder::Environment* other)
164 LivenessAnalyzerBlock* liveness_block)
165 : builder_(other->builder_), 163 : builder_(other->builder_),
166 register_count_(other->register_count_), 164 register_count_(other->register_count_),
167 parameter_count_(other->parameter_count_), 165 parameter_count_(other->parameter_count_),
168 liveness_block_(liveness_block),
169 context_(other->context_), 166 context_(other->context_),
170 control_dependency_(other->control_dependency_), 167 control_dependency_(other->control_dependency_),
171 effect_dependency_(other->effect_dependency_), 168 effect_dependency_(other->effect_dependency_),
172 values_(other->zone()), 169 values_(other->zone()),
173 parameters_state_values_(nullptr), 170 parameters_state_values_(nullptr),
174 registers_state_values_(nullptr), 171 registers_state_values_(nullptr),
175 accumulator_state_values_(nullptr), 172 accumulator_state_values_(nullptr),
176 register_base_(other->register_base_), 173 register_base_(other->register_base_),
177 accumulator_base_(other->accumulator_base_) { 174 accumulator_base_(other->accumulator_base_),
175 tmp_values_(other->zone()) {
178 values_ = other->values_; 176 values_ = other->values_;
177 tmp_values_.resize(register_count_);
179 } 178 }
180 179
181 180
182 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 181 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
183 interpreter::Register the_register) const { 182 interpreter::Register the_register) const {
184 if (the_register.is_parameter()) { 183 if (the_register.is_parameter()) {
185 return the_register.ToParameterIndex(parameter_count()); 184 return the_register.ToParameterIndex(parameter_count());
186 } else { 185 } else {
187 return the_register.index() + register_base(); 186 return the_register.index() + register_base();
188 } 187 }
189 } 188 }
190 189
191 bool BytecodeGraphBuilder::Environment::IsLivenessBlockConsistent() const {
192 return !builder_->IsLivenessAnalysisEnabled() ==
193 (liveness_block() == nullptr);
194 }
195
196 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 190 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
197 DCHECK(IsLivenessBlockConsistent());
198 if (liveness_block() != nullptr) {
199 liveness_block()->LookupAccumulator();
200 }
201 return values()->at(accumulator_base_); 191 return values()->at(accumulator_base_);
202 } 192 }
203 193
204 194
205 Node* BytecodeGraphBuilder::Environment::LookupRegister( 195 Node* BytecodeGraphBuilder::Environment::LookupRegister(
206 interpreter::Register the_register) const { 196 interpreter::Register the_register) const {
207 if (the_register.is_current_context()) { 197 if (the_register.is_current_context()) {
208 return Context(); 198 return Context();
209 } else if (the_register.is_function_closure()) { 199 } else if (the_register.is_function_closure()) {
210 return builder()->GetFunctionClosure(); 200 return builder()->GetFunctionClosure();
211 } else if (the_register.is_new_target()) { 201 } else if (the_register.is_new_target()) {
212 return builder()->GetNewTarget(); 202 return builder()->GetNewTarget();
213 } else { 203 } else {
214 int values_index = RegisterToValuesIndex(the_register); 204 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); 205 return values()->at(values_index);
220 } 206 }
221 } 207 }
222 208
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( 209 void BytecodeGraphBuilder::Environment::BindAccumulator(
233 Node* node, FrameStateAttachmentMode mode) { 210 Node* node, FrameStateAttachmentMode mode) {
234 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 211 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
235 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); 212 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0));
236 } 213 }
237 DCHECK(IsLivenessBlockConsistent());
238 if (liveness_block() != nullptr) {
239 liveness_block()->BindAccumulator();
240 }
241 values()->at(accumulator_base_) = node; 214 values()->at(accumulator_base_) = node;
242 } 215 }
243 216
244 void BytecodeGraphBuilder::Environment::BindRegister( 217 void BytecodeGraphBuilder::Environment::BindRegister(
245 interpreter::Register the_register, Node* node, 218 interpreter::Register the_register, Node* node,
246 FrameStateAttachmentMode mode) { 219 FrameStateAttachmentMode mode) {
247 int values_index = RegisterToValuesIndex(the_register); 220 int values_index = RegisterToValuesIndex(the_register);
248 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 221 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
249 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 222 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
250 accumulator_base_ - values_index)); 223 accumulator_base_ - values_index));
251 } 224 }
252 values()->at(values_index) = node; 225 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 } 226 }
258 227
259 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( 228 void BytecodeGraphBuilder::Environment::BindRegistersToProjections(
260 interpreter::Register first_reg, Node* node, 229 interpreter::Register first_reg, Node* node,
261 FrameStateAttachmentMode mode) { 230 FrameStateAttachmentMode mode) {
262 int values_index = RegisterToValuesIndex(first_reg); 231 int values_index = RegisterToValuesIndex(first_reg);
263 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 232 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
264 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 233 builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(
265 accumulator_base_ - values_index)); 234 accumulator_base_ - values_index));
266 } 235 }
267 for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 236 for (int i = 0; i < node->op()->ValueOutputCount(); i++) {
268 values()->at(values_index + i) = 237 values()->at(values_index + i) =
269 builder()->NewNode(common()->Projection(i), node); 238 builder()->NewNode(common()->Projection(i), node);
270 } 239 }
271 } 240 }
272 241
273 void BytecodeGraphBuilder::Environment::RecordAfterState( 242 void BytecodeGraphBuilder::Environment::RecordAfterState(
274 Node* node, FrameStateAttachmentMode mode) { 243 Node* node, FrameStateAttachmentMode mode) {
275 if (mode == FrameStateAttachmentMode::kAttachFrameState) { 244 if (mode == FrameStateAttachmentMode::kAttachFrameState) {
276 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); 245 builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore());
277 } 246 }
278 } 247 }
279 248
280 249
281 BytecodeGraphBuilder::Environment* 250 BytecodeGraphBuilder::Environment*
282 BytecodeGraphBuilder::Environment::CopyForLoop() { 251 BytecodeGraphBuilder::Environment::CopyForLoop() {
283 PrepareForLoop(); 252 PrepareForLoop();
284 if (liveness_block() != nullptr) { 253 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 } 254 }
290 255
291 BytecodeGraphBuilder::Environment* 256 BytecodeGraphBuilder::Environment*
292 BytecodeGraphBuilder::Environment::CopyForOsrEntry() { 257 BytecodeGraphBuilder::Environment::CopyForOsrEntry() {
293 return new (zone()) 258 return new (zone()) Environment(this);
294 Environment(this, builder_->liveness_analyzer()->NewBlock());
295 } 259 }
296 260
297 BytecodeGraphBuilder::Environment* 261 BytecodeGraphBuilder::Environment*
298 BytecodeGraphBuilder::Environment::CopyForConditional() { 262 BytecodeGraphBuilder::Environment::CopyForConditional() {
299 LivenessAnalyzerBlock* copy_liveness_block = nullptr; 263 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 } 264 }
307 265
308 266
309 void BytecodeGraphBuilder::Environment::Merge( 267 void BytecodeGraphBuilder::Environment::Merge(
310 BytecodeGraphBuilder::Environment* other) { 268 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 269 // Create a merge of the control dependencies of both environments and update
320 // the current environment's control dependency accordingly. 270 // the current environment's control dependency accordingly.
321 Node* control = builder()->MergeControl(GetControlDependency(), 271 Node* control = builder()->MergeControl(GetControlDependency(),
322 other->GetControlDependency()); 272 other->GetControlDependency());
323 UpdateControlDependency(control); 273 UpdateControlDependency(control);
324 274
325 // Create a merge of the effect dependencies of both environments and update 275 // Create a merge of the effect dependencies of both environments and update
326 // the current environment's effect dependency accordingly. 276 // the current environment's effect dependency accordingly.
327 Node* effect = builder()->MergeEffect(GetEffectDependency(), 277 Node* effect = builder()->MergeEffect(GetEffectDependency(),
328 other->GetEffectDependency(), control); 278 other->GetEffectDependency(), control);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 int size = static_cast<int>(values()->size()); 326 int size = static_cast<int>(values()->size());
377 for (int i = 0; i < size; i++) { 327 for (int i = 0; i < size; i++) {
378 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. 328 int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly.
379 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; 329 if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
380 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; 330 if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
381 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); 331 values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry);
382 } 332 }
383 333
384 BailoutId loop_id(builder_->bytecode_iterator().current_offset()); 334 BailoutId loop_id(builder_->bytecode_iterator().current_offset());
385 Node* frame_state = 335 Node* frame_state =
386 Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false); 336 Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false, nullptr);
387 Node* checkpoint = 337 Node* checkpoint =
388 graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry); 338 graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry);
389 UpdateEffectDependency(checkpoint); 339 UpdateEffectDependency(checkpoint);
390 340
391 // Create the OSR guard nodes. 341 // Create the OSR guard nodes.
392 const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized); 342 const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized);
393 Node* effect = checkpoint; 343 Node* effect = checkpoint;
394 for (int i = 0; i < size; i++) { 344 for (int i = 0; i < size; i++) {
395 values()->at(i) = effect = 345 values()->at(i) = effect =
396 graph()->NewNode(guard_op, values()->at(i), effect, entry); 346 graph()->NewNode(guard_op, values()->at(i), effect, entry);
397 } 347 }
398 Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry); 348 Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry);
399 SetContext(context); 349 SetContext(context);
400 UpdateEffectDependency(effect); 350 UpdateEffectDependency(effect);
401 } 351 }
402 352
403 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 353 bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
404 Node** state_values, int offset, int count) { 354 Node** state_values, Node** values, int count) {
405 if (*state_values == nullptr) { 355 if (*state_values == nullptr) {
406 return true; 356 return true;
407 } 357 }
408 DCHECK_EQ((*state_values)->InputCount(), count); 358 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++) { 359 for (int i = 0; i < count; i++) {
412 if ((*state_values)->InputAt(i) != env_values[i]) { 360 if ((*state_values)->InputAt(i) != values[i]) {
413 return true; 361 return true;
414 } 362 }
415 } 363 }
416 return false; 364 return false;
417 } 365 }
418 366
419 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { 367 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) {
420 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); 368 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
421 369
422 Node* control = GetControlDependency(); 370 Node* control = GetControlDependency();
(...skipping 13 matching lines...) Expand all
436 384
437 // Rename the environmnent values. 385 // Rename the environmnent values.
438 for (size_t i = 0; i < values_.size(); i++) { 386 for (size_t i = 0; i < values_.size(); i++) {
439 Node* rename = 387 Node* rename =
440 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); 388 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
441 values_[i] = rename; 389 values_[i] = rename;
442 } 390 }
443 } 391 }
444 392
445 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 393 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
446 int offset, 394 Node** values,
447 int count) { 395 int count) {
448 if (StateValuesRequireUpdate(state_values, offset, count)) { 396 if (StateValuesRequireUpdate(state_values, values, count)) {
449 const Operator* op = common()->StateValues(count); 397 const Operator* op = common()->StateValues(count);
450 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); 398 (*state_values) = graph()->NewNode(op, count, values);
451 } 399 }
452 } 400 }
453 401
402 void BytecodeGraphBuilder::Environment::UpdateStateValuesWithCache(
403 Node** state_values, Node** values, int count) {
404 *state_values = builder_->state_values_cache_.GetNodeForValues(
405 values, static_cast<size_t>(count));
406 }
407
454 Node* BytecodeGraphBuilder::Environment::Checkpoint( 408 Node* BytecodeGraphBuilder::Environment::Checkpoint(
455 BailoutId bailout_id, OutputFrameStateCombine combine, 409 BailoutId bailout_id, OutputFrameStateCombine combine,
456 bool owner_has_exception) { 410 bool owner_has_exception, const BitVector* liveness) {
457 UpdateStateValues(&parameters_state_values_, 0, parameter_count()); 411 UpdateStateValues(&parameters_state_values_, &values()->at(0),
458 UpdateStateValues(&registers_state_values_, register_base(), 412 parameter_count());
459 register_count()); 413
460 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); 414 if (liveness) {
415 Node* optimized_out = builder()->jsgraph()->OptimizedOutConstant();
416
417 for (int i = 0; i < register_count(); ++i) {
418 tmp_values_[i] = liveness->Contains(i) ? values()->at(register_base() + i)
419 : optimized_out;
420 }
421
422 Node* accumulator_value = liveness->Contains(register_count())
423 ? values()->at(accumulator_base())
424 : optimized_out;
425
426 UpdateStateValuesWithCache(&registers_state_values_, tmp_values_.data(),
427 register_count());
428
429 UpdateStateValues(&accumulator_state_values_, &accumulator_value, 1);
430 } else {
431 UpdateStateValuesWithCache(&registers_state_values_,
432 &values()->at(register_base()),
433 register_count());
434 UpdateStateValues(&accumulator_state_values_,
435 &values()->at(accumulator_base()), 1);
436 }
437
438 // PrintF("liveness: ");
439 // for (int i = 0; i < liveness->length(); ++i) {
440 // if (liveness && !liveness->Contains(i)) {
441 // PrintF(".");
442 // } else {
443 // PrintF("L");
444 // }
445 // }
446 // PrintF("\n");
447
448 // PrintF("stv live: ");
449 // for (const auto& node : StateValuesAccess(registers_state_values_)) {
450 // if (node.node == builder()->jsgraph()->OptimizedOutConstant()) {
451 // PrintF(".");
452 // } else {
453 // PrintF("L");
454 // }
455 // }
456 // for (const auto& node : StateValuesAccess(accumulator_state_values_)) {
457 // if (node.node == builder()->jsgraph()->OptimizedOutConstant()) {
458 // PrintF(".");
459 // } else {
460 // PrintF("L");
461 // }
462 // }
463 // PrintF("\n");
461 464
462 const Operator* op = common()->FrameState( 465 const Operator* op = common()->FrameState(
463 bailout_id, combine, builder()->frame_state_function_info()); 466 bailout_id, combine, builder()->frame_state_function_info());
464 Node* result = graph()->NewNode( 467 Node* result = graph()->NewNode(
465 op, parameters_state_values_, registers_state_values_, 468 op, parameters_state_values_, registers_state_values_,
466 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), 469 accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
467 builder()->graph()->start()); 470 builder()->graph()->start());
468 471
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; 472 return result;
482 } 473 }
483 474
484 BytecodeGraphBuilder::BytecodeGraphBuilder( 475 BytecodeGraphBuilder::BytecodeGraphBuilder(
485 Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph, 476 Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
486 float invocation_frequency, SourcePositionTable* source_positions, 477 float invocation_frequency, SourcePositionTable* source_positions,
487 int inlining_id) 478 int inlining_id)
488 : local_zone_(local_zone), 479 : local_zone_(local_zone),
489 jsgraph_(jsgraph), 480 jsgraph_(jsgraph),
490 invocation_frequency_(invocation_frequency), 481 invocation_frequency_(invocation_frequency),
491 bytecode_array_(handle(info->shared_info()->bytecode_array())), 482 bytecode_array_(handle(info->shared_info()->bytecode_array())),
492 exception_handler_table_( 483 exception_handler_table_(
493 handle(HandlerTable::cast(bytecode_array()->handler_table()))), 484 handle(HandlerTable::cast(bytecode_array()->handler_table()))),
494 feedback_vector_(handle(info->closure()->feedback_vector())), 485 feedback_vector_(handle(info->closure()->feedback_vector())),
495 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 486 frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
496 FrameStateType::kInterpretedFunction, 487 FrameStateType::kInterpretedFunction,
497 bytecode_array()->parameter_count(), 488 bytecode_array()->parameter_count(),
498 bytecode_array()->register_count(), info->shared_info())), 489 bytecode_array()->register_count(), info->shared_info())),
499 osr_ast_id_(info->osr_ast_id()), 490 osr_ast_id_(info->osr_ast_id()),
500 merge_environments_(local_zone), 491 merge_environments_(local_zone),
501 exception_handlers_(local_zone), 492 exception_handlers_(local_zone),
502 current_exception_handler_(0), 493 current_exception_handler_(0),
503 input_buffer_size_(0), 494 input_buffer_size_(0),
504 input_buffer_(nullptr), 495 input_buffer_(nullptr),
505 exit_controls_(local_zone), 496 exit_controls_(local_zone),
506 is_liveness_analysis_enabled_(FLAG_analyze_environment_liveness && 497 is_liveness_analysis_enabled_(FLAG_analyze_environment_liveness &&
507 info->is_deoptimization_enabled()), 498 info->is_deoptimization_enabled()),
508 state_values_cache_(jsgraph), 499 state_values_cache_(jsgraph),
509 liveness_analyzer_(
510 static_cast<size_t>(bytecode_array()->register_count()), true,
511 local_zone),
512 source_positions_(source_positions), 500 source_positions_(source_positions),
513 start_position_(info->shared_info()->start_position(), inlining_id) {} 501 start_position_(info->shared_info()->start_position(), inlining_id) {}
514 502
515 Node* BytecodeGraphBuilder::GetNewTarget() { 503 Node* BytecodeGraphBuilder::GetNewTarget() {
516 if (!new_target_.is_set()) { 504 if (!new_target_.is_set()) {
517 int params = bytecode_array()->parameter_count(); 505 int params = bytecode_array()->parameter_count();
518 int index = Linkage::GetJSCallNewTargetParamIndex(params); 506 int index = Linkage::GetJSCallNewTargetParamIndex(params);
519 const Operator* op = common()->Parameter(index, "%new.target"); 507 const Operator* op = common()->Parameter(index, "%new.target");
520 Node* node = NewNode(op, graph()->start()); 508 Node* node = NewNode(op, graph()->start());
521 new_target_.set(node); 509 new_target_.set(node);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 567
580 VisitBytecodes(stack_check); 568 VisitBytecodes(stack_check);
581 569
582 // Finish the basic structure of the graph. 570 // Finish the basic structure of the graph.
583 DCHECK_NE(0u, exit_controls_.size()); 571 DCHECK_NE(0u, exit_controls_.size());
584 int const input_count = static_cast<int>(exit_controls_.size()); 572 int const input_count = static_cast<int>(exit_controls_.size());
585 Node** const inputs = &exit_controls_.front(); 573 Node** const inputs = &exit_controls_.front();
586 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 574 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
587 graph()->SetEnd(end); 575 graph()->SetEnd(end);
588 576
589 ClearNonLiveSlotsInFrameStates();
590
591 return true; 577 return true;
592 } 578 }
593 579
594 void BytecodeGraphBuilder::PrepareEagerCheckpoint() { 580 void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
595 if (environment()->GetEffectDependency()->opcode() != IrOpcode::kCheckpoint) { 581 if (environment()->GetEffectDependency()->opcode() != IrOpcode::kCheckpoint) {
596 // Create an explicit checkpoint node for before the operation. This only 582 // Create an explicit checkpoint node for before the operation. This only
597 // needs to happen if we aren't effect-dominated by a {Checkpoint} already. 583 // needs to happen if we aren't effect-dominated by a {Checkpoint} already.
598 Node* node = NewNode(common()->Checkpoint()); 584 Node* node = NewNode(common()->Checkpoint());
599 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 585 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
600 DCHECK_EQ(IrOpcode::kDead, 586 DCHECK_EQ(IrOpcode::kDead,
601 NodeProperties::GetFrameStateInput(node)->opcode()); 587 NodeProperties::GetFrameStateInput(node)->opcode());
602 BailoutId bailout_id(bytecode_iterator().current_offset()); 588 BailoutId bailout_id(bytecode_iterator().current_offset());
589
590 const BitVector* liveness_before = bytecode_analysis()->GetInLivenessFor(
591 bytecode_iterator().current_offset());
592
603 Node* frame_state_before = environment()->Checkpoint( 593 Node* frame_state_before = environment()->Checkpoint(
604 bailout_id, OutputFrameStateCombine::Ignore(), false); 594 bailout_id, OutputFrameStateCombine::Ignore(), false, liveness_before);
605 NodeProperties::ReplaceFrameStateInput(node, frame_state_before); 595 NodeProperties::ReplaceFrameStateInput(node, frame_state_before);
606 } 596 }
607 } 597 }
608 598
609 void BytecodeGraphBuilder::PrepareFrameState(Node* node, 599 void BytecodeGraphBuilder::PrepareFrameState(Node* node,
610 OutputFrameStateCombine combine) { 600 OutputFrameStateCombine combine) {
611 if (OperatorProperties::HasFrameStateInput(node->op())) { 601 if (OperatorProperties::HasFrameStateInput(node->op())) {
612 // Add the frame state for after the operation. The node in question has 602 // Add the frame state for after the operation. The node in question has
613 // already been created and had a {Dead} frame state input up until now. 603 // already been created and had a {Dead} frame state input up until now.
614 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 604 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
615 DCHECK_EQ(IrOpcode::kDead, 605 DCHECK_EQ(IrOpcode::kDead,
616 NodeProperties::GetFrameStateInput(node)->opcode()); 606 NodeProperties::GetFrameStateInput(node)->opcode());
617 BailoutId bailout_id(bytecode_iterator().current_offset()); 607 BailoutId bailout_id(bytecode_iterator().current_offset());
618 bool has_exception = NodeProperties::IsExceptionalCall(node); 608 bool has_exception = NodeProperties::IsExceptionalCall(node);
619 Node* frame_state_after = 609
620 environment()->Checkpoint(bailout_id, combine, has_exception); 610 const BitVector* liveness_after = bytecode_analysis()->GetOutLivenessFor(
611 bytecode_iterator().current_offset());
612
613 Node* frame_state_after = environment()->Checkpoint(
614 bailout_id, combine, has_exception, liveness_after);
621 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); 615 NodeProperties::ReplaceFrameStateInput(node, frame_state_after);
622 } 616 }
623 } 617 }
624 618
625 void BytecodeGraphBuilder::ClearNonLiveSlotsInFrameStates() {
626 if (!IsLivenessAnalysisEnabled()) {
627 return;
628 }
629 NonLiveFrameStateSlotReplacer replacer(
630 &state_values_cache_, jsgraph()->OptimizedOutConstant(),
631 liveness_analyzer()->local_count(), true, local_zone());
632 liveness_analyzer()->Run(&replacer);
633 if (FLAG_trace_environment_liveness) {
634 OFStream os(stdout);
635 liveness_analyzer()->Print(os);
636 }
637 }
638
639 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { 619 void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) {
640 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone()); 620 BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone());
641 bytecode_analysis.Analyze(); 621 bytecode_analysis.Analyze();
642 set_bytecode_analysis(&bytecode_analysis); 622 set_bytecode_analysis(&bytecode_analysis);
643 623
644 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 624 interpreter::BytecodeArrayIterator iterator(bytecode_array());
645 set_bytecode_iterator(&iterator); 625 set_bytecode_iterator(&iterator);
646 SourcePositionTableIterator source_position_iterator( 626 SourcePositionTableIterator source_position_iterator(
647 bytecode_array()->source_position_table()); 627 bytecode_array()->source_position_table());
648 628
629 if (FLAG_trace_environment_liveness) {
630 OFStream of(stdout);
631
632 interpreter::BytecodeArrayIterator trace_iterator(bytecode_array());
633
634 for (; !trace_iterator.done(); trace_iterator.Advance()) {
635 const BitVector* in_liveness =
636 bytecode_analysis.GetInLivenessFor(trace_iterator.current_offset());
637 for (int i = 0; i < in_liveness->length(); ++i) {
638 of << (in_liveness->Contains(i) ? "L" : ".");
639 }
640 of << " -> ";
641
642 const BitVector* out_liveness =
643 bytecode_analysis.GetOutLivenessFor(trace_iterator.current_offset());
644 for (int i = 0; i < out_liveness->length(); ++i) {
645 of << (out_liveness->Contains(i) ? "L" : ".");
646 }
647 of << " | " << trace_iterator.current_offset() << ": ";
648 trace_iterator.Output(of) << std::endl;
649 }
650 }
651
649 BuildOSRNormalEntryPoint(); 652 BuildOSRNormalEntryPoint();
653 OFStream of(stdout);
654
650 for (; !iterator.done(); iterator.Advance()) { 655 for (; !iterator.done(); iterator.Advance()) {
651 int current_offset = iterator.current_offset(); 656 int current_offset = iterator.current_offset();
652 UpdateCurrentSourcePosition(&source_position_iterator, current_offset); 657 UpdateCurrentSourcePosition(&source_position_iterator, current_offset);
653 EnterAndExitExceptionHandlers(current_offset); 658 EnterAndExitExceptionHandlers(current_offset);
654 SwitchToMergeEnvironment(current_offset); 659 SwitchToMergeEnvironment(current_offset);
655 if (environment() != nullptr) { 660 if (environment() != nullptr) {
656 BuildLoopHeaderEnvironment(current_offset); 661 BuildLoopHeaderEnvironment(current_offset);
657 BuildOSRLoopEntryPoint(current_offset); 662 BuildOSRLoopEntryPoint(current_offset);
658 663
659 // Skip the first stack check if stack_check is false 664 // Skip the first stack check if stack_check is false
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 Node* control = 1765 Node* control =
1761 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); 1766 NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
1762 MergeControlToLeaveFunction(control); 1767 MergeControlToLeaveFunction(control);
1763 } 1768 }
1764 1769
1765 void BytecodeGraphBuilder::VisitDebugger() { 1770 void BytecodeGraphBuilder::VisitDebugger() {
1766 PrepareEagerCheckpoint(); 1771 PrepareEagerCheckpoint();
1767 Node* call = 1772 Node* call =
1768 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); 1773 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1769 environment()->BindAccumulator(call, Environment::kAttachFrameState); 1774 environment()->BindAccumulator(call, Environment::kAttachFrameState);
1770 environment()->MarkAllRegistersLive();
1771 } 1775 }
1772 1776
1773 // We cannot create a graph from the debugger copy of the bytecode array. 1777 // We cannot create a graph from the debugger copy of the bytecode array.
1774 #define DEBUG_BREAK(Name, ...) \ 1778 #define DEBUG_BREAK(Name, ...) \
1775 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } 1779 void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); }
1776 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); 1780 DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
1777 #undef DEBUG_BREAK 1781 #undef DEBUG_BREAK
1778 1782
1779 void BytecodeGraphBuilder::BuildForInPrepare() { 1783 void BytecodeGraphBuilder::BuildForInPrepare() {
1780 PrepareEagerCheckpoint(); 1784 PrepareEagerCheckpoint();
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2226 it->source_position().ScriptOffset(), start_position_.InliningId())); 2230 it->source_position().ScriptOffset(), start_position_.InliningId()));
2227 it->Advance(); 2231 it->Advance();
2228 } else { 2232 } else {
2229 DCHECK_GT(it->code_offset(), offset); 2233 DCHECK_GT(it->code_offset(), offset);
2230 } 2234 }
2231 } 2235 }
2232 2236
2233 } // namespace compiler 2237 } // namespace compiler
2234 } // namespace internal 2238 } // namespace internal
2235 } // namespace v8 2239 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698