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

Side by Side Diff: src/compiler/structured-machine-assembler.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 months 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 | Annotate | Revision Log
« no previous file with comments | « src/compiler/structured-machine-assembler.h ('k') | src/compiler/typer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/pipeline.h"
6 #include "src/compiler/scheduler.h"
7 #include "src/compiler/structured-machine-assembler.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 Node* Variable::Get() const { return smasm_->GetVariable(offset_); }
14
15
16 void Variable::Set(Node* value) const { smasm_->SetVariable(offset_, value); }
17
18
19 StructuredMachineAssembler::StructuredMachineAssembler(
20 Graph* graph, MachineCallDescriptorBuilder* call_descriptor_builder,
21 MachineRepresentation word)
22 : GraphBuilder(graph),
23 schedule_(new (zone()) Schedule(zone())),
24 machine_(zone(), word),
25 common_(zone()),
26 call_descriptor_builder_(call_descriptor_builder),
27 parameters_(NULL),
28 current_environment_(new (zone())
29 Environment(zone(), schedule()->entry(), false)),
30 number_of_variables_(0) {
31 if (parameter_count() == 0) return;
32 parameters_ = zone()->NewArray<Node*>(parameter_count());
33 for (int i = 0; i < parameter_count(); ++i) {
34 parameters_[i] = NewNode(common()->Parameter(i));
35 }
36 }
37
38
39 Schedule* StructuredMachineAssembler::Export() {
40 // Compute the correct codegen order.
41 ASSERT(schedule_->rpo_order()->empty());
42 Scheduler scheduler(zone(), graph(), schedule_);
43 scheduler.ComputeSpecialRPO();
44 // Invalidate MachineAssembler.
45 Schedule* schedule = schedule_;
46 schedule_ = NULL;
47 return schedule;
48 }
49
50
51 Node* StructuredMachineAssembler::Parameter(int index) {
52 ASSERT(0 <= index && index < parameter_count());
53 return parameters_[index];
54 }
55
56
57 Node* StructuredMachineAssembler::MakeNode(Operator* op, int input_count,
58 Node** inputs) {
59 ASSERT(ScheduleValid());
60 ASSERT(current_environment_ != NULL);
61 Node* node = graph()->NewNode(op, input_count, inputs);
62 BasicBlock* block = NULL;
63 switch (op->opcode()) {
64 case IrOpcode::kParameter:
65 case IrOpcode::kInt32Constant:
66 case IrOpcode::kInt64Constant:
67 case IrOpcode::kFloat64Constant:
68 case IrOpcode::kExternalConstant:
69 case IrOpcode::kNumberConstant:
70 case IrOpcode::kHeapConstant:
71 // Parameters and constants must be in start.
72 block = schedule()->start();
73 break;
74 default:
75 // Verify all leaf nodes handled above.
76 ASSERT((op->OutputCount() == 0) == (op->opcode() == IrOpcode::kStore));
77 block = current_environment_->block_;
78 break;
79 }
80 if (block != NULL) {
81 schedule()->AddNode(block, node);
82 }
83 return node;
84 }
85
86
87 Variable StructuredMachineAssembler::NewVariable(Node* initial_value) {
88 CHECK(initial_value != NULL);
89 int offset = number_of_variables_++;
90 // Extend current environment to correct number of values.
91 NodeVector* variables = CurrentVars();
92 size_t to_add = number_of_variables_ - variables->size();
93 if (to_add != 0) {
94 variables->reserve(number_of_variables_);
95 variables->insert(variables->end(), to_add, NULL);
96 }
97 variables->at(offset) = initial_value;
98 return Variable(this, offset);
99 }
100
101
102 Node* StructuredMachineAssembler::GetVariable(int offset) {
103 ASSERT(ScheduleValid());
104 return VariableAt(current_environment_, offset);
105 }
106
107
108 void StructuredMachineAssembler::SetVariable(int offset, Node* value) {
109 ASSERT(ScheduleValid());
110 Node*& ref = VariableAt(current_environment_, offset);
111 ref = value;
112 }
113
114
115 Node*& StructuredMachineAssembler::VariableAt(Environment* environment,
116 int32_t offset) {
117 // Variable used out of scope.
118 CHECK(static_cast<size_t>(offset) < environment->variables_.size());
119 Node*& value = environment->variables_.at(offset);
120 CHECK(value != NULL); // Variable used out of scope.
121 return value;
122 }
123
124
125 void StructuredMachineAssembler::Return(Node* value) {
126 BasicBlock* block = current_environment_->block_;
127 if (block != NULL) {
128 schedule()->AddReturn(block, value);
129 }
130 CopyCurrentAsDead();
131 }
132
133
134 void StructuredMachineAssembler::CopyCurrentAsDead() {
135 ASSERT(current_environment_ != NULL);
136 bool is_dead = current_environment_->is_dead_;
137 current_environment_->is_dead_ = true;
138 Environment* next = Copy(current_environment_);
139 current_environment_->is_dead_ = is_dead;
140 current_environment_ = next;
141 }
142
143
144 StructuredMachineAssembler::Environment* StructuredMachineAssembler::Copy(
145 Environment* env, int truncate_at) {
146 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_);
147 if (!new_env->is_dead_) {
148 new_env->block_ = schedule()->NewBasicBlock();
149 }
150 new_env->variables_.reserve(truncate_at);
151 NodeVectorIter end = env->variables_.end();
152 ASSERT(truncate_at <= static_cast<int>(env->variables_.size()));
153 end -= static_cast<int>(env->variables_.size()) - truncate_at;
154 new_env->variables_.insert(new_env->variables_.begin(),
155 env->variables_.begin(), end);
156 return new_env;
157 }
158
159
160 StructuredMachineAssembler::Environment*
161 StructuredMachineAssembler::CopyForLoopHeader(Environment* env) {
162 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_);
163 if (!new_env->is_dead_) {
164 new_env->block_ = schedule()->NewBasicBlock();
165 }
166 new_env->variables_.reserve(env->variables_.size());
167 for (NodeVectorIter i = env->variables_.begin(); i != env->variables_.end();
168 ++i) {
169 Node* phi = NULL;
170 if (*i != NULL) {
171 phi = graph()->NewNode(common()->Phi(1), *i);
172 if (new_env->block_ != NULL) {
173 schedule()->AddNode(new_env->block_, phi);
174 }
175 }
176 new_env->variables_.push_back(phi);
177 }
178 return new_env;
179 }
180
181
182 void StructuredMachineAssembler::MergeBackEdgesToLoopHeader(
183 Environment* header, EnvironmentVector* environments) {
184 // Only merge as many variables are were declared before this loop.
185 size_t n = header->variables_.size();
186 // TODO(dcarney): invert loop order and extend phis once.
187 for (EnvironmentVector::iterator i = environments->begin();
188 i != environments->end(); ++i) {
189 Environment* from = *i;
190 if (from->is_dead_) continue;
191 AddGoto(from, header);
192 for (size_t i = 0; i < n; ++i) {
193 Node* phi = header->variables_[i];
194 if (phi == NULL) continue;
195 phi->set_op(common()->Phi(phi->InputCount() + 1));
196 phi->AppendInput(zone(), VariableAt(from, i));
197 }
198 }
199 }
200
201
202 void StructuredMachineAssembler::Merge(EnvironmentVector* environments,
203 int truncate_at) {
204 ASSERT(current_environment_ == NULL || current_environment_->is_dead_);
205 Environment* next = new (zone()) Environment(zone(), NULL, false);
206 current_environment_ = next;
207 size_t n_vars = number_of_variables_;
208 NodeVector& vars = next->variables_;
209 vars.reserve(n_vars);
210 Node** scratch = NULL;
211 size_t n_envs = environments->size();
212 Environment** live_environments = reinterpret_cast<Environment**>(
213 alloca(sizeof(environments->at(0)) * n_envs));
214 size_t n_live = 0;
215 for (size_t i = 0; i < n_envs; i++) {
216 if (environments->at(i)->is_dead_) continue;
217 live_environments[n_live++] = environments->at(i);
218 }
219 n_envs = n_live;
220 if (n_live == 0) next->is_dead_ = true;
221 if (!next->is_dead_) {
222 next->block_ = schedule()->NewBasicBlock();
223 }
224 for (size_t j = 0; j < n_vars; ++j) {
225 Node* resolved = NULL;
226 // Find first non equal variable.
227 size_t i = 0;
228 for (; i < n_envs; i++) {
229 ASSERT(live_environments[i]->variables_.size() <= n_vars);
230 Node* val = NULL;
231 if (j < static_cast<size_t>(truncate_at)) {
232 val = live_environments[i]->variables_.at(j);
233 // TODO(dcarney): record start position at time of split.
234 // all variables after this should not be NULL.
235 if (val != NULL) {
236 val = VariableAt(live_environments[i], j);
237 }
238 }
239 if (val == resolved) continue;
240 if (i != 0) break;
241 resolved = val;
242 }
243 // Have to generate a phi.
244 if (i < n_envs) {
245 // All values thus far uninitialized, variable used out of scope.
246 CHECK(resolved != NULL);
247 // Init scratch buffer.
248 if (scratch == NULL) {
249 scratch = static_cast<Node**>(alloca(n_envs * sizeof(resolved)));
250 }
251 for (size_t k = 0; k < i; k++) {
252 scratch[k] = resolved;
253 }
254 for (; i < n_envs; i++) {
255 scratch[i] = live_environments[i]->variables_[j];
256 }
257 resolved = graph()->NewNode(common()->Phi(n_envs), n_envs, scratch);
258 if (next->block_ != NULL) {
259 schedule()->AddNode(next->block_, resolved);
260 }
261 }
262 vars.push_back(resolved);
263 }
264 }
265
266
267 void StructuredMachineAssembler::AddGoto(Environment* from, Environment* to) {
268 if (to->is_dead_) {
269 ASSERT(from->is_dead_);
270 return;
271 }
272 ASSERT(!from->is_dead_);
273 schedule()->AddGoto(from->block_, to->block_);
274 }
275
276
277 // TODO(dcarney): add pass before rpo to schedule to compute these.
278 BasicBlock* StructuredMachineAssembler::TrampolineFor(BasicBlock* block) {
279 BasicBlock* trampoline = schedule()->NewBasicBlock();
280 schedule()->AddGoto(trampoline, block);
281 return trampoline;
282 }
283
284
285 void StructuredMachineAssembler::AddBranch(Environment* environment,
286 Node* condition,
287 Environment* true_val,
288 Environment* false_val) {
289 ASSERT(environment->is_dead_ == true_val->is_dead_);
290 ASSERT(environment->is_dead_ == false_val->is_dead_);
291 if (true_val->block_ == false_val->block_) {
292 if (environment->is_dead_) return;
293 AddGoto(environment, true_val);
294 return;
295 }
296 Node* branch = graph()->NewNode(common()->Branch(), condition);
297 if (environment->is_dead_) return;
298 BasicBlock* true_block = TrampolineFor(true_val->block_);
299 BasicBlock* false_block = TrampolineFor(false_val->block_);
300 schedule()->AddBranch(environment->block_, branch, true_block, false_block);
301 }
302
303
304 StructuredMachineAssembler::Environment::Environment(Zone* zone,
305 BasicBlock* block,
306 bool is_dead)
307 : block_(block),
308 variables_(NodeVector::allocator_type(zone)),
309 is_dead_(is_dead) {}
310
311
312 StructuredMachineAssembler::IfBuilder::IfBuilder(
313 StructuredMachineAssembler* smasm)
314 : smasm_(smasm),
315 if_clauses_(IfClauses::allocator_type(smasm_->zone())),
316 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) {
317 ASSERT(smasm_->current_environment_ != NULL);
318 PushNewIfClause();
319 ASSERT(!IsDone());
320 }
321
322
323 StructuredMachineAssembler::IfBuilder&
324 StructuredMachineAssembler::IfBuilder::If() {
325 ASSERT(smasm_->current_environment_ != NULL);
326 IfClause* clause = CurrentClause();
327 if (clause->then_environment_ != NULL || clause->else_environment_ != NULL) {
328 PushNewIfClause();
329 }
330 return *this;
331 }
332
333
334 StructuredMachineAssembler::IfBuilder&
335 StructuredMachineAssembler::IfBuilder::If(Node* condition) {
336 If();
337 IfClause* clause = CurrentClause();
338 // Store branch for future resolution.
339 UnresolvedBranch* next = new (smasm_->zone())
340 UnresolvedBranch(smasm_->current_environment_, condition, NULL);
341 if (clause->unresolved_list_tail_ != NULL) {
342 clause->unresolved_list_tail_->next_ = next;
343 }
344 clause->unresolved_list_tail_ = next;
345 // Push onto merge queues.
346 clause->pending_else_merges_.push_back(next);
347 clause->pending_then_merges_.push_back(next);
348 smasm_->current_environment_ = NULL;
349 return *this;
350 }
351
352
353 void StructuredMachineAssembler::IfBuilder::And() {
354 CurrentClause()->ResolvePendingMerges(smasm_, kCombineThen, kExpressionTerm);
355 }
356
357
358 void StructuredMachineAssembler::IfBuilder::Or() {
359 CurrentClause()->ResolvePendingMerges(smasm_, kCombineElse, kExpressionTerm);
360 }
361
362
363 void StructuredMachineAssembler::IfBuilder::Then() {
364 CurrentClause()->ResolvePendingMerges(smasm_, kCombineThen, kExpressionDone);
365 }
366
367
368 void StructuredMachineAssembler::IfBuilder::Else() {
369 AddCurrentToPending();
370 CurrentClause()->ResolvePendingMerges(smasm_, kCombineElse, kExpressionDone);
371 }
372
373
374 void StructuredMachineAssembler::IfBuilder::AddCurrentToPending() {
375 if (smasm_->current_environment_ != NULL &&
376 !smasm_->current_environment_->is_dead_) {
377 pending_exit_merges_.push_back(smasm_->current_environment_);
378 }
379 smasm_->current_environment_ = NULL;
380 }
381
382
383 void StructuredMachineAssembler::IfBuilder::PushNewIfClause() {
384 int curr_size =
385 static_cast<int>(smasm_->current_environment_->variables_.size());
386 IfClause* clause = new (smasm_->zone()) IfClause(smasm_->zone(), curr_size);
387 if_clauses_.push_back(clause);
388 }
389
390
391 StructuredMachineAssembler::IfBuilder::IfClause::IfClause(
392 Zone* zone, int initial_environment_size)
393 : unresolved_list_tail_(NULL),
394 initial_environment_size_(initial_environment_size),
395 expression_states_(ExpressionStates::allocator_type(zone)),
396 pending_then_merges_(PendingMergeStack::allocator_type(zone)),
397 pending_else_merges_(PendingMergeStack::allocator_type(zone)),
398 then_environment_(NULL),
399 else_environment_(NULL) {
400 PushNewExpressionState();
401 }
402
403
404 StructuredMachineAssembler::IfBuilder::PendingMergeStackRange
405 StructuredMachineAssembler::IfBuilder::IfClause::ComputeRelevantMerges(
406 CombineType combine_type) {
407 ASSERT(!expression_states_.empty());
408 PendingMergeStack* stack;
409 int start;
410 if (combine_type == kCombineThen) {
411 stack = &pending_then_merges_;
412 start = expression_states_.back().pending_then_size_;
413 } else {
414 ASSERT(combine_type == kCombineElse);
415 stack = &pending_else_merges_;
416 start = expression_states_.back().pending_else_size_;
417 }
418 PendingMergeStackRange data;
419 data.merge_stack_ = stack;
420 data.start_ = start;
421 data.size_ = static_cast<int>(stack->size()) - start;
422 return data;
423 }
424
425
426 void StructuredMachineAssembler::IfBuilder::IfClause::ResolvePendingMerges(
427 StructuredMachineAssembler* smasm, CombineType combine_type,
428 ResolutionType resolution_type) {
429 ASSERT(smasm->current_environment_ == NULL);
430 PendingMergeStackRange data = ComputeRelevantMerges(combine_type);
431 ASSERT_EQ(data.merge_stack_->back(), unresolved_list_tail_);
432 ASSERT(data.size_ > 0);
433 // TODO(dcarney): assert no new variables created during expression building.
434 int truncate_at = initial_environment_size_;
435 if (data.size_ == 1) {
436 // Just copy environment in common case.
437 smasm->current_environment_ =
438 smasm->Copy(unresolved_list_tail_->environment_, truncate_at);
439 } else {
440 EnvironmentVector environments(
441 EnvironmentVector::allocator_type(smasm->zone()));
442 environments.reserve(data.size_);
443 CopyEnvironments(data, &environments);
444 ASSERT(static_cast<int>(environments.size()) == data.size_);
445 smasm->Merge(&environments, truncate_at);
446 }
447 Environment* then_environment = then_environment_;
448 Environment* else_environment = NULL;
449 if (resolution_type == kExpressionDone) {
450 ASSERT(expression_states_.size() == 1);
451 // Set the current then_ or else_environment_ to the new merged environment.
452 if (combine_type == kCombineThen) {
453 ASSERT(then_environment_ == NULL && else_environment_ == NULL);
454 this->then_environment_ = smasm->current_environment_;
455 } else {
456 ASSERT(else_environment_ == NULL);
457 this->else_environment_ = smasm->current_environment_;
458 }
459 } else {
460 ASSERT(resolution_type == kExpressionTerm);
461 ASSERT(then_environment_ == NULL && else_environment_ == NULL);
462 }
463 if (combine_type == kCombineThen) {
464 then_environment = smasm->current_environment_;
465 } else {
466 ASSERT(combine_type == kCombineElse);
467 else_environment = smasm->current_environment_;
468 }
469 // Finalize branches and clear the pending stack.
470 FinalizeBranches(smasm, data, combine_type, then_environment,
471 else_environment);
472 }
473
474
475 void StructuredMachineAssembler::IfBuilder::IfClause::CopyEnvironments(
476 const PendingMergeStackRange& data, EnvironmentVector* environments) {
477 PendingMergeStack::iterator i = data.merge_stack_->begin();
478 PendingMergeStack::iterator end = data.merge_stack_->end();
479 for (i += data.start_; i != end; ++i) {
480 environments->push_back((*i)->environment_);
481 }
482 }
483
484
485 void StructuredMachineAssembler::IfBuilder::IfClause::PushNewExpressionState() {
486 ExpressionState next;
487 next.pending_then_size_ = static_cast<int>(pending_then_merges_.size());
488 next.pending_else_size_ = static_cast<int>(pending_else_merges_.size());
489 expression_states_.push_back(next);
490 }
491
492
493 void StructuredMachineAssembler::IfBuilder::IfClause::PopExpressionState() {
494 expression_states_.pop_back();
495 ASSERT(!expression_states_.empty());
496 }
497
498
499 void StructuredMachineAssembler::IfBuilder::IfClause::FinalizeBranches(
500 StructuredMachineAssembler* smasm, const PendingMergeStackRange& data,
501 CombineType combine_type, Environment* const then_environment,
502 Environment* const else_environment) {
503 ASSERT(unresolved_list_tail_ != NULL);
504 ASSERT(smasm->current_environment_ != NULL);
505 if (data.size_ == 0) return;
506 PendingMergeStack::iterator curr = data.merge_stack_->begin();
507 PendingMergeStack::iterator end = data.merge_stack_->end();
508 // Finalize everything but the head first,
509 // in the order the branches enter the merge block.
510 end -= 1;
511 Environment* true_val = then_environment;
512 Environment* false_val = else_environment;
513 Environment** next;
514 if (combine_type == kCombineThen) {
515 next = &false_val;
516 } else {
517 ASSERT(combine_type == kCombineElse);
518 next = &true_val;
519 }
520 for (curr += data.start_; curr != end; ++curr) {
521 UnresolvedBranch* branch = *curr;
522 *next = branch->next_->environment_;
523 smasm->AddBranch(branch->environment_, branch->condition_, true_val,
524 false_val);
525 }
526 ASSERT(curr + 1 == data.merge_stack_->end());
527 // Now finalize the tail if possible.
528 if (then_environment != NULL && else_environment != NULL) {
529 UnresolvedBranch* branch = *curr;
530 smasm->AddBranch(branch->environment_, branch->condition_, then_environment,
531 else_environment);
532 }
533 // Clear the merge stack.
534 PendingMergeStack::iterator begin = data.merge_stack_->begin();
535 begin += data.start_;
536 data.merge_stack_->erase(begin, data.merge_stack_->end());
537 ASSERT_EQ(static_cast<int>(data.merge_stack_->size()), data.start_);
538 }
539
540
541 void StructuredMachineAssembler::IfBuilder::End() {
542 ASSERT(!IsDone());
543 AddCurrentToPending();
544 size_t current_pending = pending_exit_merges_.size();
545 // All unresolved branch edges are now set to pending.
546 for (IfClauses::iterator i = if_clauses_.begin(); i != if_clauses_.end();
547 ++i) {
548 IfClause* clause = *i;
549 ASSERT(clause->expression_states_.size() == 1);
550 PendingMergeStackRange data;
551 // Copy then environments.
552 data = clause->ComputeRelevantMerges(kCombineThen);
553 clause->CopyEnvironments(data, &pending_exit_merges_);
554 Environment* head = NULL;
555 // Will resolve the head node in the else_merge
556 if (data.size_ > 0 && clause->then_environment_ == NULL &&
557 clause->else_environment_ == NULL) {
558 head = pending_exit_merges_.back();
559 pending_exit_merges_.pop_back();
560 }
561 // Copy else environments.
562 data = clause->ComputeRelevantMerges(kCombineElse);
563 clause->CopyEnvironments(data, &pending_exit_merges_);
564 if (head != NULL) {
565 // Must have data to merge, or else head will never get a branch.
566 ASSERT(data.size_ != 0);
567 pending_exit_merges_.push_back(head);
568 }
569 }
570 smasm_->Merge(&pending_exit_merges_,
571 if_clauses_[0]->initial_environment_size_);
572 // Anything initally pending jumps into the new environment.
573 for (size_t i = 0; i < current_pending; ++i) {
574 smasm_->AddGoto(pending_exit_merges_[i], smasm_->current_environment_);
575 }
576 // Resolve all branches.
577 for (IfClauses::iterator i = if_clauses_.begin(); i != if_clauses_.end();
578 ++i) {
579 IfClause* clause = *i;
580 // Must finalize all environments, so ensure they are set correctly.
581 Environment* then_environment = clause->then_environment_;
582 if (then_environment == NULL) {
583 then_environment = smasm_->current_environment_;
584 }
585 Environment* else_environment = clause->else_environment_;
586 PendingMergeStackRange data;
587 // Finalize then environments.
588 data = clause->ComputeRelevantMerges(kCombineThen);
589 clause->FinalizeBranches(smasm_, data, kCombineThen, then_environment,
590 else_environment);
591 // Finalize else environments.
592 // Now set the else environment so head is finalized for edge case above.
593 if (else_environment == NULL) {
594 else_environment = smasm_->current_environment_;
595 }
596 data = clause->ComputeRelevantMerges(kCombineElse);
597 clause->FinalizeBranches(smasm_, data, kCombineElse, then_environment,
598 else_environment);
599 }
600 // Future accesses to this builder should crash immediately.
601 pending_exit_merges_.clear();
602 if_clauses_.clear();
603 ASSERT(IsDone());
604 }
605
606
607 StructuredMachineAssembler::LoopBuilder::LoopBuilder(
608 StructuredMachineAssembler* smasm)
609 : smasm_(smasm),
610 header_environment_(NULL),
611 pending_header_merges_(EnvironmentVector::allocator_type(smasm_->zone())),
612 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) {
613 ASSERT(smasm_->current_environment_ != NULL);
614 // Create header environment.
615 header_environment_ = smasm_->CopyForLoopHeader(smasm_->current_environment_);
616 smasm_->AddGoto(smasm_->current_environment_, header_environment_);
617 // Create body environment.
618 Environment* body = smasm_->Copy(header_environment_);
619 smasm_->AddGoto(header_environment_, body);
620 smasm_->current_environment_ = body;
621 ASSERT(!IsDone());
622 }
623
624
625 void StructuredMachineAssembler::LoopBuilder::Continue() {
626 ASSERT(!IsDone());
627 pending_header_merges_.push_back(smasm_->current_environment_);
628 smasm_->CopyCurrentAsDead();
629 }
630
631
632 void StructuredMachineAssembler::LoopBuilder::Break() {
633 ASSERT(!IsDone());
634 pending_exit_merges_.push_back(smasm_->current_environment_);
635 smasm_->CopyCurrentAsDead();
636 }
637
638
639 void StructuredMachineAssembler::LoopBuilder::End() {
640 ASSERT(!IsDone());
641 if (smasm_->current_environment_ != NULL) {
642 Continue();
643 }
644 // Do loop header merges.
645 smasm_->MergeBackEdgesToLoopHeader(header_environment_,
646 &pending_header_merges_);
647 int initial_size = header_environment_->variables_.size();
648 // Do loop exit merges, truncating loop variables away.
649 smasm_->Merge(&pending_exit_merges_, initial_size);
650 for (EnvironmentVector::iterator i = pending_exit_merges_.begin();
651 i != pending_exit_merges_.end(); ++i) {
652 smasm_->AddGoto(*i, smasm_->current_environment_);
653 }
654 pending_header_merges_.clear();
655 pending_exit_merges_.clear();
656 header_environment_ = NULL;
657 ASSERT(IsDone());
658 }
659
660 } // namespace compiler
661 } // namespace internal
662 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/structured-machine-assembler.h ('k') | src/compiler/typer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698