The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / lithium-allocator.cc @ f230a1cf

History | View | Annotate | Download (74.5 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include "v8.h"
29
#include "lithium-allocator-inl.h"
30

    
31
#include "hydrogen.h"
32
#include "string-stream.h"
33

    
34
#if V8_TARGET_ARCH_IA32
35
#include "ia32/lithium-ia32.h"
36
#elif V8_TARGET_ARCH_X64
37
#include "x64/lithium-x64.h"
38
#elif V8_TARGET_ARCH_ARM
39
#include "arm/lithium-arm.h"
40
#elif V8_TARGET_ARCH_MIPS
41
#include "mips/lithium-mips.h"
42
#else
43
#error "Unknown architecture."
44
#endif
45

    
46
namespace v8 {
47
namespace internal {
48

    
49
static inline LifetimePosition Min(LifetimePosition a, LifetimePosition b) {
50
  return a.Value() < b.Value() ? a : b;
51
}
52

    
53

    
54
static inline LifetimePosition Max(LifetimePosition a, LifetimePosition b) {
55
  return a.Value() > b.Value() ? a : b;
56
}
57

    
58

    
59
UsePosition::UsePosition(LifetimePosition pos,
60
                         LOperand* operand,
61
                         LOperand* hint)
62
    : operand_(operand),
63
      hint_(hint),
64
      pos_(pos),
65
      next_(NULL),
66
      requires_reg_(false),
67
      register_beneficial_(true) {
68
  if (operand_ != NULL && operand_->IsUnallocated()) {
69
    LUnallocated* unalloc = LUnallocated::cast(operand_);
70
    requires_reg_ = unalloc->HasRegisterPolicy();
71
    register_beneficial_ = !unalloc->HasAnyPolicy();
72
  }
73
  ASSERT(pos_.IsValid());
74
}
75

    
76

    
77
bool UsePosition::HasHint() const {
78
  return hint_ != NULL && !hint_->IsUnallocated();
79
}
80

    
81

    
82
bool UsePosition::RequiresRegister() const {
83
  return requires_reg_;
84
}
85

    
86

    
87
bool UsePosition::RegisterIsBeneficial() const {
88
  return register_beneficial_;
89
}
90

    
91

    
92
void UseInterval::SplitAt(LifetimePosition pos, Zone* zone) {
93
  ASSERT(Contains(pos) && pos.Value() != start().Value());
94
  UseInterval* after = new(zone) UseInterval(pos, end_);
95
  after->next_ = next_;
96
  next_ = after;
97
  end_ = pos;
98
}
99

    
100

    
101
#ifdef DEBUG
102

    
103

    
104
void LiveRange::Verify() const {
105
  UsePosition* cur = first_pos_;
106
  while (cur != NULL) {
107
    ASSERT(Start().Value() <= cur->pos().Value() &&
108
           cur->pos().Value() <= End().Value());
109
    cur = cur->next();
110
  }
111
}
112

    
113

    
114
bool LiveRange::HasOverlap(UseInterval* target) const {
115
  UseInterval* current_interval = first_interval_;
116
  while (current_interval != NULL) {
117
    // Intervals overlap if the start of one is contained in the other.
118
    if (current_interval->Contains(target->start()) ||
119
        target->Contains(current_interval->start())) {
120
      return true;
121
    }
122
    current_interval = current_interval->next();
123
  }
124
  return false;
125
}
126

    
127

    
128
#endif
129

    
130

    
131
LiveRange::LiveRange(int id, Zone* zone)
132
    : id_(id),
133
      spilled_(false),
134
      kind_(UNALLOCATED_REGISTERS),
135
      assigned_register_(kInvalidAssignment),
136
      last_interval_(NULL),
137
      first_interval_(NULL),
138
      first_pos_(NULL),
139
      parent_(NULL),
140
      next_(NULL),
141
      current_interval_(NULL),
142
      last_processed_use_(NULL),
143
      current_hint_operand_(NULL),
144
      spill_operand_(new(zone) LOperand()),
145
      spill_start_index_(kMaxInt) { }
146

    
147

    
148
void LiveRange::set_assigned_register(int reg, Zone* zone) {
149
  ASSERT(!HasRegisterAssigned() && !IsSpilled());
150
  assigned_register_ = reg;
151
  ConvertOperands(zone);
152
}
153

    
154

    
155
void LiveRange::MakeSpilled(Zone* zone) {
156
  ASSERT(!IsSpilled());
157
  ASSERT(TopLevel()->HasAllocatedSpillOperand());
158
  spilled_ = true;
159
  assigned_register_ = kInvalidAssignment;
160
  ConvertOperands(zone);
161
}
162

    
163

    
164
bool LiveRange::HasAllocatedSpillOperand() const {
165
  ASSERT(spill_operand_ != NULL);
166
  return !spill_operand_->IsIgnored();
167
}
168

    
169

    
170
void LiveRange::SetSpillOperand(LOperand* operand) {
171
  ASSERT(!operand->IsUnallocated());
172
  ASSERT(spill_operand_ != NULL);
173
  ASSERT(spill_operand_->IsIgnored());
174
  spill_operand_->ConvertTo(operand->kind(), operand->index());
175
}
176

    
177

    
178
UsePosition* LiveRange::NextUsePosition(LifetimePosition start) {
179
  UsePosition* use_pos = last_processed_use_;
180
  if (use_pos == NULL) use_pos = first_pos();
181
  while (use_pos != NULL && use_pos->pos().Value() < start.Value()) {
182
    use_pos = use_pos->next();
183
  }
184
  last_processed_use_ = use_pos;
185
  return use_pos;
186
}
187

    
188

    
189
UsePosition* LiveRange::NextUsePositionRegisterIsBeneficial(
190
    LifetimePosition start) {
191
  UsePosition* pos = NextUsePosition(start);
192
  while (pos != NULL && !pos->RegisterIsBeneficial()) {
193
    pos = pos->next();
194
  }
195
  return pos;
196
}
197

    
198

    
199
UsePosition* LiveRange::PreviousUsePositionRegisterIsBeneficial(
200
    LifetimePosition start) {
201
  UsePosition* pos = first_pos();
202
  UsePosition* prev = NULL;
203
  while (pos != NULL && pos->pos().Value() < start.Value()) {
204
    if (pos->RegisterIsBeneficial()) prev = pos;
205
    pos = pos->next();
206
  }
207
  return prev;
208
}
209

    
210

    
211
UsePosition* LiveRange::NextRegisterPosition(LifetimePosition start) {
212
  UsePosition* pos = NextUsePosition(start);
213
  while (pos != NULL && !pos->RequiresRegister()) {
214
    pos = pos->next();
215
  }
216
  return pos;
217
}
218

    
219

    
220
bool LiveRange::CanBeSpilled(LifetimePosition pos) {
221
  // We cannot spill a live range that has a use requiring a register
222
  // at the current or the immediate next position.
223
  UsePosition* use_pos = NextRegisterPosition(pos);
224
  if (use_pos == NULL) return true;
225
  return
226
      use_pos->pos().Value() > pos.NextInstruction().InstructionEnd().Value();
227
}
228

    
229

    
230
LOperand* LiveRange::CreateAssignedOperand(Zone* zone) {
231
  LOperand* op = NULL;
232
  if (HasRegisterAssigned()) {
233
    ASSERT(!IsSpilled());
234
    switch (Kind()) {
235
      case GENERAL_REGISTERS:
236
        op = LRegister::Create(assigned_register(), zone);
237
        break;
238
      case DOUBLE_REGISTERS:
239
        op = LDoubleRegister::Create(assigned_register(), zone);
240
        break;
241
      default:
242
        UNREACHABLE();
243
    }
244
  } else if (IsSpilled()) {
245
    ASSERT(!HasRegisterAssigned());
246
    op = TopLevel()->GetSpillOperand();
247
    ASSERT(!op->IsUnallocated());
248
  } else {
249
    LUnallocated* unalloc = new(zone) LUnallocated(LUnallocated::NONE);
250
    unalloc->set_virtual_register(id_);
251
    op = unalloc;
252
  }
253
  return op;
254
}
255

    
256

    
257
UseInterval* LiveRange::FirstSearchIntervalForPosition(
258
    LifetimePosition position) const {
259
  if (current_interval_ == NULL) return first_interval_;
260
  if (current_interval_->start().Value() > position.Value()) {
261
    current_interval_ = NULL;
262
    return first_interval_;
263
  }
264
  return current_interval_;
265
}
266

    
267

    
268
void LiveRange::AdvanceLastProcessedMarker(
269
    UseInterval* to_start_of, LifetimePosition but_not_past) const {
270
  if (to_start_of == NULL) return;
271
  if (to_start_of->start().Value() > but_not_past.Value()) return;
272
  LifetimePosition start =
273
      current_interval_ == NULL ? LifetimePosition::Invalid()
274
                                : current_interval_->start();
275
  if (to_start_of->start().Value() > start.Value()) {
276
    current_interval_ = to_start_of;
277
  }
278
}
279

    
280

    
281
void LiveRange::SplitAt(LifetimePosition position,
282
                        LiveRange* result,
283
                        Zone* zone) {
284
  ASSERT(Start().Value() < position.Value());
285
  ASSERT(result->IsEmpty());
286
  // Find the last interval that ends before the position. If the
287
  // position is contained in one of the intervals in the chain, we
288
  // split that interval and use the first part.
289
  UseInterval* current = FirstSearchIntervalForPosition(position);
290

    
291
  // If the split position coincides with the beginning of a use interval
292
  // we need to split use positons in a special way.
293
  bool split_at_start = false;
294

    
295
  if (current->start().Value() == position.Value()) {
296
    // When splitting at start we need to locate the previous use interval.
297
    current = first_interval_;
298
  }
299

    
300
  while (current != NULL) {
301
    if (current->Contains(position)) {
302
      current->SplitAt(position, zone);
303
      break;
304
    }
305
    UseInterval* next = current->next();
306
    if (next->start().Value() >= position.Value()) {
307
      split_at_start = (next->start().Value() == position.Value());
308
      break;
309
    }
310
    current = next;
311
  }
312

    
313
  // Partition original use intervals to the two live ranges.
314
  UseInterval* before = current;
315
  UseInterval* after = before->next();
316
  result->last_interval_ = (last_interval_ == before)
317
      ? after            // Only interval in the range after split.
318
      : last_interval_;  // Last interval of the original range.
319
  result->first_interval_ = after;
320
  last_interval_ = before;
321

    
322
  // Find the last use position before the split and the first use
323
  // position after it.
324
  UsePosition* use_after = first_pos_;
325
  UsePosition* use_before = NULL;
326
  if (split_at_start) {
327
    // The split position coincides with the beginning of a use interval (the
328
    // end of a lifetime hole). Use at this position should be attributed to
329
    // the split child because split child owns use interval covering it.
330
    while (use_after != NULL && use_after->pos().Value() < position.Value()) {
331
      use_before = use_after;
332
      use_after = use_after->next();
333
    }
334
  } else {
335
    while (use_after != NULL && use_after->pos().Value() <= position.Value()) {
336
      use_before = use_after;
337
      use_after = use_after->next();
338
    }
339
  }
340

    
341
  // Partition original use positions to the two live ranges.
342
  if (use_before != NULL) {
343
    use_before->next_ = NULL;
344
  } else {
345
    first_pos_ = NULL;
346
  }
347
  result->first_pos_ = use_after;
348

    
349
  // Discard cached iteration state. It might be pointing
350
  // to the use that no longer belongs to this live range.
351
  last_processed_use_ = NULL;
352
  current_interval_ = NULL;
353

    
354
  // Link the new live range in the chain before any of the other
355
  // ranges linked from the range before the split.
356
  result->parent_ = (parent_ == NULL) ? this : parent_;
357
  result->kind_ = result->parent_->kind_;
358
  result->next_ = next_;
359
  next_ = result;
360

    
361
#ifdef DEBUG
362
  Verify();
363
  result->Verify();
364
#endif
365
}
366

    
367

    
368
// This implements an ordering on live ranges so that they are ordered by their
369
// start positions.  This is needed for the correctness of the register
370
// allocation algorithm.  If two live ranges start at the same offset then there
371
// is a tie breaker based on where the value is first used.  This part of the
372
// ordering is merely a heuristic.
373
bool LiveRange::ShouldBeAllocatedBefore(const LiveRange* other) const {
374
  LifetimePosition start = Start();
375
  LifetimePosition other_start = other->Start();
376
  if (start.Value() == other_start.Value()) {
377
    UsePosition* pos = first_pos();
378
    if (pos == NULL) return false;
379
    UsePosition* other_pos = other->first_pos();
380
    if (other_pos == NULL) return true;
381
    return pos->pos().Value() < other_pos->pos().Value();
382
  }
383
  return start.Value() < other_start.Value();
384
}
385

    
386

    
387
void LiveRange::ShortenTo(LifetimePosition start) {
388
  LAllocator::TraceAlloc("Shorten live range %d to [%d\n", id_, start.Value());
389
  ASSERT(first_interval_ != NULL);
390
  ASSERT(first_interval_->start().Value() <= start.Value());
391
  ASSERT(start.Value() < first_interval_->end().Value());
392
  first_interval_->set_start(start);
393
}
394

    
395

    
396
void LiveRange::EnsureInterval(LifetimePosition start,
397
                               LifetimePosition end,
398
                               Zone* zone) {
399
  LAllocator::TraceAlloc("Ensure live range %d in interval [%d %d[\n",
400
                         id_,
401
                         start.Value(),
402
                         end.Value());
403
  LifetimePosition new_end = end;
404
  while (first_interval_ != NULL &&
405
         first_interval_->start().Value() <= end.Value()) {
406
    if (first_interval_->end().Value() > end.Value()) {
407
      new_end = first_interval_->end();
408
    }
409
    first_interval_ = first_interval_->next();
410
  }
411

    
412
  UseInterval* new_interval = new(zone) UseInterval(start, new_end);
413
  new_interval->next_ = first_interval_;
414
  first_interval_ = new_interval;
415
  if (new_interval->next() == NULL) {
416
    last_interval_ = new_interval;
417
  }
418
}
419

    
420

    
421
void LiveRange::AddUseInterval(LifetimePosition start,
422
                               LifetimePosition end,
423
                               Zone* zone) {
424
  LAllocator::TraceAlloc("Add to live range %d interval [%d %d[\n",
425
                         id_,
426
                         start.Value(),
427
                         end.Value());
428
  if (first_interval_ == NULL) {
429
    UseInterval* interval = new(zone) UseInterval(start, end);
430
    first_interval_ = interval;
431
    last_interval_ = interval;
432
  } else {
433
    if (end.Value() == first_interval_->start().Value()) {
434
      first_interval_->set_start(start);
435
    } else if (end.Value() < first_interval_->start().Value()) {
436
      UseInterval* interval = new(zone) UseInterval(start, end);
437
      interval->set_next(first_interval_);
438
      first_interval_ = interval;
439
    } else {
440
      // Order of instruction's processing (see ProcessInstructions) guarantees
441
      // that each new use interval either precedes or intersects with
442
      // last added interval.
443
      ASSERT(start.Value() < first_interval_->end().Value());
444
      first_interval_->start_ = Min(start, first_interval_->start_);
445
      first_interval_->end_ = Max(end, first_interval_->end_);
446
    }
447
  }
448
}
449

    
450

    
451
void LiveRange::AddUsePosition(LifetimePosition pos,
452
                               LOperand* operand,
453
                               LOperand* hint,
454
                               Zone* zone) {
455
  LAllocator::TraceAlloc("Add to live range %d use position %d\n",
456
                         id_,
457
                         pos.Value());
458
  UsePosition* use_pos = new(zone) UsePosition(pos, operand, hint);
459
  UsePosition* prev_hint = NULL;
460
  UsePosition* prev = NULL;
461
  UsePosition* current = first_pos_;
462
  while (current != NULL && current->pos().Value() < pos.Value()) {
463
    prev_hint = current->HasHint() ? current : prev_hint;
464
    prev = current;
465
    current = current->next();
466
  }
467

    
468
  if (prev == NULL) {
469
    use_pos->set_next(first_pos_);
470
    first_pos_ = use_pos;
471
  } else {
472
    use_pos->next_ = prev->next_;
473
    prev->next_ = use_pos;
474
  }
475

    
476
  if (prev_hint == NULL && use_pos->HasHint()) {
477
    current_hint_operand_ = hint;
478
  }
479
}
480

    
481

    
482
void LiveRange::ConvertOperands(Zone* zone) {
483
  LOperand* op = CreateAssignedOperand(zone);
484
  UsePosition* use_pos = first_pos();
485
  while (use_pos != NULL) {
486
    ASSERT(Start().Value() <= use_pos->pos().Value() &&
487
           use_pos->pos().Value() <= End().Value());
488

    
489
    if (use_pos->HasOperand()) {
490
      ASSERT(op->IsRegister() || op->IsDoubleRegister() ||
491
             !use_pos->RequiresRegister());
492
      use_pos->operand()->ConvertTo(op->kind(), op->index());
493
    }
494
    use_pos = use_pos->next();
495
  }
496
}
497

    
498

    
499
bool LiveRange::CanCover(LifetimePosition position) const {
500
  if (IsEmpty()) return false;
501
  return Start().Value() <= position.Value() &&
502
         position.Value() < End().Value();
503
}
504

    
505

    
506
bool LiveRange::Covers(LifetimePosition position) {
507
  if (!CanCover(position)) return false;
508
  UseInterval* start_search = FirstSearchIntervalForPosition(position);
509
  for (UseInterval* interval = start_search;
510
       interval != NULL;
511
       interval = interval->next()) {
512
    ASSERT(interval->next() == NULL ||
513
           interval->next()->start().Value() >= interval->start().Value());
514
    AdvanceLastProcessedMarker(interval, position);
515
    if (interval->Contains(position)) return true;
516
    if (interval->start().Value() > position.Value()) return false;
517
  }
518
  return false;
519
}
520

    
521

    
522
LifetimePosition LiveRange::FirstIntersection(LiveRange* other) {
523
  UseInterval* b = other->first_interval();
524
  if (b == NULL) return LifetimePosition::Invalid();
525
  LifetimePosition advance_last_processed_up_to = b->start();
526
  UseInterval* a = FirstSearchIntervalForPosition(b->start());
527
  while (a != NULL && b != NULL) {
528
    if (a->start().Value() > other->End().Value()) break;
529
    if (b->start().Value() > End().Value()) break;
530
    LifetimePosition cur_intersection = a->Intersect(b);
531
    if (cur_intersection.IsValid()) {
532
      return cur_intersection;
533
    }
534
    if (a->start().Value() < b->start().Value()) {
535
      a = a->next();
536
      if (a == NULL || a->start().Value() > other->End().Value()) break;
537
      AdvanceLastProcessedMarker(a, advance_last_processed_up_to);
538
    } else {
539
      b = b->next();
540
    }
541
  }
542
  return LifetimePosition::Invalid();
543
}
544

    
545

    
546
LAllocator::LAllocator(int num_values, HGraph* graph)
547
    : zone_(graph->isolate()),
548
      chunk_(NULL),
549
      live_in_sets_(graph->blocks()->length(), zone()),
550
      live_ranges_(num_values * 2, zone()),
551
      fixed_live_ranges_(NULL),
552
      fixed_double_live_ranges_(NULL),
553
      unhandled_live_ranges_(num_values * 2, zone()),
554
      active_live_ranges_(8, zone()),
555
      inactive_live_ranges_(8, zone()),
556
      reusable_slots_(8, zone()),
557
      next_virtual_register_(num_values),
558
      first_artificial_register_(num_values),
559
      mode_(UNALLOCATED_REGISTERS),
560
      num_registers_(-1),
561
      graph_(graph),
562
      has_osr_entry_(false),
563
      allocation_ok_(true) { }
564

    
565

    
566
void LAllocator::InitializeLivenessAnalysis() {
567
  // Initialize the live_in sets for each block to NULL.
568
  int block_count = graph_->blocks()->length();
569
  live_in_sets_.Initialize(block_count, zone());
570
  live_in_sets_.AddBlock(NULL, block_count, zone());
571
}
572

    
573

    
574
BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) {
575
  // Compute live out for the given block, except not including backward
576
  // successor edges.
577
  BitVector* live_out = new(zone()) BitVector(next_virtual_register_, zone());
578

    
579
  // Process all successor blocks.
580
  for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
581
    // Add values live on entry to the successor. Note the successor's
582
    // live_in will not be computed yet for backwards edges.
583
    HBasicBlock* successor = it.Current();
584
    BitVector* live_in = live_in_sets_[successor->block_id()];
585
    if (live_in != NULL) live_out->Union(*live_in);
586

    
587
    // All phi input operands corresponding to this successor edge are live
588
    // out from this block.
589
    int index = successor->PredecessorIndexOf(block);
590
    const ZoneList<HPhi*>* phis = successor->phis();
591
    for (int i = 0; i < phis->length(); ++i) {
592
      HPhi* phi = phis->at(i);
593
      if (!phi->OperandAt(index)->IsConstant()) {
594
        live_out->Add(phi->OperandAt(index)->id());
595
      }
596
    }
597
  }
598

    
599
  return live_out;
600
}
601

    
602

    
603
void LAllocator::AddInitialIntervals(HBasicBlock* block,
604
                                     BitVector* live_out) {
605
  // Add an interval that includes the entire block to the live range for
606
  // each live_out value.
607
  LifetimePosition start = LifetimePosition::FromInstructionIndex(
608
      block->first_instruction_index());
609
  LifetimePosition end = LifetimePosition::FromInstructionIndex(
610
      block->last_instruction_index()).NextInstruction();
611
  BitVector::Iterator iterator(live_out);
612
  while (!iterator.Done()) {
613
    int operand_index = iterator.Current();
614
    LiveRange* range = LiveRangeFor(operand_index);
615
    range->AddUseInterval(start, end, zone());
616
    iterator.Advance();
617
  }
618
}
619

    
620

    
621
int LAllocator::FixedDoubleLiveRangeID(int index) {
622
  return -index - 1 - Register::kMaxNumAllocatableRegisters;
623
}
624

    
625

    
626
LOperand* LAllocator::AllocateFixed(LUnallocated* operand,
627
                                    int pos,
628
                                    bool is_tagged) {
629
  TraceAlloc("Allocating fixed reg for op %d\n", operand->virtual_register());
630
  ASSERT(operand->HasFixedPolicy());
631
  if (operand->HasFixedSlotPolicy()) {
632
    operand->ConvertTo(LOperand::STACK_SLOT, operand->fixed_slot_index());
633
  } else if (operand->HasFixedRegisterPolicy()) {
634
    int reg_index = operand->fixed_register_index();
635
    operand->ConvertTo(LOperand::REGISTER, reg_index);
636
  } else if (operand->HasFixedDoubleRegisterPolicy()) {
637
    int reg_index = operand->fixed_register_index();
638
    operand->ConvertTo(LOperand::DOUBLE_REGISTER, reg_index);
639
  } else {
640
    UNREACHABLE();
641
  }
642
  if (is_tagged) {
643
    TraceAlloc("Fixed reg is tagged at %d\n", pos);
644
    LInstruction* instr = InstructionAt(pos);
645
    if (instr->HasPointerMap()) {
646
      instr->pointer_map()->RecordPointer(operand, chunk()->zone());
647
    }
648
  }
649
  return operand;
650
}
651

    
652

    
653
LiveRange* LAllocator::FixedLiveRangeFor(int index) {
654
  ASSERT(index < Register::kMaxNumAllocatableRegisters);
655
  LiveRange* result = fixed_live_ranges_[index];
656
  if (result == NULL) {
657
    result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone());
658
    ASSERT(result->IsFixed());
659
    result->kind_ = GENERAL_REGISTERS;
660
    SetLiveRangeAssignedRegister(result, index);
661
    fixed_live_ranges_[index] = result;
662
  }
663
  return result;
664
}
665

    
666

    
667
LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) {
668
  ASSERT(index < DoubleRegister::NumAllocatableRegisters());
669
  LiveRange* result = fixed_double_live_ranges_[index];
670
  if (result == NULL) {
671
    result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index),
672
                                   chunk()->zone());
673
    ASSERT(result->IsFixed());
674
    result->kind_ = DOUBLE_REGISTERS;
675
    SetLiveRangeAssignedRegister(result, index);
676
    fixed_double_live_ranges_[index] = result;
677
  }
678
  return result;
679
}
680

    
681

    
682
LiveRange* LAllocator::LiveRangeFor(int index) {
683
  if (index >= live_ranges_.length()) {
684
    live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1, zone());
685
  }
686
  LiveRange* result = live_ranges_[index];
687
  if (result == NULL) {
688
    result = new(zone()) LiveRange(index, chunk()->zone());
689
    live_ranges_[index] = result;
690
  }
691
  return result;
692
}
693

    
694

    
695
LGap* LAllocator::GetLastGap(HBasicBlock* block) {
696
  int last_instruction = block->last_instruction_index();
697
  int index = chunk_->NearestGapPos(last_instruction);
698
  return GapAt(index);
699
}
700

    
701

    
702
HPhi* LAllocator::LookupPhi(LOperand* operand) const {
703
  if (!operand->IsUnallocated()) return NULL;
704
  int index = LUnallocated::cast(operand)->virtual_register();
705
  HValue* instr = graph_->LookupValue(index);
706
  if (instr != NULL && instr->IsPhi()) {
707
    return HPhi::cast(instr);
708
  }
709
  return NULL;
710
}
711

    
712

    
713
LiveRange* LAllocator::LiveRangeFor(LOperand* operand) {
714
  if (operand->IsUnallocated()) {
715
    return LiveRangeFor(LUnallocated::cast(operand)->virtual_register());
716
  } else if (operand->IsRegister()) {
717
    return FixedLiveRangeFor(operand->index());
718
  } else if (operand->IsDoubleRegister()) {
719
    return FixedDoubleLiveRangeFor(operand->index());
720
  } else {
721
    return NULL;
722
  }
723
}
724

    
725

    
726
void LAllocator::Define(LifetimePosition position,
727
                        LOperand* operand,
728
                        LOperand* hint) {
729
  LiveRange* range = LiveRangeFor(operand);
730
  if (range == NULL) return;
731

    
732
  if (range->IsEmpty() || range->Start().Value() > position.Value()) {
733
    // Can happen if there is a definition without use.
734
    range->AddUseInterval(position, position.NextInstruction(), zone());
735
    range->AddUsePosition(position.NextInstruction(), NULL, NULL, zone());
736
  } else {
737
    range->ShortenTo(position);
738
  }
739

    
740
  if (operand->IsUnallocated()) {
741
    LUnallocated* unalloc_operand = LUnallocated::cast(operand);
742
    range->AddUsePosition(position, unalloc_operand, hint, zone());
743
  }
744
}
745

    
746

    
747
void LAllocator::Use(LifetimePosition block_start,
748
                     LifetimePosition position,
749
                     LOperand* operand,
750
                     LOperand* hint) {
751
  LiveRange* range = LiveRangeFor(operand);
752
  if (range == NULL) return;
753
  if (operand->IsUnallocated()) {
754
    LUnallocated* unalloc_operand = LUnallocated::cast(operand);
755
    range->AddUsePosition(position, unalloc_operand, hint, zone());
756
  }
757
  range->AddUseInterval(block_start, position, zone());
758
}
759

    
760

    
761
void LAllocator::AddConstraintsGapMove(int index,
762
                                       LOperand* from,
763
                                       LOperand* to) {
764
  LGap* gap = GapAt(index);
765
  LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START,
766
                                                     chunk()->zone());
767
  if (from->IsUnallocated()) {
768
    const ZoneList<LMoveOperands>* move_operands = move->move_operands();
769
    for (int i = 0; i < move_operands->length(); ++i) {
770
      LMoveOperands cur = move_operands->at(i);
771
      LOperand* cur_to = cur.destination();
772
      if (cur_to->IsUnallocated()) {
773
        if (LUnallocated::cast(cur_to)->virtual_register() ==
774
            LUnallocated::cast(from)->virtual_register()) {
775
          move->AddMove(cur.source(), to, chunk()->zone());
776
          return;
777
        }
778
      }
779
    }
780
  }
781
  move->AddMove(from, to, chunk()->zone());
782
}
783

    
784

    
785
void LAllocator::MeetRegisterConstraints(HBasicBlock* block) {
786
  int start = block->first_instruction_index();
787
  int end = block->last_instruction_index();
788
  if (start == -1) return;
789
  for (int i = start; i <= end; ++i) {
790
    if (IsGapAt(i)) {
791
      LInstruction* instr = NULL;
792
      LInstruction* prev_instr = NULL;
793
      if (i < end) instr = InstructionAt(i + 1);
794
      if (i > start) prev_instr = InstructionAt(i - 1);
795
      MeetConstraintsBetween(prev_instr, instr, i);
796
      if (!AllocationOk()) return;
797
    }
798
  }
799
}
800

    
801

    
802
void LAllocator::MeetConstraintsBetween(LInstruction* first,
803
                                        LInstruction* second,
804
                                        int gap_index) {
805
  // Handle fixed temporaries.
806
  if (first != NULL) {
807
    for (TempIterator it(first); !it.Done(); it.Advance()) {
808
      LUnallocated* temp = LUnallocated::cast(it.Current());
809
      if (temp->HasFixedPolicy()) {
810
        AllocateFixed(temp, gap_index - 1, false);
811
      }
812
    }
813
  }
814

    
815
  // Handle fixed output operand.
816
  if (first != NULL && first->Output() != NULL) {
817
    LUnallocated* first_output = LUnallocated::cast(first->Output());
818
    LiveRange* range = LiveRangeFor(first_output->virtual_register());
819
    bool assigned = false;
820
    if (first_output->HasFixedPolicy()) {
821
      LUnallocated* output_copy = first_output->CopyUnconstrained(
822
          chunk()->zone());
823
      bool is_tagged = HasTaggedValue(first_output->virtual_register());
824
      AllocateFixed(first_output, gap_index, is_tagged);
825

    
826
      // This value is produced on the stack, we never need to spill it.
827
      if (first_output->IsStackSlot()) {
828
        range->SetSpillOperand(first_output);
829
        range->SetSpillStartIndex(gap_index - 1);
830
        assigned = true;
831
      }
832
      chunk_->AddGapMove(gap_index, first_output, output_copy);
833
    }
834

    
835
    if (!assigned) {
836
      range->SetSpillStartIndex(gap_index);
837

    
838
      // This move to spill operand is not a real use. Liveness analysis
839
      // and splitting of live ranges do not account for it.
840
      // Thus it should be inserted to a lifetime position corresponding to
841
      // the instruction end.
842
      LGap* gap = GapAt(gap_index);
843
      LParallelMove* move = gap->GetOrCreateParallelMove(LGap::BEFORE,
844
                                                         chunk()->zone());
845
      move->AddMove(first_output, range->GetSpillOperand(),
846
                    chunk()->zone());
847
    }
848
  }
849

    
850
  // Handle fixed input operands of second instruction.
851
  if (second != NULL) {
852
    for (UseIterator it(second); !it.Done(); it.Advance()) {
853
      LUnallocated* cur_input = LUnallocated::cast(it.Current());
854
      if (cur_input->HasFixedPolicy()) {
855
        LUnallocated* input_copy = cur_input->CopyUnconstrained(
856
            chunk()->zone());
857
        bool is_tagged = HasTaggedValue(cur_input->virtual_register());
858
        AllocateFixed(cur_input, gap_index + 1, is_tagged);
859
        AddConstraintsGapMove(gap_index, input_copy, cur_input);
860
      } else if (cur_input->HasWritableRegisterPolicy()) {
861
        // The live range of writable input registers always goes until the end
862
        // of the instruction.
863
        ASSERT(!cur_input->IsUsedAtStart());
864

    
865
        LUnallocated* input_copy = cur_input->CopyUnconstrained(
866
            chunk()->zone());
867
        int vreg = GetVirtualRegister();
868
        if (!AllocationOk()) return;
869
        cur_input->set_virtual_register(vreg);
870

    
871
        if (RequiredRegisterKind(input_copy->virtual_register()) ==
872
            DOUBLE_REGISTERS) {
873
          double_artificial_registers_.Add(
874
              cur_input->virtual_register() - first_artificial_register_,
875
              zone());
876
        }
877

    
878
        AddConstraintsGapMove(gap_index, input_copy, cur_input);
879
      }
880
    }
881
  }
882

    
883
  // Handle "output same as input" for second instruction.
884
  if (second != NULL && second->Output() != NULL) {
885
    LUnallocated* second_output = LUnallocated::cast(second->Output());
886
    if (second_output->HasSameAsInputPolicy()) {
887
      LUnallocated* cur_input = LUnallocated::cast(second->FirstInput());
888
      int output_vreg = second_output->virtual_register();
889
      int input_vreg = cur_input->virtual_register();
890

    
891
      LUnallocated* input_copy = cur_input->CopyUnconstrained(
892
          chunk()->zone());
893
      cur_input->set_virtual_register(second_output->virtual_register());
894
      AddConstraintsGapMove(gap_index, input_copy, cur_input);
895

    
896
      if (HasTaggedValue(input_vreg) && !HasTaggedValue(output_vreg)) {
897
        int index = gap_index + 1;
898
        LInstruction* instr = InstructionAt(index);
899
        if (instr->HasPointerMap()) {
900
          instr->pointer_map()->RecordPointer(input_copy, chunk()->zone());
901
        }
902
      } else if (!HasTaggedValue(input_vreg) && HasTaggedValue(output_vreg)) {
903
        // The input is assumed to immediately have a tagged representation,
904
        // before the pointer map can be used. I.e. the pointer map at the
905
        // instruction will include the output operand (whose value at the
906
        // beginning of the instruction is equal to the input operand). If
907
        // this is not desired, then the pointer map at this instruction needs
908
        // to be adjusted manually.
909
      }
910
    }
911
  }
912
}
913

    
914

    
915
void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) {
916
  int block_start = block->first_instruction_index();
917
  int index = block->last_instruction_index();
918

    
919
  LifetimePosition block_start_position =
920
      LifetimePosition::FromInstructionIndex(block_start);
921

    
922
  while (index >= block_start) {
923
    LifetimePosition curr_position =
924
        LifetimePosition::FromInstructionIndex(index);
925

    
926
    if (IsGapAt(index)) {
927
      // We have a gap at this position.
928
      LGap* gap = GapAt(index);
929
      LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START,
930
                                                         chunk()->zone());
931
      const ZoneList<LMoveOperands>* move_operands = move->move_operands();
932
      for (int i = 0; i < move_operands->length(); ++i) {
933
        LMoveOperands* cur = &move_operands->at(i);
934
        if (cur->IsIgnored()) continue;
935
        LOperand* from = cur->source();
936
        LOperand* to = cur->destination();
937
        HPhi* phi = LookupPhi(to);
938
        LOperand* hint = to;
939
        if (phi != NULL) {
940
          // This is a phi resolving move.
941
          if (!phi->block()->IsLoopHeader()) {
942
            hint = LiveRangeFor(phi->id())->current_hint_operand();
943
          }
944
        } else {
945
          if (to->IsUnallocated()) {
946
            if (live->Contains(LUnallocated::cast(to)->virtual_register())) {
947
              Define(curr_position, to, from);
948
              live->Remove(LUnallocated::cast(to)->virtual_register());
949
            } else {
950
              cur->Eliminate();
951
              continue;
952
            }
953
          } else {
954
            Define(curr_position, to, from);
955
          }
956
        }
957
        Use(block_start_position, curr_position, from, hint);
958
        if (from->IsUnallocated()) {
959
          live->Add(LUnallocated::cast(from)->virtual_register());
960
        }
961
      }
962
    } else {
963
      ASSERT(!IsGapAt(index));
964
      LInstruction* instr = InstructionAt(index);
965

    
966
      if (instr != NULL) {
967
        LOperand* output = instr->Output();
968
        if (output != NULL) {
969
          if (output->IsUnallocated()) {
970
            live->Remove(LUnallocated::cast(output)->virtual_register());
971
          }
972
          Define(curr_position, output, NULL);
973
        }
974

    
975
        if (instr->ClobbersRegisters()) {
976
          for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
977
            if (output == NULL || !output->IsRegister() ||
978
                output->index() != i) {
979
              LiveRange* range = FixedLiveRangeFor(i);
980
              range->AddUseInterval(curr_position,
981
                                    curr_position.InstructionEnd(),
982
                                    zone());
983
            }
984
          }
985
        }
986

    
987
        if (instr->ClobbersDoubleRegisters()) {
988
          for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
989
            if (output == NULL || !output->IsDoubleRegister() ||
990
                output->index() != i) {
991
              LiveRange* range = FixedDoubleLiveRangeFor(i);
992
              range->AddUseInterval(curr_position,
993
                                    curr_position.InstructionEnd(),
994
                                    zone());
995
            }
996
          }
997
        }
998

    
999
        for (UseIterator it(instr); !it.Done(); it.Advance()) {
1000
          LOperand* input = it.Current();
1001

    
1002
          LifetimePosition use_pos;
1003
          if (input->IsUnallocated() &&
1004
              LUnallocated::cast(input)->IsUsedAtStart()) {
1005
            use_pos = curr_position;
1006
          } else {
1007
            use_pos = curr_position.InstructionEnd();
1008
          }
1009

    
1010
          Use(block_start_position, use_pos, input, NULL);
1011
          if (input->IsUnallocated()) {
1012
            live->Add(LUnallocated::cast(input)->virtual_register());
1013
          }
1014
        }
1015

    
1016
        for (TempIterator it(instr); !it.Done(); it.Advance()) {
1017
          LOperand* temp = it.Current();
1018
          if (instr->ClobbersTemps()) {
1019
            if (temp->IsRegister()) continue;
1020
            if (temp->IsUnallocated()) {
1021
              LUnallocated* temp_unalloc = LUnallocated::cast(temp);
1022
              if (temp_unalloc->HasFixedPolicy()) {
1023
                continue;
1024
              }
1025
            }
1026
          }
1027
          Use(block_start_position, curr_position.InstructionEnd(), temp, NULL);
1028
          Define(curr_position, temp, NULL);
1029
        }
1030
      }
1031
    }
1032

    
1033
    index = index - 1;
1034
  }
1035
}
1036

    
1037

    
1038
void LAllocator::ResolvePhis(HBasicBlock* block) {
1039
  const ZoneList<HPhi*>* phis = block->phis();
1040
  for (int i = 0; i < phis->length(); ++i) {
1041
    HPhi* phi = phis->at(i);
1042
    LUnallocated* phi_operand =
1043
        new(chunk()->zone()) LUnallocated(LUnallocated::NONE);
1044
    phi_operand->set_virtual_register(phi->id());
1045
    for (int j = 0; j < phi->OperandCount(); ++j) {
1046
      HValue* op = phi->OperandAt(j);
1047
      LOperand* operand = NULL;
1048
      if (op->IsConstant() && op->EmitAtUses()) {
1049
        HConstant* constant = HConstant::cast(op);
1050
        operand = chunk_->DefineConstantOperand(constant);
1051
      } else {
1052
        ASSERT(!op->EmitAtUses());
1053
        LUnallocated* unalloc =
1054
            new(chunk()->zone()) LUnallocated(LUnallocated::ANY);
1055
        unalloc->set_virtual_register(op->id());
1056
        operand = unalloc;
1057
      }
1058
      HBasicBlock* cur_block = block->predecessors()->at(j);
1059
      // The gap move must be added without any special processing as in
1060
      // the AddConstraintsGapMove.
1061
      chunk_->AddGapMove(cur_block->last_instruction_index() - 1,
1062
                         operand,
1063
                         phi_operand);
1064

    
1065
      // We are going to insert a move before the branch instruction.
1066
      // Some branch instructions (e.g. loops' back edges)
1067
      // can potentially cause a GC so they have a pointer map.
1068
      // By inserting a move we essentially create a copy of a
1069
      // value which is invisible to PopulatePointerMaps(), because we store
1070
      // it into a location different from the operand of a live range
1071
      // covering a branch instruction.
1072
      // Thus we need to manually record a pointer.
1073
      LInstruction* branch =
1074
          InstructionAt(cur_block->last_instruction_index());
1075
      if (branch->HasPointerMap()) {
1076
        if (phi->representation().IsTagged() && !phi->type().IsSmi()) {
1077
          branch->pointer_map()->RecordPointer(phi_operand, chunk()->zone());
1078
        } else if (!phi->representation().IsDouble()) {
1079
          branch->pointer_map()->RecordUntagged(phi_operand, chunk()->zone());
1080
        }
1081
      }
1082
    }
1083

    
1084
    LiveRange* live_range = LiveRangeFor(phi->id());
1085
    LLabel* label = chunk_->GetLabel(phi->block()->block_id());
1086
    label->GetOrCreateParallelMove(LGap::START, chunk()->zone())->
1087
        AddMove(phi_operand, live_range->GetSpillOperand(), chunk()->zone());
1088
    live_range->SetSpillStartIndex(phi->block()->first_instruction_index());
1089
  }
1090
}
1091

    
1092

    
1093
bool LAllocator::Allocate(LChunk* chunk) {
1094
  ASSERT(chunk_ == NULL);
1095
  chunk_ = static_cast<LPlatformChunk*>(chunk);
1096
  assigned_registers_ =
1097
      new(chunk->zone()) BitVector(Register::NumAllocatableRegisters(),
1098
                                   chunk->zone());
1099
  assigned_double_registers_ =
1100
      new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(),
1101
                                   chunk->zone());
1102
  MeetRegisterConstraints();
1103
  if (!AllocationOk()) return false;
1104
  ResolvePhis();
1105
  BuildLiveRanges();
1106
  AllocateGeneralRegisters();
1107
  if (!AllocationOk()) return false;
1108
  AllocateDoubleRegisters();
1109
  if (!AllocationOk()) return false;
1110
  PopulatePointerMaps();
1111
  ConnectRanges();
1112
  ResolveControlFlow();
1113
  return true;
1114
}
1115

    
1116

    
1117
void LAllocator::MeetRegisterConstraints() {
1118
  LAllocatorPhase phase("L_Register constraints", this);
1119
  first_artificial_register_ = next_virtual_register_;
1120
  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1121
  for (int i = 0; i < blocks->length(); ++i) {
1122
    HBasicBlock* block = blocks->at(i);
1123
    MeetRegisterConstraints(block);
1124
    if (!AllocationOk()) return;
1125
  }
1126
}
1127

    
1128

    
1129
void LAllocator::ResolvePhis() {
1130
  LAllocatorPhase phase("L_Resolve phis", this);
1131

    
1132
  // Process the blocks in reverse order.
1133
  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1134
  for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) {
1135
    HBasicBlock* block = blocks->at(block_id);
1136
    ResolvePhis(block);
1137
  }
1138
}
1139

    
1140

    
1141
void LAllocator::ResolveControlFlow(LiveRange* range,
1142
                                    HBasicBlock* block,
1143
                                    HBasicBlock* pred) {
1144
  LifetimePosition pred_end =
1145
      LifetimePosition::FromInstructionIndex(pred->last_instruction_index());
1146
  LifetimePosition cur_start =
1147
      LifetimePosition::FromInstructionIndex(block->first_instruction_index());
1148
  LiveRange* pred_cover = NULL;
1149
  LiveRange* cur_cover = NULL;
1150
  LiveRange* cur_range = range;
1151
  while (cur_range != NULL && (cur_cover == NULL || pred_cover == NULL)) {
1152
    if (cur_range->CanCover(cur_start)) {
1153
      ASSERT(cur_cover == NULL);
1154
      cur_cover = cur_range;
1155
    }
1156
    if (cur_range->CanCover(pred_end)) {
1157
      ASSERT(pred_cover == NULL);
1158
      pred_cover = cur_range;
1159
    }
1160
    cur_range = cur_range->next();
1161
  }
1162

    
1163
  if (cur_cover->IsSpilled()) return;
1164
  ASSERT(pred_cover != NULL && cur_cover != NULL);
1165
  if (pred_cover != cur_cover) {
1166
    LOperand* pred_op = pred_cover->CreateAssignedOperand(chunk()->zone());
1167
    LOperand* cur_op = cur_cover->CreateAssignedOperand(chunk()->zone());
1168
    if (!pred_op->Equals(cur_op)) {
1169
      LGap* gap = NULL;
1170
      if (block->predecessors()->length() == 1) {
1171
        gap = GapAt(block->first_instruction_index());
1172
      } else {
1173
        ASSERT(pred->end()->SecondSuccessor() == NULL);
1174
        gap = GetLastGap(pred);
1175

    
1176
        // We are going to insert a move before the branch instruction.
1177
        // Some branch instructions (e.g. loops' back edges)
1178
        // can potentially cause a GC so they have a pointer map.
1179
        // By inserting a move we essentially create a copy of a
1180
        // value which is invisible to PopulatePointerMaps(), because we store
1181
        // it into a location different from the operand of a live range
1182
        // covering a branch instruction.
1183
        // Thus we need to manually record a pointer.
1184
        LInstruction* branch = InstructionAt(pred->last_instruction_index());
1185
        if (branch->HasPointerMap()) {
1186
          if (HasTaggedValue(range->id())) {
1187
            branch->pointer_map()->RecordPointer(cur_op, chunk()->zone());
1188
          } else if (!cur_op->IsDoubleStackSlot() &&
1189
                     !cur_op->IsDoubleRegister()) {
1190
            branch->pointer_map()->RemovePointer(cur_op);
1191
          }
1192
        }
1193
      }
1194
      gap->GetOrCreateParallelMove(
1195
          LGap::START, chunk()->zone())->AddMove(pred_op, cur_op,
1196
                                                 chunk()->zone());
1197
    }
1198
  }
1199
}
1200

    
1201

    
1202
LParallelMove* LAllocator::GetConnectingParallelMove(LifetimePosition pos) {
1203
  int index = pos.InstructionIndex();
1204
  if (IsGapAt(index)) {
1205
    LGap* gap = GapAt(index);
1206
    return gap->GetOrCreateParallelMove(
1207
        pos.IsInstructionStart() ? LGap::START : LGap::END, chunk()->zone());
1208
  }
1209
  int gap_pos = pos.IsInstructionStart() ? (index - 1) : (index + 1);
1210
  return GapAt(gap_pos)->GetOrCreateParallelMove(
1211
      (gap_pos < index) ? LGap::AFTER : LGap::BEFORE, chunk()->zone());
1212
}
1213

    
1214

    
1215
HBasicBlock* LAllocator::GetBlock(LifetimePosition pos) {
1216
  LGap* gap = GapAt(chunk_->NearestGapPos(pos.InstructionIndex()));
1217
  return gap->block();
1218
}
1219

    
1220

    
1221
void LAllocator::ConnectRanges() {
1222
  LAllocatorPhase phase("L_Connect ranges", this);
1223
  for (int i = 0; i < live_ranges()->length(); ++i) {
1224
    LiveRange* first_range = live_ranges()->at(i);
1225
    if (first_range == NULL || first_range->parent() != NULL) continue;
1226

    
1227
    LiveRange* second_range = first_range->next();
1228
    while (second_range != NULL) {
1229
      LifetimePosition pos = second_range->Start();
1230

    
1231
      if (!second_range->IsSpilled()) {
1232
        // Add gap move if the two live ranges touch and there is no block
1233
        // boundary.
1234
        if (first_range->End().Value() == pos.Value()) {
1235
          bool should_insert = true;
1236
          if (IsBlockBoundary(pos)) {
1237
            should_insert = CanEagerlyResolveControlFlow(GetBlock(pos));
1238
          }
1239
          if (should_insert) {
1240
            LParallelMove* move = GetConnectingParallelMove(pos);
1241
            LOperand* prev_operand = first_range->CreateAssignedOperand(
1242
                chunk()->zone());
1243
            LOperand* cur_operand = second_range->CreateAssignedOperand(
1244
                chunk()->zone());
1245
            move->AddMove(prev_operand, cur_operand,
1246
                          chunk()->zone());
1247
          }
1248
        }
1249
      }
1250

    
1251
      first_range = second_range;
1252
      second_range = second_range->next();
1253
    }
1254
  }
1255
}
1256

    
1257

    
1258
bool LAllocator::CanEagerlyResolveControlFlow(HBasicBlock* block) const {
1259
  if (block->predecessors()->length() != 1) return false;
1260
  return block->predecessors()->first()->block_id() == block->block_id() - 1;
1261
}
1262

    
1263

    
1264
void LAllocator::ResolveControlFlow() {
1265
  LAllocatorPhase phase("L_Resolve control flow", this);
1266
  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1267
  for (int block_id = 1; block_id < blocks->length(); ++block_id) {
1268
    HBasicBlock* block = blocks->at(block_id);
1269
    if (CanEagerlyResolveControlFlow(block)) continue;
1270
    BitVector* live = live_in_sets_[block->block_id()];
1271
    BitVector::Iterator iterator(live);
1272
    while (!iterator.Done()) {
1273
      int operand_index = iterator.Current();
1274
      for (int i = 0; i < block->predecessors()->length(); ++i) {
1275
        HBasicBlock* cur = block->predecessors()->at(i);
1276
        LiveRange* cur_range = LiveRangeFor(operand_index);
1277
        ResolveControlFlow(cur_range, block, cur);
1278
      }
1279
      iterator.Advance();
1280
    }
1281
  }
1282
}
1283

    
1284

    
1285
void LAllocator::BuildLiveRanges() {
1286
  LAllocatorPhase phase("L_Build live ranges", this);
1287
  InitializeLivenessAnalysis();
1288
  // Process the blocks in reverse order.
1289
  const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
1290
  for (int block_id = blocks->length() - 1; block_id >= 0; --block_id) {
1291
    HBasicBlock* block = blocks->at(block_id);
1292
    BitVector* live = ComputeLiveOut(block);
1293
    // Initially consider all live_out values live for the entire block. We
1294
    // will shorten these intervals if necessary.
1295
    AddInitialIntervals(block, live);
1296

    
1297
    // Process the instructions in reverse order, generating and killing
1298
    // live values.
1299
    ProcessInstructions(block, live);
1300
    // All phi output operands are killed by this block.
1301
    const ZoneList<HPhi*>* phis = block->phis();
1302
    for (int i = 0; i < phis->length(); ++i) {
1303
      // The live range interval already ends at the first instruction of the
1304
      // block.
1305
      HPhi* phi = phis->at(i);
1306
      live->Remove(phi->id());
1307

    
1308
      LOperand* hint = NULL;
1309
      LOperand* phi_operand = NULL;
1310
      LGap* gap = GetLastGap(phi->block()->predecessors()->at(0));
1311
      LParallelMove* move = gap->GetOrCreateParallelMove(LGap::START,
1312
                                                         chunk()->zone());
1313
      for (int j = 0; j < move->move_operands()->length(); ++j) {
1314
        LOperand* to = move->move_operands()->at(j).destination();
1315
        if (to->IsUnallocated() &&
1316
            LUnallocated::cast(to)->virtual_register() == phi->id()) {
1317
          hint = move->move_operands()->at(j).source();
1318
          phi_operand = to;
1319
          break;
1320
        }
1321
      }
1322
      ASSERT(hint != NULL);
1323

    
1324
      LifetimePosition block_start = LifetimePosition::FromInstructionIndex(
1325
              block->first_instruction_index());
1326
      Define(block_start, phi_operand, hint);
1327
    }
1328

    
1329
    // Now live is live_in for this block except not including values live
1330
    // out on backward successor edges.
1331
    live_in_sets_[block_id] = live;
1332

    
1333
    // If this block is a loop header go back and patch up the necessary
1334
    // predecessor blocks.
1335
    if (block->IsLoopHeader()) {
1336
      // TODO(kmillikin): Need to be able to get the last block of the loop
1337
      // in the loop information. Add a live range stretching from the first
1338
      // loop instruction to the last for each value live on entry to the
1339
      // header.
1340
      HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1341
      BitVector::Iterator iterator(live);
1342
      LifetimePosition start = LifetimePosition::FromInstructionIndex(
1343
          block->first_instruction_index());
1344
      LifetimePosition end = LifetimePosition::FromInstructionIndex(
1345
          back_edge->last_instruction_index()).NextInstruction();
1346
      while (!iterator.Done()) {
1347
        int operand_index = iterator.Current();
1348
        LiveRange* range = LiveRangeFor(operand_index);
1349
        range->EnsureInterval(start, end, zone());
1350
        iterator.Advance();
1351
      }
1352

    
1353
      for (int i = block->block_id() + 1; i <= back_edge->block_id(); ++i) {
1354
        live_in_sets_[i]->Union(*live);
1355
      }
1356
    }
1357

    
1358
#ifdef DEBUG
1359
    if (block_id == 0) {
1360
      BitVector::Iterator iterator(live);
1361
      bool found = false;
1362
      while (!iterator.Done()) {
1363
        found = true;
1364
        int operand_index = iterator.Current();
1365
        if (chunk_->info()->IsStub()) {
1366
          CodeStub::Major major_key = chunk_->info()->code_stub()->MajorKey();
1367
          PrintF("Function: %s\n", CodeStub::MajorName(major_key, false));
1368
        } else {
1369
          ASSERT(chunk_->info()->IsOptimizing());
1370
          AllowHandleDereference allow_deref;
1371
          PrintF("Function: %s\n",
1372
                 *chunk_->info()->function()->debug_name()->ToCString());
1373
        }
1374
        PrintF("Value %d used before first definition!\n", operand_index);
1375
        LiveRange* range = LiveRangeFor(operand_index);
1376
        PrintF("First use is at %d\n", range->first_pos()->pos().Value());
1377
        iterator.Advance();
1378
      }
1379
      ASSERT(!found);
1380
    }
1381
#endif
1382
  }
1383

    
1384
  for (int i = 0; i < live_ranges_.length(); ++i) {
1385
    if (live_ranges_[i] != NULL) {
1386
      live_ranges_[i]->kind_ = RequiredRegisterKind(live_ranges_[i]->id());
1387
    }
1388
  }
1389
}
1390

    
1391

    
1392
bool LAllocator::SafePointsAreInOrder() const {
1393
  const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps();
1394
  int safe_point = 0;
1395
  for (int i = 0; i < pointer_maps->length(); ++i) {
1396
    LPointerMap* map = pointer_maps->at(i);
1397
    if (safe_point > map->lithium_position()) return false;
1398
    safe_point = map->lithium_position();
1399
  }
1400
  return true;
1401
}
1402

    
1403

    
1404
void LAllocator::PopulatePointerMaps() {
1405
  LAllocatorPhase phase("L_Populate pointer maps", this);
1406
  const ZoneList<LPointerMap*>* pointer_maps = chunk_->pointer_maps();
1407

    
1408
  ASSERT(SafePointsAreInOrder());
1409

    
1410
  // Iterate over all safe point positions and record a pointer
1411
  // for all spilled live ranges at this point.
1412
  int first_safe_point_index = 0;
1413
  int last_range_start = 0;
1414
  for (int range_idx = 0; range_idx < live_ranges()->length(); ++range_idx) {
1415
    LiveRange* range = live_ranges()->at(range_idx);
1416
    if (range == NULL) continue;
1417
    // Iterate over the first parts of multi-part live ranges.
1418
    if (range->parent() != NULL) continue;
1419
    // Skip non-pointer values.
1420
    if (!HasTaggedValue(range->id())) continue;
1421
    // Skip empty live ranges.
1422
    if (range->IsEmpty()) continue;
1423

    
1424
    // Find the extent of the range and its children.
1425
    int start = range->Start().InstructionIndex();
1426
    int end = 0;
1427
    for (LiveRange* cur = range; cur != NULL; cur = cur->next()) {
1428
      LifetimePosition this_end = cur->End();
1429
      if (this_end.InstructionIndex() > end) end = this_end.InstructionIndex();
1430
      ASSERT(cur->Start().InstructionIndex() >= start);
1431
    }
1432

    
1433
    // Most of the ranges are in order, but not all.  Keep an eye on when
1434
    // they step backwards and reset the first_safe_point_index so we don't
1435
    // miss any safe points.
1436
    if (start < last_range_start) {
1437
      first_safe_point_index = 0;
1438
    }
1439
    last_range_start = start;
1440

    
1441
    // Step across all the safe points that are before the start of this range,
1442
    // recording how far we step in order to save doing this for the next range.
1443
    while (first_safe_point_index < pointer_maps->length()) {
1444
      LPointerMap* map = pointer_maps->at(first_safe_point_index);
1445
      int safe_point = map->lithium_position();
1446
      if (safe_point >= start) break;
1447
      first_safe_point_index++;
1448
    }
1449

    
1450
    // Step through the safe points to see whether they are in the range.
1451
    for (int safe_point_index = first_safe_point_index;
1452
         safe_point_index < pointer_maps->length();
1453
         ++safe_point_index) {
1454
      LPointerMap* map = pointer_maps->at(safe_point_index);
1455
      int safe_point = map->lithium_position();
1456

    
1457
      // The safe points are sorted so we can stop searching here.
1458
      if (safe_point - 1 > end) break;
1459

    
1460
      // Advance to the next active range that covers the current
1461
      // safe point position.
1462
      LifetimePosition safe_point_pos =
1463
          LifetimePosition::FromInstructionIndex(safe_point);
1464
      LiveRange* cur = range;
1465
      while (cur != NULL && !cur->Covers(safe_point_pos)) {
1466
        cur = cur->next();
1467
      }
1468
      if (cur == NULL) continue;
1469

    
1470
      // Check if the live range is spilled and the safe point is after
1471
      // the spill position.
1472
      if (range->HasAllocatedSpillOperand() &&
1473
          safe_point >= range->spill_start_index()) {
1474
        TraceAlloc("Pointer for range %d (spilled at %d) at safe point %d\n",
1475
                   range->id(), range->spill_start_index(), safe_point);
1476
        map->RecordPointer(range->GetSpillOperand(), chunk()->zone());
1477
      }
1478

    
1479
      if (!cur->IsSpilled()) {
1480
        TraceAlloc("Pointer in register for range %d (start at %d) "
1481
                   "at safe point %d\n",
1482
                   cur->id(), cur->Start().Value(), safe_point);
1483
        LOperand* operand = cur->CreateAssignedOperand(chunk()->zone());
1484
        ASSERT(!operand->IsStackSlot());
1485
        map->RecordPointer(operand, chunk()->zone());
1486
      }
1487
    }
1488
  }
1489
}
1490

    
1491

    
1492
void LAllocator::AllocateGeneralRegisters() {
1493
  LAllocatorPhase phase("L_Allocate general registers", this);
1494
  num_registers_ = Register::NumAllocatableRegisters();
1495
  mode_ = GENERAL_REGISTERS;
1496
  AllocateRegisters();
1497
}
1498

    
1499

    
1500
void LAllocator::AllocateDoubleRegisters() {
1501
  LAllocatorPhase phase("L_Allocate double registers", this);
1502
  num_registers_ = DoubleRegister::NumAllocatableRegisters();
1503
  mode_ = DOUBLE_REGISTERS;
1504
  AllocateRegisters();
1505
}
1506

    
1507

    
1508
void LAllocator::AllocateRegisters() {
1509
  ASSERT(unhandled_live_ranges_.is_empty());
1510

    
1511
  for (int i = 0; i < live_ranges_.length(); ++i) {
1512
    if (live_ranges_[i] != NULL) {
1513
      if (live_ranges_[i]->Kind() == mode_) {
1514
        AddToUnhandledUnsorted(live_ranges_[i]);
1515
      }
1516
    }
1517
  }
1518
  SortUnhandled();
1519
  ASSERT(UnhandledIsSorted());
1520

    
1521
  ASSERT(reusable_slots_.is_empty());
1522
  ASSERT(active_live_ranges_.is_empty());
1523
  ASSERT(inactive_live_ranges_.is_empty());
1524

    
1525
  if (mode_ == DOUBLE_REGISTERS) {
1526
    for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
1527
      LiveRange* current = fixed_double_live_ranges_.at(i);
1528
      if (current != NULL) {
1529
        AddToInactive(current);
1530
      }
1531
    }
1532
  } else {
1533
    ASSERT(mode_ == GENERAL_REGISTERS);
1534
    for (int i = 0; i < fixed_live_ranges_.length(); ++i) {
1535
      LiveRange* current = fixed_live_ranges_.at(i);
1536
      if (current != NULL) {
1537
        AddToInactive(current);
1538
      }
1539
    }
1540
  }
1541

    
1542
  while (!unhandled_live_ranges_.is_empty()) {
1543
    ASSERT(UnhandledIsSorted());
1544
    LiveRange* current = unhandled_live_ranges_.RemoveLast();
1545
    ASSERT(UnhandledIsSorted());
1546
    LifetimePosition position = current->Start();
1547
#ifdef DEBUG
1548
    allocation_finger_ = position;
1549
#endif
1550
    TraceAlloc("Processing interval %d start=%d\n",
1551
               current->id(),
1552
               position.Value());
1553

    
1554
    if (current->HasAllocatedSpillOperand()) {
1555
      TraceAlloc("Live range %d already has a spill operand\n", current->id());
1556
      LifetimePosition next_pos = position;
1557
      if (IsGapAt(next_pos.InstructionIndex())) {
1558
        next_pos = next_pos.NextInstruction();
1559
      }
1560
      UsePosition* pos = current->NextUsePositionRegisterIsBeneficial(next_pos);
1561
      // If the range already has a spill operand and it doesn't need a
1562
      // register immediately, split it and spill the first part of the range.
1563
      if (pos == NULL) {
1564
        Spill(current);
1565
        continue;
1566
      } else if (pos->pos().Value() >
1567
                 current->Start().NextInstruction().Value()) {
1568
        // Do not spill live range eagerly if use position that can benefit from
1569
        // the register is too close to the start of live range.
1570
        SpillBetween(current, current->Start(), pos->pos());
1571
        if (!AllocationOk()) return;
1572
        ASSERT(UnhandledIsSorted());
1573
        continue;
1574
      }
1575
    }
1576

    
1577
    for (int i = 0; i < active_live_ranges_.length(); ++i) {
1578
      LiveRange* cur_active = active_live_ranges_.at(i);
1579
      if (cur_active->End().Value() <= position.Value()) {
1580
        ActiveToHandled(cur_active);
1581
        --i;  // The live range was removed from the list of active live ranges.
1582
      } else if (!cur_active->Covers(position)) {
1583
        ActiveToInactive(cur_active);
1584
        --i;  // The live range was removed from the list of active live ranges.
1585
      }
1586
    }
1587

    
1588
    for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1589
      LiveRange* cur_inactive = inactive_live_ranges_.at(i);
1590
      if (cur_inactive->End().Value() <= position.Value()) {
1591
        InactiveToHandled(cur_inactive);
1592
        --i;  // Live range was removed from the list of inactive live ranges.
1593
      } else if (cur_inactive->Covers(position)) {
1594
        InactiveToActive(cur_inactive);
1595
        --i;  // Live range was removed from the list of inactive live ranges.
1596
      }
1597
    }
1598

    
1599
    ASSERT(!current->HasRegisterAssigned() && !current->IsSpilled());
1600

    
1601
    bool result = TryAllocateFreeReg(current);
1602
    if (!AllocationOk()) return;
1603

    
1604
    if (!result) AllocateBlockedReg(current);
1605
    if (!AllocationOk()) return;
1606

    
1607
    if (current->HasRegisterAssigned()) {
1608
      AddToActive(current);
1609
    }
1610
  }
1611

    
1612
  reusable_slots_.Rewind(0);
1613
  active_live_ranges_.Rewind(0);
1614
  inactive_live_ranges_.Rewind(0);
1615
}
1616

    
1617

    
1618
const char* LAllocator::RegisterName(int allocation_index) {
1619
  if (mode_ == GENERAL_REGISTERS) {
1620
    return Register::AllocationIndexToString(allocation_index);
1621
  } else {
1622
    return DoubleRegister::AllocationIndexToString(allocation_index);
1623
  }
1624
}
1625

    
1626

    
1627
void LAllocator::TraceAlloc(const char* msg, ...) {
1628
  if (FLAG_trace_alloc) {
1629
    va_list arguments;
1630
    va_start(arguments, msg);
1631
    OS::VPrint(msg, arguments);
1632
    va_end(arguments);
1633
  }
1634
}
1635

    
1636

    
1637
bool LAllocator::HasTaggedValue(int virtual_register) const {
1638
  HValue* value = graph_->LookupValue(virtual_register);
1639
  if (value == NULL) return false;
1640
  return value->representation().IsTagged() && !value->type().IsSmi();
1641
}
1642

    
1643

    
1644
RegisterKind LAllocator::RequiredRegisterKind(int virtual_register) const {
1645
  if (virtual_register < first_artificial_register_) {
1646
    HValue* value = graph_->LookupValue(virtual_register);
1647
    if (value != NULL && value->representation().IsDouble()) {
1648
      return DOUBLE_REGISTERS;
1649
    }
1650
  } else if (double_artificial_registers_.Contains(
1651
      virtual_register - first_artificial_register_)) {
1652
    return DOUBLE_REGISTERS;
1653
  }
1654

    
1655
  return GENERAL_REGISTERS;
1656
}
1657

    
1658

    
1659
void LAllocator::AddToActive(LiveRange* range) {
1660
  TraceAlloc("Add live range %d to active\n", range->id());
1661
  active_live_ranges_.Add(range, zone());
1662
}
1663

    
1664

    
1665
void LAllocator::AddToInactive(LiveRange* range) {
1666
  TraceAlloc("Add live range %d to inactive\n", range->id());
1667
  inactive_live_ranges_.Add(range, zone());
1668
}
1669

    
1670

    
1671
void LAllocator::AddToUnhandledSorted(LiveRange* range) {
1672
  if (range == NULL || range->IsEmpty()) return;
1673
  ASSERT(!range->HasRegisterAssigned() && !range->IsSpilled());
1674
  ASSERT(allocation_finger_.Value() <= range->Start().Value());
1675
  for (int i = unhandled_live_ranges_.length() - 1; i >= 0; --i) {
1676
    LiveRange* cur_range = unhandled_live_ranges_.at(i);
1677
    if (range->ShouldBeAllocatedBefore(cur_range)) {
1678
      TraceAlloc("Add live range %d to unhandled at %d\n", range->id(), i + 1);
1679
      unhandled_live_ranges_.InsertAt(i + 1, range, zone());
1680
      ASSERT(UnhandledIsSorted());
1681
      return;
1682
    }
1683
  }
1684
  TraceAlloc("Add live range %d to unhandled at start\n", range->id());
1685
  unhandled_live_ranges_.InsertAt(0, range, zone());
1686
  ASSERT(UnhandledIsSorted());
1687
}
1688

    
1689

    
1690
void LAllocator::AddToUnhandledUnsorted(LiveRange* range) {
1691
  if (range == NULL || range->IsEmpty()) return;
1692
  ASSERT(!range->HasRegisterAssigned() && !range->IsSpilled());
1693
  TraceAlloc("Add live range %d to unhandled unsorted at end\n", range->id());
1694
  unhandled_live_ranges_.Add(range, zone());
1695
}
1696

    
1697

    
1698
static int UnhandledSortHelper(LiveRange* const* a, LiveRange* const* b) {
1699
  ASSERT(!(*a)->ShouldBeAllocatedBefore(*b) ||
1700
         !(*b)->ShouldBeAllocatedBefore(*a));
1701
  if ((*a)->ShouldBeAllocatedBefore(*b)) return 1;
1702
  if ((*b)->ShouldBeAllocatedBefore(*a)) return -1;
1703
  return (*a)->id() - (*b)->id();
1704
}
1705

    
1706

    
1707
// Sort the unhandled live ranges so that the ranges to be processed first are
1708
// at the end of the array list.  This is convenient for the register allocation
1709
// algorithm because it is efficient to remove elements from the end.
1710
void LAllocator::SortUnhandled() {
1711
  TraceAlloc("Sort unhandled\n");
1712
  unhandled_live_ranges_.Sort(&UnhandledSortHelper);
1713
}
1714

    
1715

    
1716
bool LAllocator::UnhandledIsSorted() {
1717
  int len = unhandled_live_ranges_.length();
1718
  for (int i = 1; i < len; i++) {
1719
    LiveRange* a = unhandled_live_ranges_.at(i - 1);
1720
    LiveRange* b = unhandled_live_ranges_.at(i);
1721
    if (a->Start().Value() < b->Start().Value()) return false;
1722
  }
1723
  return true;
1724
}
1725

    
1726

    
1727
void LAllocator::FreeSpillSlot(LiveRange* range) {
1728
  // Check that we are the last range.
1729
  if (range->next() != NULL) return;
1730

    
1731
  if (!range->TopLevel()->HasAllocatedSpillOperand()) return;
1732

    
1733
  int index = range->TopLevel()->GetSpillOperand()->index();
1734
  if (index >= 0) {
1735
    reusable_slots_.Add(range, zone());
1736
  }
1737
}
1738

    
1739

    
1740
LOperand* LAllocator::TryReuseSpillSlot(LiveRange* range) {
1741
  if (reusable_slots_.is_empty()) return NULL;
1742
  if (reusable_slots_.first()->End().Value() >
1743
      range->TopLevel()->Start().Value()) {
1744
    return NULL;
1745
  }
1746
  LOperand* result = reusable_slots_.first()->TopLevel()->GetSpillOperand();
1747
  reusable_slots_.Remove(0);
1748
  return result;
1749
}
1750

    
1751

    
1752
void LAllocator::ActiveToHandled(LiveRange* range) {
1753
  ASSERT(active_live_ranges_.Contains(range));
1754
  active_live_ranges_.RemoveElement(range);
1755
  TraceAlloc("Moving live range %d from active to handled\n", range->id());
1756
  FreeSpillSlot(range);
1757
}
1758

    
1759

    
1760
void LAllocator::ActiveToInactive(LiveRange* range) {
1761
  ASSERT(active_live_ranges_.Contains(range));
1762
  active_live_ranges_.RemoveElement(range);
1763
  inactive_live_ranges_.Add(range, zone());
1764
  TraceAlloc("Moving live range %d from active to inactive\n", range->id());
1765
}
1766

    
1767

    
1768
void LAllocator::InactiveToHandled(LiveRange* range) {
1769
  ASSERT(inactive_live_ranges_.Contains(range));
1770
  inactive_live_ranges_.RemoveElement(range);
1771
  TraceAlloc("Moving live range %d from inactive to handled\n", range->id());
1772
  FreeSpillSlot(range);
1773
}
1774

    
1775

    
1776
void LAllocator::InactiveToActive(LiveRange* range) {
1777
  ASSERT(inactive_live_ranges_.Contains(range));
1778
  inactive_live_ranges_.RemoveElement(range);
1779
  active_live_ranges_.Add(range, zone());
1780
  TraceAlloc("Moving live range %d from inactive to active\n", range->id());
1781
}
1782

    
1783

    
1784
// TryAllocateFreeReg and AllocateBlockedReg assume this
1785
// when allocating local arrays.
1786
STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >=
1787
              Register::kMaxNumAllocatableRegisters);
1788

    
1789

    
1790
bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
1791
  LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters];
1792

    
1793
  for (int i = 0; i < num_registers_; i++) {
1794
    free_until_pos[i] = LifetimePosition::MaxPosition();
1795
  }
1796

    
1797
  for (int i = 0; i < active_live_ranges_.length(); ++i) {
1798
    LiveRange* cur_active = active_live_ranges_.at(i);
1799
    free_until_pos[cur_active->assigned_register()] =
1800
        LifetimePosition::FromInstructionIndex(0);
1801
  }
1802

    
1803
  for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1804
    LiveRange* cur_inactive = inactive_live_ranges_.at(i);
1805
    ASSERT(cur_inactive->End().Value() > current->Start().Value());
1806
    LifetimePosition next_intersection =
1807
        cur_inactive->FirstIntersection(current);
1808
    if (!next_intersection.IsValid()) continue;
1809
    int cur_reg = cur_inactive->assigned_register();
1810
    free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
1811
  }
1812

    
1813
  LOperand* hint = current->FirstHint();
1814
  if (hint != NULL && (hint->IsRegister() || hint->IsDoubleRegister())) {
1815
    int register_index = hint->index();
1816
    TraceAlloc(
1817
        "Found reg hint %s (free until [%d) for live range %d (end %d[).\n",
1818
        RegisterName(register_index),
1819
        free_until_pos[register_index].Value(),
1820
        current->id(),
1821
        current->End().Value());
1822

    
1823
    // The desired register is free until the end of the current live range.
1824
    if (free_until_pos[register_index].Value() >= current->End().Value()) {
1825
      TraceAlloc("Assigning preferred reg %s to live range %d\n",
1826
                 RegisterName(register_index),
1827
                 current->id());
1828
      SetLiveRangeAssignedRegister(current, register_index);
1829
      return true;
1830
    }
1831
  }
1832

    
1833
  // Find the register which stays free for the longest time.
1834
  int reg = 0;
1835
  for (int i = 1; i < RegisterCount(); ++i) {
1836
    if (free_until_pos[i].Value() > free_until_pos[reg].Value()) {
1837
      reg = i;
1838
    }
1839
  }
1840

    
1841
  LifetimePosition pos = free_until_pos[reg];
1842

    
1843
  if (pos.Value() <= current->Start().Value()) {
1844
    // All registers are blocked.
1845
    return false;
1846
  }
1847

    
1848
  if (pos.Value() < current->End().Value()) {
1849
    // Register reg is available at the range start but becomes blocked before
1850
    // the range end. Split current at position where it becomes blocked.
1851
    LiveRange* tail = SplitRangeAt(current, pos);
1852
    if (!AllocationOk()) return false;
1853
    AddToUnhandledSorted(tail);
1854
  }
1855

    
1856

    
1857
  // Register reg is available at the range start and is free until
1858
  // the range end.
1859
  ASSERT(pos.Value() >= current->End().Value());
1860
  TraceAlloc("Assigning free reg %s to live range %d\n",
1861
             RegisterName(reg),
1862
             current->id());
1863
  SetLiveRangeAssignedRegister(current, reg);
1864

    
1865
  return true;
1866
}
1867

    
1868

    
1869
void LAllocator::AllocateBlockedReg(LiveRange* current) {
1870
  UsePosition* register_use = current->NextRegisterPosition(current->Start());
1871
  if (register_use == NULL) {
1872
    // There is no use in the current live range that requires a register.
1873
    // We can just spill it.
1874
    Spill(current);
1875
    return;
1876
  }
1877

    
1878

    
1879
  LifetimePosition use_pos[DoubleRegister::kMaxNumAllocatableRegisters];
1880
  LifetimePosition block_pos[DoubleRegister::kMaxNumAllocatableRegisters];
1881

    
1882
  for (int i = 0; i < num_registers_; i++) {
1883
    use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
1884
  }
1885

    
1886
  for (int i = 0; i < active_live_ranges_.length(); ++i) {
1887
    LiveRange* range = active_live_ranges_[i];
1888
    int cur_reg = range->assigned_register();
1889
    if (range->IsFixed() || !range->CanBeSpilled(current->Start())) {
1890
      block_pos[cur_reg] = use_pos[cur_reg] =
1891
          LifetimePosition::FromInstructionIndex(0);
1892
    } else {
1893
      UsePosition* next_use = range->NextUsePositionRegisterIsBeneficial(
1894
          current->Start());
1895
      if (next_use == NULL) {
1896
        use_pos[cur_reg] = range->End();
1897
      } else {
1898
        use_pos[cur_reg] = next_use->pos();
1899
      }
1900
    }
1901
  }
1902

    
1903
  for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
1904
    LiveRange* range = inactive_live_ranges_.at(i);
1905
    ASSERT(range->End().Value() > current->Start().Value());
1906
    LifetimePosition next_intersection = range->FirstIntersection(current);
1907
    if (!next_intersection.IsValid()) continue;
1908
    int cur_reg = range->assigned_register();
1909
    if (range->IsFixed()) {
1910
      block_pos[cur_reg] = Min(block_pos[cur_reg], next_intersection);
1911
      use_pos[cur_reg] = Min(block_pos[cur_reg], use_pos[cur_reg]);
1912
    } else {
1913
      use_pos[cur_reg] = Min(use_pos[cur_reg], next_intersection);
1914
    }
1915
  }
1916

    
1917
  int reg = 0;
1918
  for (int i = 1; i < RegisterCount(); ++i) {
1919
    if (use_pos[i].Value() > use_pos[reg].Value()) {
1920
      reg = i;
1921
    }
1922
  }
1923

    
1924
  LifetimePosition pos = use_pos[reg];
1925

    
1926
  if (pos.Value() < register_use->pos().Value()) {
1927
    // All registers are blocked before the first use that requires a register.
1928
    // Spill starting part of live range up to that use.
1929
    SpillBetween(current, current->Start(), register_use->pos());
1930
    return;
1931
  }
1932

    
1933
  if (block_pos[reg].Value() < current->End().Value()) {
1934
    // Register becomes blocked before the current range end. Split before that
1935
    // position.
1936
    LiveRange* tail = SplitBetween(current,
1937
                                   current->Start(),
1938
                                   block_pos[reg].InstructionStart());
1939
    if (!AllocationOk()) return;
1940
    AddToUnhandledSorted(tail);
1941
  }
1942

    
1943
  // Register reg is not blocked for the whole range.
1944
  ASSERT(block_pos[reg].Value() >= current->End().Value());
1945
  TraceAlloc("Assigning blocked reg %s to live range %d\n",
1946
             RegisterName(reg),
1947
             current->id());
1948
  SetLiveRangeAssignedRegister(current, reg);
1949

    
1950
  // This register was not free. Thus we need to find and spill
1951
  // parts of active and inactive live regions that use the same register
1952
  // at the same lifetime positions as current.
1953
  SplitAndSpillIntersecting(current);
1954
}
1955

    
1956

    
1957
LifetimePosition LAllocator::FindOptimalSpillingPos(LiveRange* range,
1958
                                                    LifetimePosition pos) {
1959
  HBasicBlock* block = GetBlock(pos.InstructionStart());
1960
  HBasicBlock* loop_header =
1961
      block->IsLoopHeader() ? block : block->parent_loop_header();
1962

    
1963
  if (loop_header == NULL) return pos;
1964

    
1965
  UsePosition* prev_use =
1966
    range->PreviousUsePositionRegisterIsBeneficial(pos);
1967

    
1968
  while (loop_header != NULL) {
1969
    // We are going to spill live range inside the loop.
1970
    // If possible try to move spilling position backwards to loop header.
1971
    // This will reduce number of memory moves on the back edge.
1972
    LifetimePosition loop_start = LifetimePosition::FromInstructionIndex(
1973
        loop_header->first_instruction_index());
1974

    
1975
    if (range->Covers(loop_start)) {
1976
      if (prev_use == NULL || prev_use->pos().Value() < loop_start.Value()) {
1977
        // No register beneficial use inside the loop before the pos.
1978
        pos = loop_start;
1979
      }
1980
    }
1981

    
1982
    // Try hoisting out to an outer loop.
1983
    loop_header = loop_header->parent_loop_header();
1984
  }
1985

    
1986
  return pos;
1987
}
1988

    
1989

    
1990
void LAllocator::SplitAndSpillIntersecting(LiveRange* current) {
1991
  ASSERT(current->HasRegisterAssigned());
1992
  int reg = current->assigned_register();
1993
  LifetimePosition split_pos = current->Start();
1994
  for (int i = 0; i < active_live_ranges_.length(); ++i) {
1995
    LiveRange* range = active_live_ranges_[i];
1996
    if (range->assigned_register() == reg) {
1997
      UsePosition* next_pos = range->NextRegisterPosition(current->Start());
1998
      LifetimePosition spill_pos = FindOptimalSpillingPos(range, split_pos);
1999
      if (next_pos == NULL) {
2000
        SpillAfter(range, spill_pos);
2001
      } else {
2002
        // When spilling between spill_pos and next_pos ensure that the range
2003
        // remains spilled at least until the start of the current live range.
2004
        // This guarantees that we will not introduce new unhandled ranges that
2005
        // start before the current range as this violates allocation invariant
2006
        // and will lead to an inconsistent state of active and inactive
2007
        // live-ranges: ranges are allocated in order of their start positions,
2008
        // ranges are retired from active/inactive when the start of the
2009
        // current live-range is larger than their end.
2010
        SpillBetweenUntil(range, spill_pos, current->Start(), next_pos->pos());
2011
      }
2012
      if (!AllocationOk()) return;
2013
      ActiveToHandled(range);
2014
      --i;
2015
    }
2016
  }
2017

    
2018
  for (int i = 0; i < inactive_live_ranges_.length(); ++i) {
2019
    LiveRange* range = inactive_live_ranges_[i];
2020
    ASSERT(range->End().Value() > current->Start().Value());
2021
    if (range->assigned_register() == reg && !range->IsFixed()) {
2022
      LifetimePosition next_intersection = range->FirstIntersection(current);
2023
      if (next_intersection.IsValid()) {
2024
        UsePosition* next_pos = range->NextRegisterPosition(current->Start());
2025
        if (next_pos == NULL) {
2026
          SpillAfter(range, split_pos);
2027
        } else {
2028
          next_intersection = Min(next_intersection, next_pos->pos());
2029
          SpillBetween(range, split_pos, next_intersection);
2030
        }
2031
        if (!AllocationOk()) return;
2032
        InactiveToHandled(range);
2033
        --i;
2034
      }
2035
    }
2036
  }
2037
}
2038

    
2039

    
2040
bool LAllocator::IsBlockBoundary(LifetimePosition pos) {
2041
  return pos.IsInstructionStart() &&
2042
      InstructionAt(pos.InstructionIndex())->IsLabel();
2043
}
2044

    
2045

    
2046
LiveRange* LAllocator::SplitRangeAt(LiveRange* range, LifetimePosition pos) {
2047
  ASSERT(!range->IsFixed());
2048
  TraceAlloc("Splitting live range %d at %d\n", range->id(), pos.Value());
2049

    
2050
  if (pos.Value() <= range->Start().Value()) return range;
2051

    
2052
  // We can't properly connect liveranges if split occured at the end
2053
  // of control instruction.
2054
  ASSERT(pos.IsInstructionStart() ||
2055
         !chunk_->instructions()->at(pos.InstructionIndex())->IsControl());
2056

    
2057
  int vreg = GetVirtualRegister();
2058
  if (!AllocationOk()) return NULL;
2059
  LiveRange* result = LiveRangeFor(vreg);
2060
  range->SplitAt(pos, result, zone());
2061
  return result;
2062
}
2063

    
2064

    
2065
LiveRange* LAllocator::SplitBetween(LiveRange* range,
2066
                                    LifetimePosition start,
2067
                                    LifetimePosition end) {
2068
  ASSERT(!range->IsFixed());
2069
  TraceAlloc("Splitting live range %d in position between [%d, %d]\n",
2070
             range->id(),
2071
             start.Value(),
2072
             end.Value());
2073

    
2074
  LifetimePosition split_pos = FindOptimalSplitPos(start, end);
2075
  ASSERT(split_pos.Value() >= start.Value());
2076
  return SplitRangeAt(range, split_pos);
2077
}
2078

    
2079

    
2080
LifetimePosition LAllocator::FindOptimalSplitPos(LifetimePosition start,
2081
                                                 LifetimePosition end) {
2082
  int start_instr = start.InstructionIndex();
2083
  int end_instr = end.InstructionIndex();
2084
  ASSERT(start_instr <= end_instr);
2085

    
2086
  // We have no choice
2087
  if (start_instr == end_instr) return end;
2088

    
2089
  HBasicBlock* start_block = GetBlock(start);
2090
  HBasicBlock* end_block = GetBlock(end);
2091

    
2092
  if (end_block == start_block) {
2093
    // The interval is split in the same basic block. Split at the latest
2094
    // possible position.
2095
    return end;
2096
  }
2097

    
2098
  HBasicBlock* block = end_block;
2099
  // Find header of outermost loop.
2100
  while (block->parent_loop_header() != NULL &&
2101
      block->parent_loop_header()->block_id() > start_block->block_id()) {
2102
    block = block->parent_loop_header();
2103
  }
2104

    
2105
  // We did not find any suitable outer loop. Split at the latest possible
2106
  // position unless end_block is a loop header itself.
2107
  if (block == end_block && !end_block->IsLoopHeader()) return end;
2108

    
2109
  return LifetimePosition::FromInstructionIndex(
2110
      block->first_instruction_index());
2111
}
2112

    
2113

    
2114
void LAllocator::SpillAfter(LiveRange* range, LifetimePosition pos) {
2115
  LiveRange* second_part = SplitRangeAt(range, pos);
2116
  if (!AllocationOk()) return;
2117
  Spill(second_part);
2118
}
2119

    
2120

    
2121
void LAllocator::SpillBetween(LiveRange* range,
2122
                              LifetimePosition start,
2123
                              LifetimePosition end) {
2124
  SpillBetweenUntil(range, start, start, end);
2125
}
2126

    
2127

    
2128
void LAllocator::SpillBetweenUntil(LiveRange* range,
2129
                                   LifetimePosition start,
2130
                                   LifetimePosition until,
2131
                                   LifetimePosition end) {
2132
  CHECK(start.Value() < end.Value());
2133
  LiveRange* second_part = SplitRangeAt(range, start);
2134
  if (!AllocationOk()) return;
2135

    
2136
  if (second_part->Start().Value() < end.Value()) {
2137
    // The split result intersects with [start, end[.
2138
    // Split it at position between ]start+1, end[, spill the middle part
2139
    // and put the rest to unhandled.
2140
    LiveRange* third_part = SplitBetween(
2141
        second_part,
2142
        Max(second_part->Start().InstructionEnd(), until),
2143
        end.PrevInstruction().InstructionEnd());
2144
    if (!AllocationOk()) return;
2145

    
2146
    ASSERT(third_part != second_part);
2147

    
2148
    Spill(second_part);
2149
    AddToUnhandledSorted(third_part);
2150
  } else {
2151
    // The split result does not intersect with [start, end[.
2152
    // Nothing to spill. Just put it to unhandled as whole.
2153
    AddToUnhandledSorted(second_part);
2154
  }
2155
}
2156

    
2157

    
2158
void LAllocator::Spill(LiveRange* range) {
2159
  ASSERT(!range->IsSpilled());
2160
  TraceAlloc("Spilling live range %d\n", range->id());
2161
  LiveRange* first = range->TopLevel();
2162

    
2163
  if (!first->HasAllocatedSpillOperand()) {
2164
    LOperand* op = TryReuseSpillSlot(range);
2165
    if (op == NULL) op = chunk_->GetNextSpillSlot(range->Kind());
2166
    first->SetSpillOperand(op);
2167
  }
2168
  range->MakeSpilled(chunk()->zone());
2169
}
2170

    
2171

    
2172
int LAllocator::RegisterCount() const {
2173
  return num_registers_;
2174
}
2175

    
2176

    
2177
#ifdef DEBUG
2178

    
2179

    
2180
void LAllocator::Verify() const {
2181
  for (int i = 0; i < live_ranges()->length(); ++i) {
2182
    LiveRange* current = live_ranges()->at(i);
2183
    if (current != NULL) current->Verify();
2184
  }
2185
}
2186

    
2187

    
2188
#endif
2189

    
2190

    
2191
LAllocatorPhase::LAllocatorPhase(const char* name, LAllocator* allocator)
2192
    : CompilationPhase(name, allocator->graph()->info()),
2193
      allocator_(allocator) {
2194
  if (FLAG_hydrogen_stats) {
2195
    allocator_zone_start_allocation_size_ =
2196
        allocator->zone()->allocation_size();
2197
  }
2198
}
2199

    
2200

    
2201
LAllocatorPhase::~LAllocatorPhase() {
2202
  if (FLAG_hydrogen_stats) {
2203
    unsigned size = allocator_->zone()->allocation_size() -
2204
                    allocator_zone_start_allocation_size_;
2205
    isolate()->GetHStatistics()->SaveTiming(name(), TimeDelta(), size);
2206
  }
2207

    
2208
  if (ShouldProduceTraceOutput()) {
2209
    isolate()->GetHTracer()->TraceLithium(name(), allocator_->chunk());
2210
    isolate()->GetHTracer()->TraceLiveRanges(name(), allocator_);
2211
  }
2212

    
2213
#ifdef DEBUG
2214
  if (allocator_ != NULL) allocator_->Verify();
2215
#endif
2216
}
2217

    
2218

    
2219
} }  // namespace v8::internal