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 / hydrogen-instructions.cc @ f230a1cf

History | View | Annotate | Download (129 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

    
30
#include "double.h"
31
#include "factory.h"
32
#include "hydrogen-infer-representation.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 Unsupported target architecture.
44
#endif
45

    
46
namespace v8 {
47
namespace internal {
48

    
49
#define DEFINE_COMPILE(type)                                         \
50
  LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) {  \
51
    return builder->Do##type(this);                                  \
52
  }
53
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
54
#undef DEFINE_COMPILE
55

    
56

    
57
int HValue::LoopWeight() const {
58
  const int w = FLAG_loop_weight;
59
  static const int weights[] = { 1, w, w*w, w*w*w, w*w*w*w };
60
  return weights[Min(block()->LoopNestingDepth(),
61
                     static_cast<int>(ARRAY_SIZE(weights)-1))];
62
}
63

    
64

    
65
Isolate* HValue::isolate() const {
66
  ASSERT(block() != NULL);
67
  return block()->isolate();
68
}
69

    
70

    
71
void HValue::AssumeRepresentation(Representation r) {
72
  if (CheckFlag(kFlexibleRepresentation)) {
73
    ChangeRepresentation(r);
74
    // The representation of the value is dictated by type feedback and
75
    // will not be changed later.
76
    ClearFlag(kFlexibleRepresentation);
77
  }
78
}
79

    
80

    
81
void HValue::InferRepresentation(HInferRepresentationPhase* h_infer) {
82
  ASSERT(CheckFlag(kFlexibleRepresentation));
83
  Representation new_rep = RepresentationFromInputs();
84
  UpdateRepresentation(new_rep, h_infer, "inputs");
85
  new_rep = RepresentationFromUses();
86
  UpdateRepresentation(new_rep, h_infer, "uses");
87
  if (representation().IsSmi() && HasNonSmiUse()) {
88
    UpdateRepresentation(
89
        Representation::Integer32(), h_infer, "use requirements");
90
  }
91
}
92

    
93

    
94
Representation HValue::RepresentationFromUses() {
95
  if (HasNoUses()) return Representation::None();
96

    
97
  // Array of use counts for each representation.
98
  int use_count[Representation::kNumRepresentations] = { 0 };
99

    
100
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
101
    HValue* use = it.value();
102
    Representation rep = use->observed_input_representation(it.index());
103
    if (rep.IsNone()) continue;
104
    if (FLAG_trace_representation) {
105
      PrintF("#%d %s is used by #%d %s as %s%s\n",
106
             id(), Mnemonic(), use->id(), use->Mnemonic(), rep.Mnemonic(),
107
             (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : ""));
108
    }
109
    use_count[rep.kind()] += use->LoopWeight();
110
  }
111
  if (IsPhi()) HPhi::cast(this)->AddIndirectUsesTo(&use_count[0]);
112
  int tagged_count = use_count[Representation::kTagged];
113
  int double_count = use_count[Representation::kDouble];
114
  int int32_count = use_count[Representation::kInteger32];
115
  int smi_count = use_count[Representation::kSmi];
116

    
117
  if (tagged_count > 0) return Representation::Tagged();
118
  if (double_count > 0) return Representation::Double();
119
  if (int32_count > 0) return Representation::Integer32();
120
  if (smi_count > 0) return Representation::Smi();
121

    
122
  return Representation::None();
123
}
124

    
125

    
126
void HValue::UpdateRepresentation(Representation new_rep,
127
                                  HInferRepresentationPhase* h_infer,
128
                                  const char* reason) {
129
  Representation r = representation();
130
  if (new_rep.is_more_general_than(r)) {
131
    if (CheckFlag(kCannotBeTagged) && new_rep.IsTagged()) return;
132
    if (FLAG_trace_representation) {
133
      PrintF("Changing #%d %s representation %s -> %s based on %s\n",
134
             id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason);
135
    }
136
    ChangeRepresentation(new_rep);
137
    AddDependantsToWorklist(h_infer);
138
  }
139
}
140

    
141

    
142
void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
143
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
144
    h_infer->AddToWorklist(it.value());
145
  }
146
  for (int i = 0; i < OperandCount(); ++i) {
147
    h_infer->AddToWorklist(OperandAt(i));
148
  }
149
}
150

    
151

    
152
static int32_t ConvertAndSetOverflow(Representation r,
153
                                     int64_t result,
154
                                     bool* overflow) {
155
  if (r.IsSmi()) {
156
    if (result > Smi::kMaxValue) {
157
      *overflow = true;
158
      return Smi::kMaxValue;
159
    }
160
    if (result < Smi::kMinValue) {
161
      *overflow = true;
162
      return Smi::kMinValue;
163
    }
164
  } else {
165
    if (result > kMaxInt) {
166
      *overflow = true;
167
      return kMaxInt;
168
    }
169
    if (result < kMinInt) {
170
      *overflow = true;
171
      return kMinInt;
172
    }
173
  }
174
  return static_cast<int32_t>(result);
175
}
176

    
177

    
178
static int32_t AddWithoutOverflow(Representation r,
179
                                  int32_t a,
180
                                  int32_t b,
181
                                  bool* overflow) {
182
  int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
183
  return ConvertAndSetOverflow(r, result, overflow);
184
}
185

    
186

    
187
static int32_t SubWithoutOverflow(Representation r,
188
                                  int32_t a,
189
                                  int32_t b,
190
                                  bool* overflow) {
191
  int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
192
  return ConvertAndSetOverflow(r, result, overflow);
193
}
194

    
195

    
196
static int32_t MulWithoutOverflow(const Representation& r,
197
                                  int32_t a,
198
                                  int32_t b,
199
                                  bool* overflow) {
200
  int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
201
  return ConvertAndSetOverflow(r, result, overflow);
202
}
203

    
204

    
205
int32_t Range::Mask() const {
206
  if (lower_ == upper_) return lower_;
207
  if (lower_ >= 0) {
208
    int32_t res = 1;
209
    while (res < upper_) {
210
      res = (res << 1) | 1;
211
    }
212
    return res;
213
  }
214
  return 0xffffffff;
215
}
216

    
217

    
218
void Range::AddConstant(int32_t value) {
219
  if (value == 0) return;
220
  bool may_overflow = false;  // Overflow is ignored here.
221
  Representation r = Representation::Integer32();
222
  lower_ = AddWithoutOverflow(r, lower_, value, &may_overflow);
223
  upper_ = AddWithoutOverflow(r, upper_, value, &may_overflow);
224
#ifdef DEBUG
225
  Verify();
226
#endif
227
}
228

    
229

    
230
void Range::Intersect(Range* other) {
231
  upper_ = Min(upper_, other->upper_);
232
  lower_ = Max(lower_, other->lower_);
233
  bool b = CanBeMinusZero() && other->CanBeMinusZero();
234
  set_can_be_minus_zero(b);
235
}
236

    
237

    
238
void Range::Union(Range* other) {
239
  upper_ = Max(upper_, other->upper_);
240
  lower_ = Min(lower_, other->lower_);
241
  bool b = CanBeMinusZero() || other->CanBeMinusZero();
242
  set_can_be_minus_zero(b);
243
}
244

    
245

    
246
void Range::CombinedMax(Range* other) {
247
  upper_ = Max(upper_, other->upper_);
248
  lower_ = Max(lower_, other->lower_);
249
  set_can_be_minus_zero(CanBeMinusZero() || other->CanBeMinusZero());
250
}
251

    
252

    
253
void Range::CombinedMin(Range* other) {
254
  upper_ = Min(upper_, other->upper_);
255
  lower_ = Min(lower_, other->lower_);
256
  set_can_be_minus_zero(CanBeMinusZero() || other->CanBeMinusZero());
257
}
258

    
259

    
260
void Range::Sar(int32_t value) {
261
  int32_t bits = value & 0x1F;
262
  lower_ = lower_ >> bits;
263
  upper_ = upper_ >> bits;
264
  set_can_be_minus_zero(false);
265
}
266

    
267

    
268
void Range::Shl(int32_t value) {
269
  int32_t bits = value & 0x1F;
270
  int old_lower = lower_;
271
  int old_upper = upper_;
272
  lower_ = lower_ << bits;
273
  upper_ = upper_ << bits;
274
  if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
275
    upper_ = kMaxInt;
276
    lower_ = kMinInt;
277
  }
278
  set_can_be_minus_zero(false);
279
}
280

    
281

    
282
bool Range::AddAndCheckOverflow(const Representation& r, Range* other) {
283
  bool may_overflow = false;
284
  lower_ = AddWithoutOverflow(r, lower_, other->lower(), &may_overflow);
285
  upper_ = AddWithoutOverflow(r, upper_, other->upper(), &may_overflow);
286
  KeepOrder();
287
#ifdef DEBUG
288
  Verify();
289
#endif
290
  return may_overflow;
291
}
292

    
293

    
294
bool Range::SubAndCheckOverflow(const Representation& r, Range* other) {
295
  bool may_overflow = false;
296
  lower_ = SubWithoutOverflow(r, lower_, other->upper(), &may_overflow);
297
  upper_ = SubWithoutOverflow(r, upper_, other->lower(), &may_overflow);
298
  KeepOrder();
299
#ifdef DEBUG
300
  Verify();
301
#endif
302
  return may_overflow;
303
}
304

    
305

    
306
void Range::KeepOrder() {
307
  if (lower_ > upper_) {
308
    int32_t tmp = lower_;
309
    lower_ = upper_;
310
    upper_ = tmp;
311
  }
312
}
313

    
314

    
315
#ifdef DEBUG
316
void Range::Verify() const {
317
  ASSERT(lower_ <= upper_);
318
}
319
#endif
320

    
321

    
322
bool Range::MulAndCheckOverflow(const Representation& r, Range* other) {
323
  bool may_overflow = false;
324
  int v1 = MulWithoutOverflow(r, lower_, other->lower(), &may_overflow);
325
  int v2 = MulWithoutOverflow(r, lower_, other->upper(), &may_overflow);
326
  int v3 = MulWithoutOverflow(r, upper_, other->lower(), &may_overflow);
327
  int v4 = MulWithoutOverflow(r, upper_, other->upper(), &may_overflow);
328
  lower_ = Min(Min(v1, v2), Min(v3, v4));
329
  upper_ = Max(Max(v1, v2), Max(v3, v4));
330
#ifdef DEBUG
331
  Verify();
332
#endif
333
  return may_overflow;
334
}
335

    
336

    
337
const char* HType::ToString() {
338
  // Note: The c1visualizer syntax for locals allows only a sequence of the
339
  // following characters: A-Za-z0-9_-|:
340
  switch (type_) {
341
    case kNone: return "none";
342
    case kTagged: return "tagged";
343
    case kTaggedPrimitive: return "primitive";
344
    case kTaggedNumber: return "number";
345
    case kSmi: return "smi";
346
    case kHeapNumber: return "heap-number";
347
    case kString: return "string";
348
    case kBoolean: return "boolean";
349
    case kNonPrimitive: return "non-primitive";
350
    case kJSArray: return "array";
351
    case kJSObject: return "object";
352
  }
353
  UNREACHABLE();
354
  return "unreachable";
355
}
356

    
357

    
358
HType HType::TypeFromValue(Handle<Object> value) {
359
  HType result = HType::Tagged();
360
  if (value->IsSmi()) {
361
    result = HType::Smi();
362
  } else if (value->IsHeapNumber()) {
363
    result = HType::HeapNumber();
364
  } else if (value->IsString()) {
365
    result = HType::String();
366
  } else if (value->IsBoolean()) {
367
    result = HType::Boolean();
368
  } else if (value->IsJSObject()) {
369
    result = HType::JSObject();
370
  } else if (value->IsJSArray()) {
371
    result = HType::JSArray();
372
  }
373
  return result;
374
}
375

    
376

    
377
bool HValue::IsDefinedAfter(HBasicBlock* other) const {
378
  return block()->block_id() > other->block_id();
379
}
380

    
381

    
382
HUseListNode* HUseListNode::tail() {
383
  // Skip and remove dead items in the use list.
384
  while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) {
385
    tail_ = tail_->tail_;
386
  }
387
  return tail_;
388
}
389

    
390

    
391
bool HValue::CheckUsesForFlag(Flag f) const {
392
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
393
    if (it.value()->IsSimulate()) continue;
394
    if (!it.value()->CheckFlag(f)) return false;
395
  }
396
  return true;
397
}
398

    
399

    
400
bool HValue::CheckUsesForFlag(Flag f, HValue** value) const {
401
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
402
    if (it.value()->IsSimulate()) continue;
403
    if (!it.value()->CheckFlag(f)) {
404
      *value = it.value();
405
      return false;
406
    }
407
  }
408
  return true;
409
}
410

    
411

    
412
bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) const {
413
  bool return_value = false;
414
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
415
    if (it.value()->IsSimulate()) continue;
416
    if (!it.value()->CheckFlag(f)) return false;
417
    return_value = true;
418
  }
419
  return return_value;
420
}
421

    
422

    
423
HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
424
  Advance();
425
}
426

    
427

    
428
void HUseIterator::Advance() {
429
  current_ = next_;
430
  if (current_ != NULL) {
431
    next_ = current_->tail();
432
    value_ = current_->value();
433
    index_ = current_->index();
434
  }
435
}
436

    
437

    
438
int HValue::UseCount() const {
439
  int count = 0;
440
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
441
  return count;
442
}
443

    
444

    
445
HUseListNode* HValue::RemoveUse(HValue* value, int index) {
446
  HUseListNode* previous = NULL;
447
  HUseListNode* current = use_list_;
448
  while (current != NULL) {
449
    if (current->value() == value && current->index() == index) {
450
      if (previous == NULL) {
451
        use_list_ = current->tail();
452
      } else {
453
        previous->set_tail(current->tail());
454
      }
455
      break;
456
    }
457

    
458
    previous = current;
459
    current = current->tail();
460
  }
461

    
462
#ifdef DEBUG
463
  // Do not reuse use list nodes in debug mode, zap them.
464
  if (current != NULL) {
465
    HUseListNode* temp =
466
        new(block()->zone())
467
        HUseListNode(current->value(), current->index(), NULL);
468
    current->Zap();
469
    current = temp;
470
  }
471
#endif
472
  return current;
473
}
474

    
475

    
476
bool HValue::Equals(HValue* other) {
477
  if (other->opcode() != opcode()) return false;
478
  if (!other->representation().Equals(representation())) return false;
479
  if (!other->type_.Equals(type_)) return false;
480
  if (other->flags() != flags()) return false;
481
  if (OperandCount() != other->OperandCount()) return false;
482
  for (int i = 0; i < OperandCount(); ++i) {
483
    if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
484
  }
485
  bool result = DataEquals(other);
486
  ASSERT(!result || Hashcode() == other->Hashcode());
487
  return result;
488
}
489

    
490

    
491
intptr_t HValue::Hashcode() {
492
  intptr_t result = opcode();
493
  int count = OperandCount();
494
  for (int i = 0; i < count; ++i) {
495
    result = result * 19 + OperandAt(i)->id() + (result >> 7);
496
  }
497
  return result;
498
}
499

    
500

    
501
const char* HValue::Mnemonic() const {
502
  switch (opcode()) {
503
#define MAKE_CASE(type) case k##type: return #type;
504
    HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
505
#undef MAKE_CASE
506
    case kPhi: return "Phi";
507
    default: return "";
508
  }
509
}
510

    
511

    
512
bool HValue::CanReplaceWithDummyUses() {
513
  return FLAG_unreachable_code_elimination &&
514
      !(block()->IsReachable() ||
515
        IsBlockEntry() ||
516
        IsControlInstruction() ||
517
        IsSimulate() ||
518
        IsEnterInlined() ||
519
        IsLeaveInlined());
520
}
521

    
522

    
523
bool HValue::IsInteger32Constant() {
524
  return IsConstant() && HConstant::cast(this)->HasInteger32Value();
525
}
526

    
527

    
528
int32_t HValue::GetInteger32Constant() {
529
  return HConstant::cast(this)->Integer32Value();
530
}
531

    
532

    
533
bool HValue::EqualsInteger32Constant(int32_t value) {
534
  return IsInteger32Constant() && GetInteger32Constant() == value;
535
}
536

    
537

    
538
void HValue::SetOperandAt(int index, HValue* value) {
539
  RegisterUse(index, value);
540
  InternalSetOperandAt(index, value);
541
}
542

    
543

    
544
void HValue::DeleteAndReplaceWith(HValue* other) {
545
  // We replace all uses first, so Delete can assert that there are none.
546
  if (other != NULL) ReplaceAllUsesWith(other);
547
  Kill();
548
  DeleteFromGraph();
549
}
550

    
551

    
552
void HValue::ReplaceAllUsesWith(HValue* other) {
553
  while (use_list_ != NULL) {
554
    HUseListNode* list_node = use_list_;
555
    HValue* value = list_node->value();
556
    ASSERT(!value->block()->IsStartBlock());
557
    value->InternalSetOperandAt(list_node->index(), other);
558
    use_list_ = list_node->tail();
559
    list_node->set_tail(other->use_list_);
560
    other->use_list_ = list_node;
561
  }
562
}
563

    
564

    
565
void HValue::Kill() {
566
  // Instead of going through the entire use list of each operand, we only
567
  // check the first item in each use list and rely on the tail() method to
568
  // skip dead items, removing them lazily next time we traverse the list.
569
  SetFlag(kIsDead);
570
  for (int i = 0; i < OperandCount(); ++i) {
571
    HValue* operand = OperandAt(i);
572
    if (operand == NULL) continue;
573
    HUseListNode* first = operand->use_list_;
574
    if (first != NULL && first->value()->CheckFlag(kIsDead)) {
575
      operand->use_list_ = first->tail();
576
    }
577
  }
578
}
579

    
580

    
581
void HValue::SetBlock(HBasicBlock* block) {
582
  ASSERT(block_ == NULL || block == NULL);
583
  block_ = block;
584
  if (id_ == kNoNumber && block != NULL) {
585
    id_ = block->graph()->GetNextValueID(this);
586
  }
587
}
588

    
589

    
590
void HValue::PrintTypeTo(StringStream* stream) {
591
  if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
592
  stream->Add(" type:%s", type().ToString());
593
}
594

    
595

    
596
void HValue::PrintRangeTo(StringStream* stream) {
597
  if (range() == NULL || range()->IsMostGeneric()) return;
598
  // Note: The c1visualizer syntax for locals allows only a sequence of the
599
  // following characters: A-Za-z0-9_-|:
600
  stream->Add(" range:%d_%d%s",
601
              range()->lower(),
602
              range()->upper(),
603
              range()->CanBeMinusZero() ? "_m0" : "");
604
}
605

    
606

    
607
void HValue::PrintChangesTo(StringStream* stream) {
608
  GVNFlagSet changes_flags = ChangesFlags();
609
  if (changes_flags.IsEmpty()) return;
610
  stream->Add(" changes[");
611
  if (changes_flags == AllSideEffectsFlagSet()) {
612
    stream->Add("*");
613
  } else {
614
    bool add_comma = false;
615
#define PRINT_DO(type)                            \
616
    if (changes_flags.Contains(kChanges##type)) { \
617
      if (add_comma) stream->Add(",");            \
618
      add_comma = true;                           \
619
      stream->Add(#type);                         \
620
    }
621
    GVN_TRACKED_FLAG_LIST(PRINT_DO);
622
    GVN_UNTRACKED_FLAG_LIST(PRINT_DO);
623
#undef PRINT_DO
624
  }
625
  stream->Add("]");
626
}
627

    
628

    
629
void HValue::PrintNameTo(StringStream* stream) {
630
  stream->Add("%s%d", representation_.Mnemonic(), id());
631
}
632

    
633

    
634
bool HValue::HasMonomorphicJSObjectType() {
635
  return !GetMonomorphicJSObjectMap().is_null();
636
}
637

    
638

    
639
bool HValue::UpdateInferredType() {
640
  HType type = CalculateInferredType();
641
  bool result = (!type.Equals(type_));
642
  type_ = type;
643
  return result;
644
}
645

    
646

    
647
void HValue::RegisterUse(int index, HValue* new_value) {
648
  HValue* old_value = OperandAt(index);
649
  if (old_value == new_value) return;
650

    
651
  HUseListNode* removed = NULL;
652
  if (old_value != NULL) {
653
    removed = old_value->RemoveUse(this, index);
654
  }
655

    
656
  if (new_value != NULL) {
657
    if (removed == NULL) {
658
      new_value->use_list_ = new(new_value->block()->zone()) HUseListNode(
659
          this, index, new_value->use_list_);
660
    } else {
661
      removed->set_tail(new_value->use_list_);
662
      new_value->use_list_ = removed;
663
    }
664
  }
665
}
666

    
667

    
668
void HValue::AddNewRange(Range* r, Zone* zone) {
669
  if (!HasRange()) ComputeInitialRange(zone);
670
  if (!HasRange()) range_ = new(zone) Range();
671
  ASSERT(HasRange());
672
  r->StackUpon(range_);
673
  range_ = r;
674
}
675

    
676

    
677
void HValue::RemoveLastAddedRange() {
678
  ASSERT(HasRange());
679
  ASSERT(range_->next() != NULL);
680
  range_ = range_->next();
681
}
682

    
683

    
684
void HValue::ComputeInitialRange(Zone* zone) {
685
  ASSERT(!HasRange());
686
  range_ = InferRange(zone);
687
  ASSERT(HasRange());
688
}
689

    
690

    
691
void HInstruction::PrintTo(StringStream* stream) {
692
  PrintMnemonicTo(stream);
693
  PrintDataTo(stream);
694
  PrintRangeTo(stream);
695
  PrintChangesTo(stream);
696
  PrintTypeTo(stream);
697
  if (CheckFlag(HValue::kHasNoObservableSideEffects)) {
698
    stream->Add(" [noOSE]");
699
  }
700
}
701

    
702

    
703
void HInstruction::PrintDataTo(StringStream *stream) {
704
  for (int i = 0; i < OperandCount(); ++i) {
705
    if (i > 0) stream->Add(" ");
706
    OperandAt(i)->PrintNameTo(stream);
707
  }
708
}
709

    
710

    
711
void HInstruction::PrintMnemonicTo(StringStream* stream) {
712
  stream->Add("%s ", Mnemonic());
713
}
714

    
715

    
716
void HInstruction::Unlink() {
717
  ASSERT(IsLinked());
718
  ASSERT(!IsControlInstruction());  // Must never move control instructions.
719
  ASSERT(!IsBlockEntry());  // Doesn't make sense to delete these.
720
  ASSERT(previous_ != NULL);
721
  previous_->next_ = next_;
722
  if (next_ == NULL) {
723
    ASSERT(block()->last() == this);
724
    block()->set_last(previous_);
725
  } else {
726
    next_->previous_ = previous_;
727
  }
728
  clear_block();
729
}
730

    
731

    
732
void HInstruction::InsertBefore(HInstruction* next) {
733
  ASSERT(!IsLinked());
734
  ASSERT(!next->IsBlockEntry());
735
  ASSERT(!IsControlInstruction());
736
  ASSERT(!next->block()->IsStartBlock());
737
  ASSERT(next->previous_ != NULL);
738
  HInstruction* prev = next->previous();
739
  prev->next_ = this;
740
  next->previous_ = this;
741
  next_ = next;
742
  previous_ = prev;
743
  SetBlock(next->block());
744
  if (position() == RelocInfo::kNoPosition &&
745
      next->position() != RelocInfo::kNoPosition) {
746
    set_position(next->position());
747
  }
748
}
749

    
750

    
751
void HInstruction::InsertAfter(HInstruction* previous) {
752
  ASSERT(!IsLinked());
753
  ASSERT(!previous->IsControlInstruction());
754
  ASSERT(!IsControlInstruction() || previous->next_ == NULL);
755
  HBasicBlock* block = previous->block();
756
  // Never insert anything except constants into the start block after finishing
757
  // it.
758
  if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
759
    ASSERT(block->end()->SecondSuccessor() == NULL);
760
    InsertAfter(block->end()->FirstSuccessor()->first());
761
    return;
762
  }
763

    
764
  // If we're inserting after an instruction with side-effects that is
765
  // followed by a simulate instruction, we need to insert after the
766
  // simulate instruction instead.
767
  HInstruction* next = previous->next_;
768
  if (previous->HasObservableSideEffects() && next != NULL) {
769
    ASSERT(next->IsSimulate());
770
    previous = next;
771
    next = previous->next_;
772
  }
773

    
774
  previous_ = previous;
775
  next_ = next;
776
  SetBlock(block);
777
  previous->next_ = this;
778
  if (next != NULL) next->previous_ = this;
779
  if (block->last() == previous) {
780
    block->set_last(this);
781
  }
782
  if (position() == RelocInfo::kNoPosition &&
783
      previous->position() != RelocInfo::kNoPosition) {
784
    set_position(previous->position());
785
  }
786
}
787

    
788

    
789
#ifdef DEBUG
790
void HInstruction::Verify() {
791
  // Verify that input operands are defined before use.
792
  HBasicBlock* cur_block = block();
793
  for (int i = 0; i < OperandCount(); ++i) {
794
    HValue* other_operand = OperandAt(i);
795
    if (other_operand == NULL) continue;
796
    HBasicBlock* other_block = other_operand->block();
797
    if (cur_block == other_block) {
798
      if (!other_operand->IsPhi()) {
799
        HInstruction* cur = this->previous();
800
        while (cur != NULL) {
801
          if (cur == other_operand) break;
802
          cur = cur->previous();
803
        }
804
        // Must reach other operand in the same block!
805
        ASSERT(cur == other_operand);
806
      }
807
    } else {
808
      // If the following assert fires, you may have forgotten an
809
      // AddInstruction.
810
      ASSERT(other_block->Dominates(cur_block));
811
    }
812
  }
813

    
814
  // Verify that instructions that may have side-effects are followed
815
  // by a simulate instruction.
816
  if (HasObservableSideEffects() && !IsOsrEntry()) {
817
    ASSERT(next()->IsSimulate());
818
  }
819

    
820
  // Verify that instructions that can be eliminated by GVN have overridden
821
  // HValue::DataEquals.  The default implementation is UNREACHABLE.  We
822
  // don't actually care whether DataEquals returns true or false here.
823
  if (CheckFlag(kUseGVN)) DataEquals(this);
824

    
825
  // Verify that all uses are in the graph.
826
  for (HUseIterator use = uses(); !use.Done(); use.Advance()) {
827
    if (use.value()->IsInstruction()) {
828
      ASSERT(HInstruction::cast(use.value())->IsLinked());
829
    }
830
  }
831
}
832
#endif
833

    
834

    
835
void HDummyUse::PrintDataTo(StringStream* stream) {
836
  value()->PrintNameTo(stream);
837
}
838

    
839

    
840
void HEnvironmentMarker::PrintDataTo(StringStream* stream) {
841
  stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index());
842
}
843

    
844

    
845
void HUnaryCall::PrintDataTo(StringStream* stream) {
846
  value()->PrintNameTo(stream);
847
  stream->Add(" ");
848
  stream->Add("#%d", argument_count());
849
}
850

    
851

    
852
void HBinaryCall::PrintDataTo(StringStream* stream) {
853
  first()->PrintNameTo(stream);
854
  stream->Add(" ");
855
  second()->PrintNameTo(stream);
856
  stream->Add(" ");
857
  stream->Add("#%d", argument_count());
858
}
859

    
860

    
861
void HBoundsCheck::ApplyIndexChange() {
862
  if (skip_check()) return;
863

    
864
  DecompositionResult decomposition;
865
  bool index_is_decomposable = index()->TryDecompose(&decomposition);
866
  if (index_is_decomposable) {
867
    ASSERT(decomposition.base() == base());
868
    if (decomposition.offset() == offset() &&
869
        decomposition.scale() == scale()) return;
870
  } else {
871
    return;
872
  }
873

    
874
  ReplaceAllUsesWith(index());
875

    
876
  HValue* current_index = decomposition.base();
877
  int actual_offset = decomposition.offset() + offset();
878
  int actual_scale = decomposition.scale() + scale();
879

    
880
  Zone* zone = block()->graph()->zone();
881
  HValue* context = block()->graph()->GetInvalidContext();
882
  if (actual_offset != 0) {
883
    HConstant* add_offset = HConstant::New(zone, context, actual_offset);
884
    add_offset->InsertBefore(this);
885
    HInstruction* add = HAdd::New(zone, context,
886
                                  current_index, add_offset);
887
    add->InsertBefore(this);
888
    add->AssumeRepresentation(index()->representation());
889
    add->ClearFlag(kCanOverflow);
890
    current_index = add;
891
  }
892

    
893
  if (actual_scale != 0) {
894
    HConstant* sar_scale = HConstant::New(zone, context, actual_scale);
895
    sar_scale->InsertBefore(this);
896
    HInstruction* sar = HSar::New(zone, context,
897
                                  current_index, sar_scale);
898
    sar->InsertBefore(this);
899
    sar->AssumeRepresentation(index()->representation());
900
    current_index = sar;
901
  }
902

    
903
  SetOperandAt(0, current_index);
904

    
905
  base_ = NULL;
906
  offset_ = 0;
907
  scale_ = 0;
908
}
909

    
910

    
911
void HBoundsCheck::PrintDataTo(StringStream* stream) {
912
  index()->PrintNameTo(stream);
913
  stream->Add(" ");
914
  length()->PrintNameTo(stream);
915
  if (base() != NULL && (offset() != 0 || scale() != 0)) {
916
    stream->Add(" base: ((");
917
    if (base() != index()) {
918
      index()->PrintNameTo(stream);
919
    } else {
920
      stream->Add("index");
921
    }
922
    stream->Add(" + %d) >> %d)", offset(), scale());
923
  }
924
  if (skip_check()) {
925
    stream->Add(" [DISABLED]");
926
  }
927
}
928

    
929

    
930
void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
931
  ASSERT(CheckFlag(kFlexibleRepresentation));
932
  HValue* actual_index = index()->ActualValue();
933
  HValue* actual_length = length()->ActualValue();
934
  Representation index_rep = actual_index->representation();
935
  Representation length_rep = actual_length->representation();
936
  if (index_rep.IsTagged() && actual_index->type().IsSmi()) {
937
    index_rep = Representation::Smi();
938
  }
939
  if (length_rep.IsTagged() && actual_length->type().IsSmi()) {
940
    length_rep = Representation::Smi();
941
  }
942
  Representation r = index_rep.generalize(length_rep);
943
  if (r.is_more_general_than(Representation::Integer32())) {
944
    r = Representation::Integer32();
945
  }
946
  UpdateRepresentation(r, h_infer, "boundscheck");
947
}
948

    
949

    
950
void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
951
  stream->Add("base: ");
952
  base_index()->PrintNameTo(stream);
953
  stream->Add(", check: ");
954
  base_index()->PrintNameTo(stream);
955
}
956

    
957

    
958
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
959
  if (IsApplyFunction()) {
960
    stream->Add("optimized apply ");
961
  } else {
962
    stream->Add("%o ", function()->shared()->DebugName());
963
  }
964
  stream->Add("#%d", argument_count());
965
}
966

    
967

    
968
void HCallNamed::PrintDataTo(StringStream* stream) {
969
  stream->Add("%o ", *name());
970
  HUnaryCall::PrintDataTo(stream);
971
}
972

    
973

    
974
void HCallGlobal::PrintDataTo(StringStream* stream) {
975
  stream->Add("%o ", *name());
976
  HUnaryCall::PrintDataTo(stream);
977
}
978

    
979

    
980
void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
981
  stream->Add("%o ", target()->shared()->DebugName());
982
  stream->Add("#%d", argument_count());
983
}
984

    
985

    
986
void HCallNewArray::PrintDataTo(StringStream* stream) {
987
  stream->Add(ElementsKindToString(elements_kind()));
988
  stream->Add(" ");
989
  HBinaryCall::PrintDataTo(stream);
990
}
991

    
992

    
993
void HCallRuntime::PrintDataTo(StringStream* stream) {
994
  stream->Add("%o ", *name());
995
  if (save_doubles() == kSaveFPRegs) {
996
    stream->Add("[save doubles] ");
997
  }
998
  stream->Add("#%d", argument_count());
999
}
1000

    
1001

    
1002
void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
1003
  stream->Add("class_of_test(");
1004
  value()->PrintNameTo(stream);
1005
  stream->Add(", \"%o\")", *class_name());
1006
}
1007

    
1008

    
1009
void HWrapReceiver::PrintDataTo(StringStream* stream) {
1010
  receiver()->PrintNameTo(stream);
1011
  stream->Add(" ");
1012
  function()->PrintNameTo(stream);
1013
}
1014

    
1015

    
1016
void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
1017
  arguments()->PrintNameTo(stream);
1018
  stream->Add("[");
1019
  index()->PrintNameTo(stream);
1020
  stream->Add("], length ");
1021
  length()->PrintNameTo(stream);
1022
}
1023

    
1024

    
1025
void HControlInstruction::PrintDataTo(StringStream* stream) {
1026
  stream->Add(" goto (");
1027
  bool first_block = true;
1028
  for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
1029
    stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
1030
    first_block = false;
1031
  }
1032
  stream->Add(")");
1033
}
1034

    
1035

    
1036
void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
1037
  value()->PrintNameTo(stream);
1038
  HControlInstruction::PrintDataTo(stream);
1039
}
1040

    
1041

    
1042
void HReturn::PrintDataTo(StringStream* stream) {
1043
  value()->PrintNameTo(stream);
1044
  stream->Add(" (pop ");
1045
  parameter_count()->PrintNameTo(stream);
1046
  stream->Add(" values)");
1047
}
1048

    
1049

    
1050
Representation HBranch::observed_input_representation(int index) {
1051
  static const ToBooleanStub::Types tagged_types(
1052
      ToBooleanStub::NULL_TYPE |
1053
      ToBooleanStub::SPEC_OBJECT |
1054
      ToBooleanStub::STRING |
1055
      ToBooleanStub::SYMBOL);
1056
  if (expected_input_types_.ContainsAnyOf(tagged_types)) {
1057
    return Representation::Tagged();
1058
  }
1059
  if (expected_input_types_.Contains(ToBooleanStub::UNDEFINED)) {
1060
    if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) {
1061
      return Representation::Double();
1062
    }
1063
    return Representation::Tagged();
1064
  }
1065
  if (expected_input_types_.Contains(ToBooleanStub::HEAP_NUMBER)) {
1066
    return Representation::Double();
1067
  }
1068
  if (expected_input_types_.Contains(ToBooleanStub::SMI)) {
1069
    return Representation::Smi();
1070
  }
1071
  return Representation::None();
1072
}
1073

    
1074

    
1075
bool HBranch::KnownSuccessorBlock(HBasicBlock** block) {
1076
  HValue* value = this->value();
1077
  if (value->EmitAtUses()) {
1078
    ASSERT(value->IsConstant());
1079
    ASSERT(!value->representation().IsDouble());
1080
    *block = HConstant::cast(value)->BooleanValue()
1081
        ? FirstSuccessor()
1082
        : SecondSuccessor();
1083
    return true;
1084
  }
1085
  *block = NULL;
1086
  return false;
1087
}
1088

    
1089

    
1090
void HCompareMap::PrintDataTo(StringStream* stream) {
1091
  value()->PrintNameTo(stream);
1092
  stream->Add(" (%p)", *map().handle());
1093
  HControlInstruction::PrintDataTo(stream);
1094
}
1095

    
1096

    
1097
const char* HUnaryMathOperation::OpName() const {
1098
  switch (op()) {
1099
    case kMathFloor: return "floor";
1100
    case kMathRound: return "round";
1101
    case kMathAbs: return "abs";
1102
    case kMathLog: return "log";
1103
    case kMathSin: return "sin";
1104
    case kMathCos: return "cos";
1105
    case kMathTan: return "tan";
1106
    case kMathExp: return "exp";
1107
    case kMathSqrt: return "sqrt";
1108
    case kMathPowHalf: return "pow-half";
1109
    default:
1110
      UNREACHABLE();
1111
      return NULL;
1112
  }
1113
}
1114

    
1115

    
1116
Range* HUnaryMathOperation::InferRange(Zone* zone) {
1117
  Representation r = representation();
1118
  if (r.IsSmiOrInteger32() && value()->HasRange()) {
1119
    if (op() == kMathAbs) {
1120
      int upper = value()->range()->upper();
1121
      int lower = value()->range()->lower();
1122
      bool spans_zero = value()->range()->CanBeZero();
1123
      // Math.abs(kMinInt) overflows its representation, on which the
1124
      // instruction deopts. Hence clamp it to kMaxInt.
1125
      int abs_upper = upper == kMinInt ? kMaxInt : abs(upper);
1126
      int abs_lower = lower == kMinInt ? kMaxInt : abs(lower);
1127
      Range* result =
1128
          new(zone) Range(spans_zero ? 0 : Min(abs_lower, abs_upper),
1129
                          Max(abs_lower, abs_upper));
1130
      // In case of Smi representation, clamp Math.abs(Smi::kMinValue) to
1131
      // Smi::kMaxValue.
1132
      if (r.IsSmi()) result->ClampToSmi();
1133
      return result;
1134
    }
1135
  }
1136
  return HValue::InferRange(zone);
1137
}
1138

    
1139

    
1140
void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
1141
  const char* name = OpName();
1142
  stream->Add("%s ", name);
1143
  value()->PrintNameTo(stream);
1144
}
1145

    
1146

    
1147
void HUnaryOperation::PrintDataTo(StringStream* stream) {
1148
  value()->PrintNameTo(stream);
1149
}
1150

    
1151

    
1152
void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
1153
  value()->PrintNameTo(stream);
1154
  switch (from_) {
1155
    case FIRST_JS_RECEIVER_TYPE:
1156
      if (to_ == LAST_TYPE) stream->Add(" spec_object");
1157
      break;
1158
    case JS_REGEXP_TYPE:
1159
      if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
1160
      break;
1161
    case JS_ARRAY_TYPE:
1162
      if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
1163
      break;
1164
    case JS_FUNCTION_TYPE:
1165
      if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
1166
      break;
1167
    default:
1168
      break;
1169
  }
1170
}
1171

    
1172

    
1173
void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
1174
  value()->PrintNameTo(stream);
1175
  stream->Add(" == %o", *type_literal_);
1176
  HControlInstruction::PrintDataTo(stream);
1177
}
1178

    
1179

    
1180
void HCheckMapValue::PrintDataTo(StringStream* stream) {
1181
  value()->PrintNameTo(stream);
1182
  stream->Add(" ");
1183
  map()->PrintNameTo(stream);
1184
}
1185

    
1186

    
1187
void HForInPrepareMap::PrintDataTo(StringStream* stream) {
1188
  enumerable()->PrintNameTo(stream);
1189
}
1190

    
1191

    
1192
void HForInCacheArray::PrintDataTo(StringStream* stream) {
1193
  enumerable()->PrintNameTo(stream);
1194
  stream->Add(" ");
1195
  map()->PrintNameTo(stream);
1196
  stream->Add("[%d]", idx_);
1197
}
1198

    
1199

    
1200
void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
1201
  object()->PrintNameTo(stream);
1202
  stream->Add(" ");
1203
  index()->PrintNameTo(stream);
1204
}
1205

    
1206

    
1207
static bool MatchLeftIsOnes(HValue* l, HValue* r, HValue** negated) {
1208
  if (!l->EqualsInteger32Constant(~0)) return false;
1209
  *negated = r;
1210
  return true;
1211
}
1212

    
1213

    
1214
static bool MatchNegationViaXor(HValue* instr, HValue** negated) {
1215
  if (!instr->IsBitwise()) return false;
1216
  HBitwise* b = HBitwise::cast(instr);
1217
  return (b->op() == Token::BIT_XOR) &&
1218
      (MatchLeftIsOnes(b->left(), b->right(), negated) ||
1219
       MatchLeftIsOnes(b->right(), b->left(), negated));
1220
}
1221

    
1222

    
1223
static bool MatchDoubleNegation(HValue* instr, HValue** arg) {
1224
  HValue* negated;
1225
  return MatchNegationViaXor(instr, &negated) &&
1226
      MatchNegationViaXor(negated, arg);
1227
}
1228

    
1229

    
1230
HValue* HBitwise::Canonicalize() {
1231
  if (!representation().IsSmiOrInteger32()) return this;
1232
  // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
1233
  int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
1234
  if (left()->EqualsInteger32Constant(nop_constant) &&
1235
      !right()->CheckFlag(kUint32)) {
1236
    return right();
1237
  }
1238
  if (right()->EqualsInteger32Constant(nop_constant) &&
1239
      !left()->CheckFlag(kUint32)) {
1240
    return left();
1241
  }
1242
  // Optimize double negation, a common pattern used for ToInt32(x).
1243
  HValue* arg;
1244
  if (MatchDoubleNegation(this, &arg) && !arg->CheckFlag(kUint32)) {
1245
    return arg;
1246
  }
1247
  return this;
1248
}
1249

    
1250

    
1251
static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
1252
  return arg1->representation().IsSpecialization() &&
1253
    arg2->EqualsInteger32Constant(identity);
1254
}
1255

    
1256

    
1257
HValue* HAdd::Canonicalize() {
1258
  // Adding 0 is an identity operation except in case of -0: -0 + 0 = +0
1259
  if (IsIdentityOperation(left(), right(), 0) &&
1260
      !left()->representation().IsDouble()) {  // Left could be -0.
1261
    return left();
1262
  }
1263
  if (IsIdentityOperation(right(), left(), 0) &&
1264
      !left()->representation().IsDouble()) {  // Right could be -0.
1265
    return right();
1266
  }
1267
  return this;
1268
}
1269

    
1270

    
1271
HValue* HSub::Canonicalize() {
1272
  if (IsIdentityOperation(left(), right(), 0)) return left();
1273
  return this;
1274
}
1275

    
1276

    
1277
HValue* HMul::Canonicalize() {
1278
  if (IsIdentityOperation(left(), right(), 1)) return left();
1279
  if (IsIdentityOperation(right(), left(), 1)) return right();
1280
  return this;
1281
}
1282

    
1283

    
1284
bool HMul::MulMinusOne() {
1285
  if (left()->EqualsInteger32Constant(-1) ||
1286
      right()->EqualsInteger32Constant(-1)) {
1287
    return true;
1288
  }
1289

    
1290
  return false;
1291
}
1292

    
1293

    
1294
HValue* HMod::Canonicalize() {
1295
  return this;
1296
}
1297

    
1298

    
1299
HValue* HDiv::Canonicalize() {
1300
  if (IsIdentityOperation(left(), right(), 1)) return left();
1301
  return this;
1302
}
1303

    
1304

    
1305
HValue* HChange::Canonicalize() {
1306
  return (from().Equals(to())) ? value() : this;
1307
}
1308

    
1309

    
1310
HValue* HWrapReceiver::Canonicalize() {
1311
  if (HasNoUses()) return NULL;
1312
  if (receiver()->type().IsJSObject()) {
1313
    return receiver();
1314
  }
1315
  return this;
1316
}
1317

    
1318

    
1319
void HTypeof::PrintDataTo(StringStream* stream) {
1320
  value()->PrintNameTo(stream);
1321
}
1322

    
1323

    
1324
void HForceRepresentation::PrintDataTo(StringStream* stream) {
1325
  stream->Add("%s ", representation().Mnemonic());
1326
  value()->PrintNameTo(stream);
1327
}
1328

    
1329

    
1330
void HChange::PrintDataTo(StringStream* stream) {
1331
  HUnaryOperation::PrintDataTo(stream);
1332
  stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
1333

    
1334
  if (CanTruncateToInt32()) stream->Add(" truncating-int32");
1335
  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1336
  if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan");
1337
}
1338

    
1339

    
1340
static HValue* SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1341
  // A value with an integer representation does not need to be transformed.
1342
  if (dividend->representation().IsInteger32()) {
1343
    return dividend;
1344
  }
1345
  // A change from an integer32 can be replaced by the integer32 value.
1346
  if (dividend->IsChange() &&
1347
      HChange::cast(dividend)->from().IsInteger32()) {
1348
    return HChange::cast(dividend)->value();
1349
  }
1350
  return NULL;
1351
}
1352

    
1353

    
1354
HValue* HUnaryMathOperation::Canonicalize() {
1355
  if (op() == kMathRound || op() == kMathFloor) {
1356
    HValue* val = value();
1357
    if (val->IsChange()) val = HChange::cast(val)->value();
1358

    
1359
    // If the input is smi or integer32 then we replace the instruction with its
1360
    // input.
1361
    if (val->representation().IsSmiOrInteger32()) {
1362
      if (!val->representation().Equals(representation())) {
1363
        HChange* result = new(block()->zone()) HChange(
1364
            val, representation(), false, false);
1365
        result->InsertBefore(this);
1366
        return result;
1367
      }
1368
      return val;
1369
    }
1370
  }
1371

    
1372
  if (op() == kMathFloor) {
1373
    HValue* val = value();
1374
    if (val->IsChange()) val = HChange::cast(val)->value();
1375
    if (val->IsDiv() && (val->UseCount() == 1)) {
1376
      HDiv* hdiv = HDiv::cast(val);
1377
      HValue* left = hdiv->left();
1378
      HValue* right = hdiv->right();
1379
      // Try to simplify left and right values of the division.
1380
      HValue* new_left = SimplifiedDividendForMathFloorOfDiv(left);
1381
      if (new_left == NULL &&
1382
          hdiv->observed_input_representation(1).IsSmiOrInteger32()) {
1383
        new_left = new(block()->zone()) HChange(
1384
            left, Representation::Integer32(), false, false);
1385
        HChange::cast(new_left)->InsertBefore(this);
1386
      }
1387
      HValue* new_right =
1388
          LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
1389
      if (new_right == NULL &&
1390
#if V8_TARGET_ARCH_ARM
1391
          CpuFeatures::IsSupported(SUDIV) &&
1392
#endif
1393
          hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
1394
        new_right = new(block()->zone()) HChange(
1395
            right, Representation::Integer32(), false, false);
1396
        HChange::cast(new_right)->InsertBefore(this);
1397
      }
1398

    
1399
      // Return if left or right are not optimizable.
1400
      if ((new_left == NULL) || (new_right == NULL)) return this;
1401

    
1402
      // Insert the new values in the graph.
1403
      if (new_left->IsInstruction() &&
1404
          !HInstruction::cast(new_left)->IsLinked()) {
1405
        HInstruction::cast(new_left)->InsertBefore(this);
1406
      }
1407
      if (new_right->IsInstruction() &&
1408
          !HInstruction::cast(new_right)->IsLinked()) {
1409
        HInstruction::cast(new_right)->InsertBefore(this);
1410
      }
1411
      HMathFloorOfDiv* instr =
1412
          HMathFloorOfDiv::New(block()->zone(), context(), new_left, new_right);
1413
      // Replace this HMathFloor instruction by the new HMathFloorOfDiv.
1414
      instr->InsertBefore(this);
1415
      ReplaceAllUsesWith(instr);
1416
      Kill();
1417
      // We know the division had no other uses than this HMathFloor. Delete it.
1418
      // Dead code elimination will deal with |left| and |right| if
1419
      // appropriate.
1420
      hdiv->DeleteAndReplaceWith(NULL);
1421

    
1422
      // Return NULL to remove this instruction from the graph.
1423
      return NULL;
1424
    }
1425
  }
1426
  return this;
1427
}
1428

    
1429

    
1430
HValue* HCheckInstanceType::Canonicalize() {
1431
  if (check_ == IS_STRING && value()->type().IsString()) {
1432
    return value();
1433
  }
1434

    
1435
  if (check_ == IS_INTERNALIZED_STRING && value()->IsConstant()) {
1436
    if (HConstant::cast(value())->HasInternalizedStringValue()) {
1437
      return value();
1438
    }
1439
  }
1440
  return this;
1441
}
1442

    
1443

    
1444
void HCheckInstanceType::GetCheckInterval(InstanceType* first,
1445
                                          InstanceType* last) {
1446
  ASSERT(is_interval_check());
1447
  switch (check_) {
1448
    case IS_SPEC_OBJECT:
1449
      *first = FIRST_SPEC_OBJECT_TYPE;
1450
      *last = LAST_SPEC_OBJECT_TYPE;
1451
      return;
1452
    case IS_JS_ARRAY:
1453
      *first = *last = JS_ARRAY_TYPE;
1454
      return;
1455
    default:
1456
      UNREACHABLE();
1457
  }
1458
}
1459

    
1460

    
1461
void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
1462
  ASSERT(!is_interval_check());
1463
  switch (check_) {
1464
    case IS_STRING:
1465
      *mask = kIsNotStringMask;
1466
      *tag = kStringTag;
1467
      return;
1468
    case IS_INTERNALIZED_STRING:
1469
      *mask = kIsNotInternalizedMask;
1470
      *tag = kInternalizedTag;
1471
      return;
1472
    default:
1473
      UNREACHABLE();
1474
  }
1475
}
1476

    
1477

    
1478
void HCheckMaps::HandleSideEffectDominator(GVNFlag side_effect,
1479
                                           HValue* dominator) {
1480
  ASSERT(side_effect == kChangesMaps);
1481
  // TODO(mstarzinger): For now we specialize on HStoreNamedField, but once
1482
  // type information is rich enough we should generalize this to any HType
1483
  // for which the map is known.
1484
  if (HasNoUses() && dominator->IsStoreNamedField()) {
1485
    HStoreNamedField* store = HStoreNamedField::cast(dominator);
1486
    if (!store->has_transition() || store->object() != value()) return;
1487
    HConstant* transition = HConstant::cast(store->transition());
1488
    if (map_set_.Contains(transition->GetUnique())) {
1489
      DeleteAndReplaceWith(NULL);
1490
      return;
1491
    }
1492
  }
1493
}
1494

    
1495

    
1496
void HCheckMaps::PrintDataTo(StringStream* stream) {
1497
  value()->PrintNameTo(stream);
1498
  stream->Add(" [%p", *map_set_.at(0).handle());
1499
  for (int i = 1; i < map_set_.size(); ++i) {
1500
    stream->Add(",%p", *map_set_.at(i).handle());
1501
  }
1502
  stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : "");
1503
}
1504

    
1505

    
1506
void HCheckValue::PrintDataTo(StringStream* stream) {
1507
  value()->PrintNameTo(stream);
1508
  stream->Add(" ");
1509
  object().handle()->ShortPrint(stream);
1510
}
1511

    
1512

    
1513
HValue* HCheckValue::Canonicalize() {
1514
  return (value()->IsConstant() &&
1515
          HConstant::cast(value())->GetUnique() == object_)
1516
      ? NULL
1517
      : this;
1518
}
1519

    
1520

    
1521
const char* HCheckInstanceType::GetCheckName() {
1522
  switch (check_) {
1523
    case IS_SPEC_OBJECT: return "object";
1524
    case IS_JS_ARRAY: return "array";
1525
    case IS_STRING: return "string";
1526
    case IS_INTERNALIZED_STRING: return "internalized_string";
1527
  }
1528
  UNREACHABLE();
1529
  return "";
1530
}
1531

    
1532

    
1533
void HCheckInstanceType::PrintDataTo(StringStream* stream) {
1534
  stream->Add("%s ", GetCheckName());
1535
  HUnaryOperation::PrintDataTo(stream);
1536
}
1537

    
1538

    
1539
void HCallStub::PrintDataTo(StringStream* stream) {
1540
  stream->Add("%s ",
1541
              CodeStub::MajorName(major_key_, false));
1542
  HUnaryCall::PrintDataTo(stream);
1543
}
1544

    
1545

    
1546
void HUnknownOSRValue::PrintDataTo(StringStream *stream) {
1547
  const char* type = "expression";
1548
  if (environment_->is_local_index(index_)) type = "local";
1549
  if (environment_->is_special_index(index_)) type = "special";
1550
  if (environment_->is_parameter_index(index_)) type = "parameter";
1551
  stream->Add("%s @ %d", type, index_);
1552
}
1553

    
1554

    
1555
void HInstanceOf::PrintDataTo(StringStream* stream) {
1556
  left()->PrintNameTo(stream);
1557
  stream->Add(" ");
1558
  right()->PrintNameTo(stream);
1559
  stream->Add(" ");
1560
  context()->PrintNameTo(stream);
1561
}
1562

    
1563

    
1564
Range* HValue::InferRange(Zone* zone) {
1565
  Range* result;
1566
  if (representation().IsSmi() || type().IsSmi()) {
1567
    result = new(zone) Range(Smi::kMinValue, Smi::kMaxValue);
1568
    result->set_can_be_minus_zero(false);
1569
  } else {
1570
    result = new(zone) Range();
1571
    result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32));
1572
    // TODO(jkummerow): The range cannot be minus zero when the upper type
1573
    // bound is Integer32.
1574
  }
1575
  return result;
1576
}
1577

    
1578

    
1579
Range* HChange::InferRange(Zone* zone) {
1580
  Range* input_range = value()->range();
1581
  if (from().IsInteger32() && !value()->CheckFlag(HInstruction::kUint32) &&
1582
      (to().IsSmi() ||
1583
       (to().IsTagged() &&
1584
        input_range != NULL &&
1585
        input_range->IsInSmiRange()))) {
1586
    set_type(HType::Smi());
1587
    ClearGVNFlag(kChangesNewSpacePromotion);
1588
  }
1589
  Range* result = (input_range != NULL)
1590
      ? input_range->Copy(zone)
1591
      : HValue::InferRange(zone);
1592
  result->set_can_be_minus_zero(!to().IsSmiOrInteger32() ||
1593
                                !(CheckFlag(kAllUsesTruncatingToInt32) ||
1594
                                  CheckFlag(kAllUsesTruncatingToSmi)));
1595
  if (to().IsSmi()) result->ClampToSmi();
1596
  return result;
1597
}
1598

    
1599

    
1600
Range* HConstant::InferRange(Zone* zone) {
1601
  if (has_int32_value_) {
1602
    Range* result = new(zone) Range(int32_value_, int32_value_);
1603
    result->set_can_be_minus_zero(false);
1604
    return result;
1605
  }
1606
  return HValue::InferRange(zone);
1607
}
1608

    
1609

    
1610
int HPhi::position() const {
1611
  return block()->first()->position();
1612
}
1613

    
1614

    
1615
Range* HPhi::InferRange(Zone* zone) {
1616
  Representation r = representation();
1617
  if (r.IsSmiOrInteger32()) {
1618
    if (block()->IsLoopHeader()) {
1619
      Range* range = r.IsSmi()
1620
          ? new(zone) Range(Smi::kMinValue, Smi::kMaxValue)
1621
          : new(zone) Range(kMinInt, kMaxInt);
1622
      return range;
1623
    } else {
1624
      Range* range = OperandAt(0)->range()->Copy(zone);
1625
      for (int i = 1; i < OperandCount(); ++i) {
1626
        range->Union(OperandAt(i)->range());
1627
      }
1628
      return range;
1629
    }
1630
  } else {
1631
    return HValue::InferRange(zone);
1632
  }
1633
}
1634

    
1635

    
1636
Range* HAdd::InferRange(Zone* zone) {
1637
  Representation r = representation();
1638
  if (r.IsSmiOrInteger32()) {
1639
    Range* a = left()->range();
1640
    Range* b = right()->range();
1641
    Range* res = a->Copy(zone);
1642
    if (!res->AddAndCheckOverflow(r, b) ||
1643
        (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1644
        (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
1645
      ClearFlag(kCanOverflow);
1646
    }
1647
    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1648
                               !CheckFlag(kAllUsesTruncatingToInt32) &&
1649
                               a->CanBeMinusZero() && b->CanBeMinusZero());
1650
    return res;
1651
  } else {
1652
    return HValue::InferRange(zone);
1653
  }
1654
}
1655

    
1656

    
1657
Range* HSub::InferRange(Zone* zone) {
1658
  Representation r = representation();
1659
  if (r.IsSmiOrInteger32()) {
1660
    Range* a = left()->range();
1661
    Range* b = right()->range();
1662
    Range* res = a->Copy(zone);
1663
    if (!res->SubAndCheckOverflow(r, b) ||
1664
        (r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1665
        (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) {
1666
      ClearFlag(kCanOverflow);
1667
    }
1668
    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1669
                               !CheckFlag(kAllUsesTruncatingToInt32) &&
1670
                               a->CanBeMinusZero() && b->CanBeZero());
1671
    return res;
1672
  } else {
1673
    return HValue::InferRange(zone);
1674
  }
1675
}
1676

    
1677

    
1678
Range* HMul::InferRange(Zone* zone) {
1679
  Representation r = representation();
1680
  if (r.IsSmiOrInteger32()) {
1681
    Range* a = left()->range();
1682
    Range* b = right()->range();
1683
    Range* res = a->Copy(zone);
1684
    if (!res->MulAndCheckOverflow(r, b) ||
1685
        (((r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) ||
1686
         (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) &&
1687
         MulMinusOne())) {
1688
      // Truncated int multiplication is too precise and therefore not the
1689
      // same as converting to Double and back.
1690
      // Handle truncated integer multiplication by -1 special.
1691
      ClearFlag(kCanOverflow);
1692
    }
1693
    res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) &&
1694
                               !CheckFlag(kAllUsesTruncatingToInt32) &&
1695
                               ((a->CanBeZero() && b->CanBeNegative()) ||
1696
                                (a->CanBeNegative() && b->CanBeZero())));
1697
    return res;
1698
  } else {
1699
    return HValue::InferRange(zone);
1700
  }
1701
}
1702

    
1703

    
1704
Range* HDiv::InferRange(Zone* zone) {
1705
  if (representation().IsInteger32()) {
1706
    Range* a = left()->range();
1707
    Range* b = right()->range();
1708
    Range* result = new(zone) Range();
1709
    result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1710
                                  (a->CanBeMinusZero() ||
1711
                                   (a->CanBeZero() && b->CanBeNegative())));
1712
    if (!a->Includes(kMinInt) ||
1713
        !b->Includes(-1) ||
1714
        CheckFlag(kAllUsesTruncatingToInt32)) {
1715
      // It is safe to clear kCanOverflow when kAllUsesTruncatingToInt32.
1716
      ClearFlag(HValue::kCanOverflow);
1717
    }
1718

    
1719
    if (!b->CanBeZero()) {
1720
      ClearFlag(HValue::kCanBeDivByZero);
1721
    }
1722
    return result;
1723
  } else {
1724
    return HValue::InferRange(zone);
1725
  }
1726
}
1727

    
1728

    
1729
Range* HMod::InferRange(Zone* zone) {
1730
  if (representation().IsInteger32()) {
1731
    Range* a = left()->range();
1732
    Range* b = right()->range();
1733

    
1734
    // The magnitude of the modulus is bounded by the right operand. Note that
1735
    // apart for the cases involving kMinInt, the calculation below is the same
1736
    // as Max(Abs(b->lower()), Abs(b->upper())) - 1.
1737
    int32_t positive_bound = -(Min(NegAbs(b->lower()), NegAbs(b->upper())) + 1);
1738

    
1739
    // The result of the modulo operation has the sign of its left operand.
1740
    bool left_can_be_negative = a->CanBeMinusZero() || a->CanBeNegative();
1741
    Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0,
1742
                                    a->CanBePositive() ? positive_bound : 0);
1743

    
1744
    result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) &&
1745
                                  left_can_be_negative);
1746

    
1747
    if (!a->Includes(kMinInt) || !b->Includes(-1)) {
1748
      ClearFlag(HValue::kCanOverflow);
1749
    }
1750

    
1751
    if (!b->CanBeZero()) {
1752
      ClearFlag(HValue::kCanBeDivByZero);
1753
    }
1754
    return result;
1755
  } else {
1756
    return HValue::InferRange(zone);
1757
  }
1758
}
1759

    
1760

    
1761
InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) {
1762
  if (phi->block()->loop_information() == NULL) return NULL;
1763
  if (phi->OperandCount() != 2) return NULL;
1764
  int32_t candidate_increment;
1765

    
1766
  candidate_increment = ComputeIncrement(phi, phi->OperandAt(0));
1767
  if (candidate_increment != 0) {
1768
    return new(phi->block()->graph()->zone())
1769
        InductionVariableData(phi, phi->OperandAt(1), candidate_increment);
1770
  }
1771

    
1772
  candidate_increment = ComputeIncrement(phi, phi->OperandAt(1));
1773
  if (candidate_increment != 0) {
1774
    return new(phi->block()->graph()->zone())
1775
        InductionVariableData(phi, phi->OperandAt(0), candidate_increment);
1776
  }
1777

    
1778
  return NULL;
1779
}
1780

    
1781

    
1782
/*
1783
 * This function tries to match the following patterns (and all the relevant
1784
 * variants related to |, & and + being commutative):
1785
 * base | constant_or_mask
1786
 * base & constant_and_mask
1787
 * (base + constant_offset) & constant_and_mask
1788
 * (base - constant_offset) & constant_and_mask
1789
 */
1790
void InductionVariableData::DecomposeBitwise(
1791
    HValue* value,
1792
    BitwiseDecompositionResult* result) {
1793
  HValue* base = IgnoreOsrValue(value);
1794
  result->base = value;
1795

    
1796
  if (!base->representation().IsInteger32()) return;
1797

    
1798
  if (base->IsBitwise()) {
1799
    bool allow_offset = false;
1800
    int32_t mask = 0;
1801

    
1802
    HBitwise* bitwise = HBitwise::cast(base);
1803
    if (bitwise->right()->IsInteger32Constant()) {
1804
      mask = bitwise->right()->GetInteger32Constant();
1805
      base = bitwise->left();
1806
    } else if (bitwise->left()->IsInteger32Constant()) {
1807
      mask = bitwise->left()->GetInteger32Constant();
1808
      base = bitwise->right();
1809
    } else {
1810
      return;
1811
    }
1812
    if (bitwise->op() == Token::BIT_AND) {
1813
      result->and_mask = mask;
1814
      allow_offset = true;
1815
    } else if (bitwise->op() == Token::BIT_OR) {
1816
      result->or_mask = mask;
1817
    } else {
1818
      return;
1819
    }
1820

    
1821
    result->context = bitwise->context();
1822

    
1823
    if (allow_offset) {
1824
      if (base->IsAdd()) {
1825
        HAdd* add = HAdd::cast(base);
1826
        if (add->right()->IsInteger32Constant()) {
1827
          base = add->left();
1828
        } else if (add->left()->IsInteger32Constant()) {
1829
          base = add->right();
1830
        }
1831
      } else if (base->IsSub()) {
1832
        HSub* sub = HSub::cast(base);
1833
        if (sub->right()->IsInteger32Constant()) {
1834
          base = sub->left();
1835
        }
1836
      }
1837
    }
1838

    
1839
    result->base = base;
1840
  }
1841
}
1842

    
1843

    
1844
void InductionVariableData::AddCheck(HBoundsCheck* check,
1845
                                     int32_t upper_limit) {
1846
  ASSERT(limit_validity() != NULL);
1847
  if (limit_validity() != check->block() &&
1848
      !limit_validity()->Dominates(check->block())) return;
1849
  if (!phi()->block()->current_loop()->IsNestedInThisLoop(
1850
      check->block()->current_loop())) return;
1851

    
1852
  ChecksRelatedToLength* length_checks = checks();
1853
  while (length_checks != NULL) {
1854
    if (length_checks->length() == check->length()) break;
1855
    length_checks = length_checks->next();
1856
  }
1857
  if (length_checks == NULL) {
1858
    length_checks = new(check->block()->zone())
1859
        ChecksRelatedToLength(check->length(), checks());
1860
    checks_ = length_checks;
1861
  }
1862

    
1863
  length_checks->AddCheck(check, upper_limit);
1864
}
1865

    
1866

    
1867
void InductionVariableData::ChecksRelatedToLength::CloseCurrentBlock() {
1868
  if (checks() != NULL) {
1869
    InductionVariableCheck* c = checks();
1870
    HBasicBlock* current_block = c->check()->block();
1871
    while (c != NULL && c->check()->block() == current_block) {
1872
      c->set_upper_limit(current_upper_limit_);
1873
      c = c->next();
1874
    }
1875
  }
1876
}
1877

    
1878

    
1879
void InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock(
1880
    Token::Value token,
1881
    int32_t mask,
1882
    HValue* index_base,
1883
    HValue* context) {
1884
  ASSERT(first_check_in_block() != NULL);
1885
  HValue* previous_index = first_check_in_block()->index();
1886
  ASSERT(context != NULL);
1887

    
1888
  Zone* zone = index_base->block()->graph()->zone();
1889
  set_added_constant(HConstant::New(zone, context, mask));
1890
  if (added_index() != NULL) {
1891
    added_constant()->InsertBefore(added_index());
1892
  } else {
1893
    added_constant()->InsertBefore(first_check_in_block());
1894
  }
1895

    
1896
  if (added_index() == NULL) {
1897
    first_check_in_block()->ReplaceAllUsesWith(first_check_in_block()->index());
1898
    HInstruction* new_index =  HBitwise::New(zone, context, token, index_base,
1899
                                             added_constant());
1900
    ASSERT(new_index->IsBitwise());
1901
    new_index->ClearAllSideEffects();
1902
    new_index->AssumeRepresentation(Representation::Integer32());
1903
    set_added_index(HBitwise::cast(new_index));
1904
    added_index()->InsertBefore(first_check_in_block());
1905
  }
1906
  ASSERT(added_index()->op() == token);
1907

    
1908
  added_index()->SetOperandAt(1, index_base);
1909
  added_index()->SetOperandAt(2, added_constant());
1910
  first_check_in_block()->SetOperandAt(0, added_index());
1911
  if (previous_index->UseCount() == 0) {
1912
    previous_index->DeleteAndReplaceWith(NULL);
1913
  }
1914
}
1915

    
1916
void InductionVariableData::ChecksRelatedToLength::AddCheck(
1917
    HBoundsCheck* check,
1918
    int32_t upper_limit) {
1919
  BitwiseDecompositionResult decomposition;
1920
  InductionVariableData::DecomposeBitwise(check->index(), &decomposition);
1921

    
1922
  if (first_check_in_block() == NULL ||
1923
      first_check_in_block()->block() != check->block()) {
1924
    CloseCurrentBlock();
1925

    
1926
    first_check_in_block_ = check;
1927
    set_added_index(NULL);
1928
    set_added_constant(NULL);
1929
    current_and_mask_in_block_ = decomposition.and_mask;
1930
    current_or_mask_in_block_ = decomposition.or_mask;
1931
    current_upper_limit_ = upper_limit;
1932

    
1933
    InductionVariableCheck* new_check = new(check->block()->graph()->zone())
1934
        InductionVariableCheck(check, checks_, upper_limit);
1935
    checks_ = new_check;
1936
    return;
1937
  }
1938

    
1939
  if (upper_limit > current_upper_limit()) {
1940
    current_upper_limit_ = upper_limit;
1941
  }
1942

    
1943
  if (decomposition.and_mask != 0 &&
1944
      current_or_mask_in_block() == 0) {
1945
    if (current_and_mask_in_block() == 0 ||
1946
        decomposition.and_mask > current_and_mask_in_block()) {
1947
      UseNewIndexInCurrentBlock(Token::BIT_AND,
1948
                                decomposition.and_mask,
1949
                                decomposition.base,
1950
                                decomposition.context);
1951
      current_and_mask_in_block_ = decomposition.and_mask;
1952
    }
1953
    check->set_skip_check();
1954
  }
1955
  if (current_and_mask_in_block() == 0) {
1956
    if (decomposition.or_mask > current_or_mask_in_block()) {
1957
      UseNewIndexInCurrentBlock(Token::BIT_OR,
1958
                                decomposition.or_mask,
1959
                                decomposition.base,
1960
                                decomposition.context);
1961
      current_or_mask_in_block_ = decomposition.or_mask;
1962
    }
1963
    check->set_skip_check();
1964
  }
1965

    
1966
  if (!check->skip_check()) {
1967
    InductionVariableCheck* new_check = new(check->block()->graph()->zone())
1968
        InductionVariableCheck(check, checks_, upper_limit);
1969
    checks_ = new_check;
1970
  }
1971
}
1972

    
1973

    
1974
/*
1975
 * This method detects if phi is an induction variable, with phi_operand as
1976
 * its "incremented" value (the other operand would be the "base" value).
1977
 *
1978
 * It cheks is phi_operand has the form "phi + constant".
1979
 * If yes, the constant is the increment that the induction variable gets at
1980
 * every loop iteration.
1981
 * Otherwise it returns 0.
1982
 */
1983
int32_t InductionVariableData::ComputeIncrement(HPhi* phi,
1984
                                                HValue* phi_operand) {
1985
  if (!phi_operand->representation().IsInteger32()) return 0;
1986

    
1987
  if (phi_operand->IsAdd()) {
1988
    HAdd* operation = HAdd::cast(phi_operand);
1989
    if (operation->left() == phi &&
1990
        operation->right()->IsInteger32Constant()) {
1991
      return operation->right()->GetInteger32Constant();
1992
    } else if (operation->right() == phi &&
1993
               operation->left()->IsInteger32Constant()) {
1994
      return operation->left()->GetInteger32Constant();
1995
    }
1996
  } else if (phi_operand->IsSub()) {
1997
    HSub* operation = HSub::cast(phi_operand);
1998
    if (operation->left() == phi &&
1999
        operation->right()->IsInteger32Constant()) {
2000
      return -operation->right()->GetInteger32Constant();
2001
    }
2002
  }
2003

    
2004
  return 0;
2005
}
2006

    
2007

    
2008
/*
2009
 * Swaps the information in "update" with the one contained in "this".
2010
 * The swapping is important because this method is used while doing a
2011
 * dominator tree traversal, and "update" will retain the old data that
2012
 * will be restored while backtracking.
2013
 */
2014
void InductionVariableData::UpdateAdditionalLimit(
2015
    InductionVariableLimitUpdate* update) {
2016
  ASSERT(update->updated_variable == this);
2017
  if (update->limit_is_upper) {
2018
    swap(&additional_upper_limit_, &update->limit);
2019
    swap(&additional_upper_limit_is_included_, &update->limit_is_included);
2020
  } else {
2021
    swap(&additional_lower_limit_, &update->limit);
2022
    swap(&additional_lower_limit_is_included_, &update->limit_is_included);
2023
  }
2024
}
2025

    
2026

    
2027
int32_t InductionVariableData::ComputeUpperLimit(int32_t and_mask,
2028
                                                 int32_t or_mask) {
2029
  // Should be Smi::kMaxValue but it must fit 32 bits; lower is safe anyway.
2030
  const int32_t MAX_LIMIT = 1 << 30;
2031

    
2032
  int32_t result = MAX_LIMIT;
2033

    
2034
  if (limit() != NULL &&
2035
      limit()->IsInteger32Constant()) {
2036
    int32_t limit_value = limit()->GetInteger32Constant();
2037
    if (!limit_included()) {
2038
      limit_value--;
2039
    }
2040
    if (limit_value < result) result = limit_value;
2041
  }
2042

    
2043
  if (additional_upper_limit() != NULL &&
2044
      additional_upper_limit()->IsInteger32Constant()) {
2045
    int32_t limit_value = additional_upper_limit()->GetInteger32Constant();
2046
    if (!additional_upper_limit_is_included()) {
2047
      limit_value--;
2048
    }
2049
    if (limit_value < result) result = limit_value;
2050
  }
2051

    
2052
  if (and_mask > 0 && and_mask < MAX_LIMIT) {
2053
    if (and_mask < result) result = and_mask;
2054
    return result;
2055
  }
2056

    
2057
  // Add the effect of the or_mask.
2058
  result |= or_mask;
2059

    
2060
  return result >= MAX_LIMIT ? kNoLimit : result;
2061
}
2062

    
2063

    
2064
HValue* InductionVariableData::IgnoreOsrValue(HValue* v) {
2065
  if (!v->IsPhi()) return v;
2066
  HPhi* phi = HPhi::cast(v);
2067
  if (phi->OperandCount() != 2) return v;
2068
  if (phi->OperandAt(0)->block()->is_osr_entry()) {
2069
    return phi->OperandAt(1);
2070
  } else if (phi->OperandAt(1)->block()->is_osr_entry()) {
2071
    return phi->OperandAt(0);
2072
  } else {
2073
    return v;
2074
  }
2075
}
2076

    
2077

    
2078
InductionVariableData* InductionVariableData::GetInductionVariableData(
2079
    HValue* v) {
2080
  v = IgnoreOsrValue(v);
2081
  if (v->IsPhi()) {
2082
    return HPhi::cast(v)->induction_variable_data();
2083
  }
2084
  return NULL;
2085
}
2086

    
2087

    
2088
/*
2089
 * Check if a conditional branch to "current_branch" with token "token" is
2090
 * the branch that keeps the induction loop running (and, conversely, will
2091
 * terminate it if the "other_branch" is taken).
2092
 *
2093
 * Three conditions must be met:
2094
 * - "current_branch" must be in the induction loop.
2095
 * - "other_branch" must be out of the induction loop.
2096
 * - "token" and the induction increment must be "compatible": the token should
2097
 *   be a condition that keeps the execution inside the loop until the limit is
2098
 *   reached.
2099
 */
2100
bool InductionVariableData::CheckIfBranchIsLoopGuard(
2101
    Token::Value token,
2102
    HBasicBlock* current_branch,
2103
    HBasicBlock* other_branch) {
2104
  if (!phi()->block()->current_loop()->IsNestedInThisLoop(
2105
      current_branch->current_loop())) {
2106
    return false;
2107
  }
2108

    
2109
  if (phi()->block()->current_loop()->IsNestedInThisLoop(
2110
      other_branch->current_loop())) {
2111
    return false;
2112
  }
2113

    
2114
  if (increment() > 0 && (token == Token::LT || token == Token::LTE)) {
2115
    return true;
2116
  }
2117
  if (increment() < 0 && (token == Token::GT || token == Token::GTE)) {
2118
    return true;
2119
  }
2120
  if (Token::IsInequalityOp(token) && (increment() == 1 || increment() == -1)) {
2121
    return true;
2122
  }
2123

    
2124
  return false;
2125
}
2126

    
2127

    
2128
void InductionVariableData::ComputeLimitFromPredecessorBlock(
2129
    HBasicBlock* block,
2130
    LimitFromPredecessorBlock* result) {
2131
  if (block->predecessors()->length() != 1) return;
2132
  HBasicBlock* predecessor = block->predecessors()->at(0);
2133
  HInstruction* end = predecessor->last();
2134

    
2135
  if (!end->IsCompareNumericAndBranch()) return;
2136
  HCompareNumericAndBranch* branch = HCompareNumericAndBranch::cast(end);
2137

    
2138
  Token::Value token = branch->token();
2139
  if (!Token::IsArithmeticCompareOp(token)) return;
2140

    
2141
  HBasicBlock* other_target;
2142
  if (block == branch->SuccessorAt(0)) {
2143
    other_target = branch->SuccessorAt(1);
2144
  } else {
2145
    other_target = branch->SuccessorAt(0);
2146
    token = Token::NegateCompareOp(token);
2147
    ASSERT(block == branch->SuccessorAt(1));
2148
  }
2149

    
2150
  InductionVariableData* data;
2151

    
2152
  data = GetInductionVariableData(branch->left());
2153
  HValue* limit = branch->right();
2154
  if (data == NULL) {
2155
    data = GetInductionVariableData(branch->right());
2156
    token = Token::ReverseCompareOp(token);
2157
    limit = branch->left();
2158
  }
2159

    
2160
  if (data != NULL) {
2161
    result->variable = data;
2162
    result->token = token;
2163
    result->limit = limit;
2164
    result->other_target = other_target;
2165
  }
2166
}
2167

    
2168

    
2169
/*
2170
 * Compute the limit that is imposed on an induction variable when entering
2171
 * "block" (if any).
2172
 * If the limit is the "proper" induction limit (the one that makes the loop
2173
 * terminate when the induction variable reaches it) it is stored directly in
2174
 * the induction variable data.
2175
 * Otherwise the limit is written in "additional_limit" and the method
2176
 * returns true.
2177
 */
2178
bool InductionVariableData::ComputeInductionVariableLimit(
2179
    HBasicBlock* block,
2180
    InductionVariableLimitUpdate* additional_limit) {
2181
  LimitFromPredecessorBlock limit;
2182
  ComputeLimitFromPredecessorBlock(block, &limit);
2183
  if (!limit.LimitIsValid()) return false;
2184

    
2185
  if (limit.variable->CheckIfBranchIsLoopGuard(limit.token,
2186
                                               block,
2187
                                               limit.other_target)) {
2188
    limit.variable->limit_ = limit.limit;
2189
    limit.variable->limit_included_ = limit.LimitIsIncluded();
2190
    limit.variable->limit_validity_ = block;
2191
    limit.variable->induction_exit_block_ = block->predecessors()->at(0);
2192
    limit.variable->induction_exit_target_ = limit.other_target;
2193
    return false;
2194
  } else {
2195
    additional_limit->updated_variable = limit.variable;
2196
    additional_limit->limit = limit.limit;
2197
    additional_limit->limit_is_upper = limit.LimitIsUpper();
2198
    additional_limit->limit_is_included = limit.LimitIsIncluded();
2199
    return true;
2200
  }
2201
}
2202

    
2203

    
2204
Range* HMathMinMax::InferRange(Zone* zone) {
2205
  if (representation().IsSmiOrInteger32()) {
2206
    Range* a = left()->range();
2207
    Range* b = right()->range();
2208
    Range* res = a->Copy(zone);
2209
    if (operation_ == kMathMax) {
2210
      res->CombinedMax(b);
2211
    } else {
2212
      ASSERT(operation_ == kMathMin);
2213
      res->CombinedMin(b);
2214
    }
2215
    return res;
2216
  } else {
2217
    return HValue::InferRange(zone);
2218
  }
2219
}
2220

    
2221

    
2222
void HPhi::PrintTo(StringStream* stream) {
2223
  stream->Add("[");
2224
  for (int i = 0; i < OperandCount(); ++i) {
2225
    HValue* value = OperandAt(i);
2226
    stream->Add(" ");
2227
    value->PrintNameTo(stream);
2228
    stream->Add(" ");
2229
  }
2230
  stream->Add(" uses:%d_%ds_%di_%dd_%dt",
2231
              UseCount(),
2232
              smi_non_phi_uses() + smi_indirect_uses(),
2233
              int32_non_phi_uses() + int32_indirect_uses(),
2234
              double_non_phi_uses() + double_indirect_uses(),
2235
              tagged_non_phi_uses() + tagged_indirect_uses());
2236
  PrintRangeTo(stream);
2237
  PrintTypeTo(stream);
2238
  stream->Add("]");
2239
}
2240

    
2241

    
2242
void HPhi::AddInput(HValue* value) {
2243
  inputs_.Add(NULL, value->block()->zone());
2244
  SetOperandAt(OperandCount() - 1, value);
2245
  // Mark phis that may have 'arguments' directly or indirectly as an operand.
2246
  if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
2247
    SetFlag(kIsArguments);
2248
  }
2249
}
2250

    
2251

    
2252
bool HPhi::HasRealUses() {
2253
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2254
    if (!it.value()->IsPhi()) return true;
2255
  }
2256
  return false;
2257
}
2258

    
2259

    
2260
HValue* HPhi::GetRedundantReplacement() {
2261
  HValue* candidate = NULL;
2262
  int count = OperandCount();
2263
  int position = 0;
2264
  while (position < count && candidate == NULL) {
2265
    HValue* current = OperandAt(position++);
2266
    if (current != this) candidate = current;
2267
  }
2268
  while (position < count) {
2269
    HValue* current = OperandAt(position++);
2270
    if (current != this && current != candidate) return NULL;
2271
  }
2272
  ASSERT(candidate != this);
2273
  return candidate;
2274
}
2275

    
2276

    
2277
void HPhi::DeleteFromGraph() {
2278
  ASSERT(block() != NULL);
2279
  block()->RemovePhi(this);
2280
  ASSERT(block() == NULL);
2281
}
2282

    
2283

    
2284
void HPhi::InitRealUses(int phi_id) {
2285
  // Initialize real uses.
2286
  phi_id_ = phi_id;
2287
  // Compute a conservative approximation of truncating uses before inferring
2288
  // representations. The proper, exact computation will be done later, when
2289
  // inserting representation changes.
2290
  SetFlag(kTruncatingToSmi);
2291
  SetFlag(kTruncatingToInt32);
2292
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2293
    HValue* value = it.value();
2294
    if (!value->IsPhi()) {
2295
      Representation rep = value->observed_input_representation(it.index());
2296
      non_phi_uses_[rep.kind()] += value->LoopWeight();
2297
      if (FLAG_trace_representation) {
2298
        PrintF("#%d Phi is used by real #%d %s as %s\n",
2299
               id(), value->id(), value->Mnemonic(), rep.Mnemonic());
2300
      }
2301
      if (!value->IsSimulate()) {
2302
        if (!value->CheckFlag(kTruncatingToSmi)) {
2303
          ClearFlag(kTruncatingToSmi);
2304
        }
2305
        if (!value->CheckFlag(kTruncatingToInt32)) {
2306
          ClearFlag(kTruncatingToInt32);
2307
        }
2308
      }
2309
    }
2310
  }
2311
}
2312

    
2313

    
2314
void HPhi::AddNonPhiUsesFrom(HPhi* other) {
2315
  if (FLAG_trace_representation) {
2316
    PrintF("adding to #%d Phi uses of #%d Phi: s%d i%d d%d t%d\n",
2317
           id(), other->id(),
2318
           other->non_phi_uses_[Representation::kSmi],
2319
           other->non_phi_uses_[Representation::kInteger32],
2320
           other->non_phi_uses_[Representation::kDouble],
2321
           other->non_phi_uses_[Representation::kTagged]);
2322
  }
2323

    
2324
  for (int i = 0; i < Representation::kNumRepresentations; i++) {
2325
    indirect_uses_[i] += other->non_phi_uses_[i];
2326
  }
2327
}
2328

    
2329

    
2330
void HPhi::AddIndirectUsesTo(int* dest) {
2331
  for (int i = 0; i < Representation::kNumRepresentations; i++) {
2332
    dest[i] += indirect_uses_[i];
2333
  }
2334
}
2335

    
2336

    
2337
void HSimulate::MergeWith(ZoneList<HSimulate*>* list) {
2338
  while (!list->is_empty()) {
2339
    HSimulate* from = list->RemoveLast();
2340
    ZoneList<HValue*>* from_values = &from->values_;
2341
    for (int i = 0; i < from_values->length(); ++i) {
2342
      if (from->HasAssignedIndexAt(i)) {
2343
        int index = from->GetAssignedIndexAt(i);
2344
        if (HasValueForIndex(index)) continue;
2345
        AddAssignedValue(index, from_values->at(i));
2346
      } else {
2347
        if (pop_count_ > 0) {
2348
          pop_count_--;
2349
        } else {
2350
          AddPushedValue(from_values->at(i));
2351
        }
2352
      }
2353
    }
2354
    pop_count_ += from->pop_count_;
2355
    from->DeleteAndReplaceWith(NULL);
2356
  }
2357
}
2358

    
2359

    
2360
void HSimulate::PrintDataTo(StringStream* stream) {
2361
  stream->Add("id=%d", ast_id().ToInt());
2362
  if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
2363
  if (values_.length() > 0) {
2364
    if (pop_count_ > 0) stream->Add(" /");
2365
    for (int i = values_.length() - 1; i >= 0; --i) {
2366
      if (HasAssignedIndexAt(i)) {
2367
        stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
2368
      } else {
2369
        stream->Add(" push ");
2370
      }
2371
      values_[i]->PrintNameTo(stream);
2372
      if (i > 0) stream->Add(",");
2373
    }
2374
  }
2375
}
2376

    
2377

    
2378
void HSimulate::ReplayEnvironment(HEnvironment* env) {
2379
  ASSERT(env != NULL);
2380
  env->set_ast_id(ast_id());
2381
  env->Drop(pop_count());
2382
  for (int i = values()->length() - 1; i >= 0; --i) {
2383
    HValue* value = values()->at(i);
2384
    if (HasAssignedIndexAt(i)) {
2385
      env->Bind(GetAssignedIndexAt(i), value);
2386
    } else {
2387
      env->Push(value);
2388
    }
2389
  }
2390
}
2391

    
2392

    
2393
static void ReplayEnvironmentNested(const ZoneList<HValue*>* values,
2394
                                    HCapturedObject* other) {
2395
  for (int i = 0; i < values->length(); ++i) {
2396
    HValue* value = values->at(i);
2397
    if (value->IsCapturedObject()) {
2398
      if (HCapturedObject::cast(value)->capture_id() == other->capture_id()) {
2399
        values->at(i) = other;
2400
      } else {
2401
        ReplayEnvironmentNested(HCapturedObject::cast(value)->values(), other);
2402
      }
2403
    }
2404
  }
2405
}
2406

    
2407

    
2408
// Replay captured objects by replacing all captured objects with the
2409
// same capture id in the current and all outer environments.
2410
void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
2411
  ASSERT(env != NULL);
2412
  while (env != NULL) {
2413
    ReplayEnvironmentNested(env->values(), this);
2414
    env = env->outer();
2415
  }
2416
}
2417

    
2418

    
2419
void HCapturedObject::PrintDataTo(StringStream* stream) {
2420
  stream->Add("#%d ", capture_id());
2421
  HDematerializedObject::PrintDataTo(stream);
2422
}
2423

    
2424

    
2425
void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target,
2426
                                         Zone* zone) {
2427
  ASSERT(return_target->IsInlineReturnTarget());
2428
  return_targets_.Add(return_target, zone);
2429
}
2430

    
2431

    
2432
void HEnterInlined::PrintDataTo(StringStream* stream) {
2433
  SmartArrayPointer<char> name = function()->debug_name()->ToCString();
2434
  stream->Add("%s, id=%d", *name, function()->id().ToInt());
2435
}
2436

    
2437

    
2438
static bool IsInteger32(double value) {
2439
  double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
2440
  return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value);
2441
}
2442

    
2443

    
2444
HConstant::HConstant(Handle<Object> handle, Representation r)
2445
  : HTemplateInstruction<0>(HType::TypeFromValue(handle)),
2446
    object_(Unique<Object>::CreateUninitialized(handle)),
2447
    has_smi_value_(false),
2448
    has_int32_value_(false),
2449
    has_double_value_(false),
2450
    has_external_reference_value_(false),
2451
    is_internalized_string_(false),
2452
    is_not_in_new_space_(true),
2453
    is_cell_(false),
2454
    boolean_value_(handle->BooleanValue()) {
2455
  if (handle->IsHeapObject()) {
2456
    Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
2457
    is_not_in_new_space_ = !heap->InNewSpace(*handle);
2458
  }
2459
  if (handle->IsNumber()) {
2460
    double n = handle->Number();
2461
    has_int32_value_ = IsInteger32(n);
2462
    int32_value_ = DoubleToInt32(n);
2463
    has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
2464
    double_value_ = n;
2465
    has_double_value_ = true;
2466
  } else {
2467
    is_internalized_string_ = handle->IsInternalizedString();
2468
  }
2469

    
2470
  is_cell_ = !handle.is_null() &&
2471
      (handle->IsCell() || handle->IsPropertyCell());
2472
  Initialize(r);
2473
}
2474

    
2475

    
2476
HConstant::HConstant(Unique<Object> unique,
2477
                     Representation r,
2478
                     HType type,
2479
                     bool is_internalize_string,
2480
                     bool is_not_in_new_space,
2481
                     bool is_cell,
2482
                     bool boolean_value)
2483
  : HTemplateInstruction<0>(type),
2484
    object_(unique),
2485
    has_smi_value_(false),
2486
    has_int32_value_(false),
2487
    has_double_value_(false),
2488
    has_external_reference_value_(false),
2489
    is_internalized_string_(is_internalize_string),
2490
    is_not_in_new_space_(is_not_in_new_space),
2491
    is_cell_(is_cell),
2492
    boolean_value_(boolean_value) {
2493
  ASSERT(!unique.handle().is_null());
2494
  ASSERT(!type.IsTaggedNumber());
2495
  Initialize(r);
2496
}
2497

    
2498

    
2499
HConstant::HConstant(int32_t integer_value,
2500
                     Representation r,
2501
                     bool is_not_in_new_space,
2502
                     Unique<Object> object)
2503
  : object_(object),
2504
    has_smi_value_(Smi::IsValid(integer_value)),
2505
    has_int32_value_(true),
2506
    has_double_value_(true),
2507
    has_external_reference_value_(false),
2508
    is_internalized_string_(false),
2509
    is_not_in_new_space_(is_not_in_new_space),
2510
    is_cell_(false),
2511
    boolean_value_(integer_value != 0),
2512
    int32_value_(integer_value),
2513
    double_value_(FastI2D(integer_value)) {
2514
  set_type(has_smi_value_ ? HType::Smi() : HType::TaggedNumber());
2515
  Initialize(r);
2516
}
2517

    
2518

    
2519
HConstant::HConstant(double double_value,
2520
                     Representation r,
2521
                     bool is_not_in_new_space,
2522
                     Unique<Object> object)
2523
  : object_(object),
2524
    has_int32_value_(IsInteger32(double_value)),
2525
    has_double_value_(true),
2526
    has_external_reference_value_(false),
2527
    is_internalized_string_(false),
2528
    is_not_in_new_space_(is_not_in_new_space),
2529
    is_cell_(false),
2530
    boolean_value_(double_value != 0 && !std::isnan(double_value)),
2531
    int32_value_(DoubleToInt32(double_value)),
2532
    double_value_(double_value) {
2533
  has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
2534
  set_type(has_smi_value_ ? HType::Smi() : HType::TaggedNumber());
2535
  Initialize(r);
2536
}
2537

    
2538

    
2539
HConstant::HConstant(ExternalReference reference)
2540
  : HTemplateInstruction<0>(HType::None()),
2541
    object_(Unique<Object>(Handle<Object>::null())),
2542
    has_smi_value_(false),
2543
    has_int32_value_(false),
2544
    has_double_value_(false),
2545
    has_external_reference_value_(true),
2546
    is_internalized_string_(false),
2547
    is_not_in_new_space_(true),
2548
    is_cell_(false),
2549
    boolean_value_(true),
2550
    external_reference_value_(reference) {
2551
  Initialize(Representation::External());
2552
}
2553

    
2554

    
2555
void HConstant::Initialize(Representation r) {
2556
  if (r.IsNone()) {
2557
    if (has_smi_value_ && SmiValuesAre31Bits()) {
2558
      r = Representation::Smi();
2559
    } else if (has_int32_value_) {
2560
      r = Representation::Integer32();
2561
    } else if (has_double_value_) {
2562
      r = Representation::Double();
2563
    } else if (has_external_reference_value_) {
2564
      r = Representation::External();
2565
    } else {
2566
      Handle<Object> object = object_.handle();
2567
      if (object->IsJSObject()) {
2568
        // Try to eagerly migrate JSObjects that have deprecated maps.
2569
        Handle<JSObject> js_object = Handle<JSObject>::cast(object);
2570
        if (js_object->map()->is_deprecated()) {
2571
          JSObject::TryMigrateInstance(js_object);
2572
        }
2573
      }
2574
      r = Representation::Tagged();
2575
    }
2576
  }
2577
  set_representation(r);
2578
  SetFlag(kUseGVN);
2579
}
2580

    
2581

    
2582
bool HConstant::EmitAtUses() {
2583
  ASSERT(IsLinked());
2584
  if (block()->graph()->has_osr() &&
2585
      block()->graph()->IsStandardConstant(this)) {
2586
    // TODO(titzer): this seems like a hack that should be fixed by custom OSR.
2587
    return true;
2588
  }
2589
  if (UseCount() == 0) return true;
2590
  if (IsCell()) return false;
2591
  if (representation().IsDouble()) return false;
2592
  return true;
2593
}
2594

    
2595

    
2596
HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
2597
  if (r.IsSmi() && !has_smi_value_) return NULL;
2598
  if (r.IsInteger32() && !has_int32_value_) return NULL;
2599
  if (r.IsDouble() && !has_double_value_) return NULL;
2600
  if (r.IsExternal() && !has_external_reference_value_) return NULL;
2601
  if (has_int32_value_) {
2602
    return new(zone) HConstant(int32_value_, r, is_not_in_new_space_, object_);
2603
  }
2604
  if (has_double_value_) {
2605
    return new(zone) HConstant(double_value_, r, is_not_in_new_space_, object_);
2606
  }
2607
  if (has_external_reference_value_) {
2608
    return new(zone) HConstant(external_reference_value_);
2609
  }
2610
  ASSERT(!object_.handle().is_null());
2611
  return new(zone) HConstant(object_,
2612
                             r,
2613
                             type_,
2614
                             is_internalized_string_,
2615
                             is_not_in_new_space_,
2616
                             is_cell_,
2617
                             boolean_value_);
2618
}
2619

    
2620

    
2621
Maybe<HConstant*> HConstant::CopyToTruncatedInt32(Zone* zone) {
2622
  HConstant* res = NULL;
2623
  if (has_int32_value_) {
2624
    res = new(zone) HConstant(int32_value_,
2625
                              Representation::Integer32(),
2626
                              is_not_in_new_space_,
2627
                              object_);
2628
  } else if (has_double_value_) {
2629
    res = new(zone) HConstant(DoubleToInt32(double_value_),
2630
                              Representation::Integer32(),
2631
                              is_not_in_new_space_,
2632
                              object_);
2633
  }
2634
  return Maybe<HConstant*>(res != NULL, res);
2635
}
2636

    
2637

    
2638
Maybe<HConstant*> HConstant::CopyToTruncatedNumber(Zone* zone) {
2639
  HConstant* res = NULL;
2640
  Handle<Object> handle = this->handle(zone->isolate());
2641
  if (handle->IsBoolean()) {
2642
    res = handle->BooleanValue() ?
2643
      new(zone) HConstant(1) : new(zone) HConstant(0);
2644
  } else if (handle->IsUndefined()) {
2645
    res = new(zone) HConstant(OS::nan_value());
2646
  } else if (handle->IsNull()) {
2647
    res = new(zone) HConstant(0);
2648
  }
2649
  return Maybe<HConstant*>(res != NULL, res);
2650
}
2651

    
2652

    
2653
void HConstant::PrintDataTo(StringStream* stream) {
2654
  if (has_int32_value_) {
2655
    stream->Add("%d ", int32_value_);
2656
  } else if (has_double_value_) {
2657
    stream->Add("%f ", FmtElm(double_value_));
2658
  } else if (has_external_reference_value_) {
2659
    stream->Add("%p ", reinterpret_cast<void*>(
2660
            external_reference_value_.address()));
2661
  } else {
2662
    handle(Isolate::Current())->ShortPrint(stream);
2663
  }
2664
}
2665

    
2666

    
2667
void HBinaryOperation::PrintDataTo(StringStream* stream) {
2668
  left()->PrintNameTo(stream);
2669
  stream->Add(" ");
2670
  right()->PrintNameTo(stream);
2671
  if (CheckFlag(kCanOverflow)) stream->Add(" !");
2672
  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
2673
}
2674

    
2675

    
2676
void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
2677
  ASSERT(CheckFlag(kFlexibleRepresentation));
2678
  Representation new_rep = RepresentationFromInputs();
2679
  UpdateRepresentation(new_rep, h_infer, "inputs");
2680

    
2681
  if (representation().IsSmi() && HasNonSmiUse()) {
2682
    UpdateRepresentation(
2683
        Representation::Integer32(), h_infer, "use requirements");
2684
  }
2685

    
2686
  if (observed_output_representation_.IsNone()) {
2687
    new_rep = RepresentationFromUses();
2688
    UpdateRepresentation(new_rep, h_infer, "uses");
2689
  } else {
2690
    new_rep = RepresentationFromOutput();
2691
    UpdateRepresentation(new_rep, h_infer, "output");
2692
  }
2693
}
2694

    
2695

    
2696
Representation HBinaryOperation::RepresentationFromInputs() {
2697
  // Determine the worst case of observed input representations and
2698
  // the currently assumed output representation.
2699
  Representation rep = representation();
2700
  for (int i = 1; i <= 2; ++i) {
2701
    rep = rep.generalize(observed_input_representation(i));
2702
  }
2703
  // If any of the actual input representation is more general than what we
2704
  // have so far but not Tagged, use that representation instead.
2705
  Representation left_rep = left()->representation();
2706
  Representation right_rep = right()->representation();
2707
  if (!left_rep.IsTagged()) rep = rep.generalize(left_rep);
2708
  if (!right_rep.IsTagged()) rep = rep.generalize(right_rep);
2709

    
2710
  return rep;
2711
}
2712

    
2713

    
2714
bool HBinaryOperation::IgnoreObservedOutputRepresentation(
2715
    Representation current_rep) {
2716
  return ((current_rep.IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) ||
2717
          (current_rep.IsSmi() && CheckUsesForFlag(kTruncatingToSmi))) &&
2718
         // Mul in Integer32 mode would be too precise.
2719
         (!this->IsMul() || HMul::cast(this)->MulMinusOne());
2720
}
2721

    
2722

    
2723
Representation HBinaryOperation::RepresentationFromOutput() {
2724
  Representation rep = representation();
2725
  // Consider observed output representation, but ignore it if it's Double,
2726
  // this instruction is not a division, and all its uses are truncating
2727
  // to Integer32.
2728
  if (observed_output_representation_.is_more_general_than(rep) &&
2729
      !IgnoreObservedOutputRepresentation(rep)) {
2730
    return observed_output_representation_;
2731
  }
2732
  return Representation::None();
2733
}
2734

    
2735

    
2736
void HBinaryOperation::AssumeRepresentation(Representation r) {
2737
  set_observed_input_representation(1, r);
2738
  set_observed_input_representation(2, r);
2739
  HValue::AssumeRepresentation(r);
2740
}
2741

    
2742

    
2743
void HMathMinMax::InferRepresentation(HInferRepresentationPhase* h_infer) {
2744
  ASSERT(CheckFlag(kFlexibleRepresentation));
2745
  Representation new_rep = RepresentationFromInputs();
2746
  UpdateRepresentation(new_rep, h_infer, "inputs");
2747
  // Do not care about uses.
2748
}
2749

    
2750

    
2751
Range* HBitwise::InferRange(Zone* zone) {
2752
  if (op() == Token::BIT_XOR) {
2753
    if (left()->HasRange() && right()->HasRange()) {
2754
      // The maximum value has the high bit, and all bits below, set:
2755
      // (1 << high) - 1.
2756
      // If the range can be negative, the minimum int is a negative number with
2757
      // the high bit, and all bits below, unset:
2758
      // -(1 << high).
2759
      // If it cannot be negative, conservatively choose 0 as minimum int.
2760
      int64_t left_upper = left()->range()->upper();
2761
      int64_t left_lower = left()->range()->lower();
2762
      int64_t right_upper = right()->range()->upper();
2763
      int64_t right_lower = right()->range()->lower();
2764

    
2765
      if (left_upper < 0) left_upper = ~left_upper;
2766
      if (left_lower < 0) left_lower = ~left_lower;
2767
      if (right_upper < 0) right_upper = ~right_upper;
2768
      if (right_lower < 0) right_lower = ~right_lower;
2769

    
2770
      int high = MostSignificantBit(
2771
          static_cast<uint32_t>(
2772
              left_upper | left_lower | right_upper | right_lower));
2773

    
2774
      int64_t limit = 1;
2775
      limit <<= high;
2776
      int32_t min = (left()->range()->CanBeNegative() ||
2777
                     right()->range()->CanBeNegative())
2778
                    ? static_cast<int32_t>(-limit) : 0;
2779
      return new(zone) Range(min, static_cast<int32_t>(limit - 1));
2780
    }
2781
    Range* result = HValue::InferRange(zone);
2782
    result->set_can_be_minus_zero(false);
2783
    return result;
2784
  }
2785
  const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
2786
  int32_t left_mask = (left()->range() != NULL)
2787
      ? left()->range()->Mask()
2788
      : kDefaultMask;
2789
  int32_t right_mask = (right()->range() != NULL)
2790
      ? right()->range()->Mask()
2791
      : kDefaultMask;
2792
  int32_t result_mask = (op() == Token::BIT_AND)
2793
      ? left_mask & right_mask
2794
      : left_mask | right_mask;
2795
  if (result_mask >= 0) return new(zone) Range(0, result_mask);
2796

    
2797
  Range* result = HValue::InferRange(zone);
2798
  result->set_can_be_minus_zero(false);
2799
  return result;
2800
}
2801

    
2802

    
2803
Range* HSar::InferRange(Zone* zone) {
2804
  if (right()->IsConstant()) {
2805
    HConstant* c = HConstant::cast(right());
2806
    if (c->HasInteger32Value()) {
2807
      Range* result = (left()->range() != NULL)
2808
          ? left()->range()->Copy(zone)
2809
          : new(zone) Range();
2810
      result->Sar(c->Integer32Value());
2811
      return result;
2812
    }
2813
  }
2814
  return HValue::InferRange(zone);
2815
}
2816

    
2817

    
2818
Range* HShr::InferRange(Zone* zone) {
2819
  if (right()->IsConstant()) {
2820
    HConstant* c = HConstant::cast(right());
2821
    if (c->HasInteger32Value()) {
2822
      int shift_count = c->Integer32Value() & 0x1f;
2823
      if (left()->range()->CanBeNegative()) {
2824
        // Only compute bounds if the result always fits into an int32.
2825
        return (shift_count >= 1)
2826
            ? new(zone) Range(0,
2827
                              static_cast<uint32_t>(0xffffffff) >> shift_count)
2828
            : new(zone) Range();
2829
      } else {
2830
        // For positive inputs we can use the >> operator.
2831
        Range* result = (left()->range() != NULL)
2832
            ? left()->range()->Copy(zone)
2833
            : new(zone) Range();
2834
        result->Sar(c->Integer32Value());
2835
        return result;
2836
      }
2837
    }
2838
  }
2839
  return HValue::InferRange(zone);
2840
}
2841

    
2842

    
2843
Range* HShl::InferRange(Zone* zone) {
2844
  if (right()->IsConstant()) {
2845
    HConstant* c = HConstant::cast(right());
2846
    if (c->HasInteger32Value()) {
2847
      Range* result = (left()->range() != NULL)
2848
          ? left()->range()->Copy(zone)
2849
          : new(zone) Range();
2850
      result->Shl(c->Integer32Value());
2851
      return result;
2852
    }
2853
  }
2854
  return HValue::InferRange(zone);
2855
}
2856

    
2857

    
2858
Range* HLoadNamedField::InferRange(Zone* zone) {
2859
  if (access().representation().IsByte()) {
2860
    return new(zone) Range(0, 255);
2861
  }
2862
  if (access().IsStringLength()) {
2863
    return new(zone) Range(0, String::kMaxLength);
2864
  }
2865
  return HValue::InferRange(zone);
2866
}
2867

    
2868

    
2869
Range* HLoadKeyed::InferRange(Zone* zone) {
2870
  switch (elements_kind()) {
2871
    case EXTERNAL_PIXEL_ELEMENTS:
2872
      return new(zone) Range(0, 255);
2873
    case EXTERNAL_BYTE_ELEMENTS:
2874
      return new(zone) Range(-128, 127);
2875
    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2876
      return new(zone) Range(0, 255);
2877
    case EXTERNAL_SHORT_ELEMENTS:
2878
      return new(zone) Range(-32768, 32767);
2879
    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2880
      return new(zone) Range(0, 65535);
2881
    default:
2882
      return HValue::InferRange(zone);
2883
  }
2884
}
2885

    
2886

    
2887
void HCompareGeneric::PrintDataTo(StringStream* stream) {
2888
  stream->Add(Token::Name(token()));
2889
  stream->Add(" ");
2890
  HBinaryOperation::PrintDataTo(stream);
2891
}
2892

    
2893

    
2894
void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
2895
  stream->Add(Token::Name(token()));
2896
  stream->Add(" ");
2897
  HControlInstruction::PrintDataTo(stream);
2898
}
2899

    
2900

    
2901
void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
2902
  stream->Add(Token::Name(token()));
2903
  stream->Add(" ");
2904
  left()->PrintNameTo(stream);
2905
  stream->Add(" ");
2906
  right()->PrintNameTo(stream);
2907
  HControlInstruction::PrintDataTo(stream);
2908
}
2909

    
2910

    
2911
void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
2912
  left()->PrintNameTo(stream);
2913
  stream->Add(" ");
2914
  right()->PrintNameTo(stream);
2915
  HControlInstruction::PrintDataTo(stream);
2916
}
2917

    
2918

    
2919
bool HCompareObjectEqAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
2920
  if (left()->IsConstant() && right()->IsConstant()) {
2921
    bool comparison_result =
2922
        HConstant::cast(left())->Equals(HConstant::cast(right()));
2923
    *block = comparison_result
2924
        ? FirstSuccessor()
2925
        : SecondSuccessor();
2926
    return true;
2927
  }
2928
  *block = NULL;
2929
  return false;
2930
}
2931

    
2932

    
2933
void HCompareHoleAndBranch::InferRepresentation(
2934
    HInferRepresentationPhase* h_infer) {
2935
  ChangeRepresentation(value()->representation());
2936
}
2937

    
2938

    
2939
void HGoto::PrintDataTo(StringStream* stream) {
2940
  stream->Add("B%d", SuccessorAt(0)->block_id());
2941
}
2942

    
2943

    
2944
void HCompareNumericAndBranch::InferRepresentation(
2945
    HInferRepresentationPhase* h_infer) {
2946
  Representation left_rep = left()->representation();
2947
  Representation right_rep = right()->representation();
2948
  Representation observed_left = observed_input_representation(0);
2949
  Representation observed_right = observed_input_representation(1);
2950

    
2951
  Representation rep = Representation::None();
2952
  rep = rep.generalize(observed_left);
2953
  rep = rep.generalize(observed_right);
2954
  if (rep.IsNone() || rep.IsSmiOrInteger32()) {
2955
    if (!left_rep.IsTagged()) rep = rep.generalize(left_rep);
2956
    if (!right_rep.IsTagged()) rep = rep.generalize(right_rep);
2957
  } else {
2958
    rep = Representation::Double();
2959
  }
2960

    
2961
  if (rep.IsDouble()) {
2962
    // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
2963
    // and !=) have special handling of undefined, e.g. undefined == undefined
2964
    // is 'true'. Relational comparisons have a different semantic, first
2965
    // calling ToPrimitive() on their arguments.  The standard Crankshaft
2966
    // tagged-to-double conversion to ensure the HCompareNumericAndBranch's
2967
    // inputs are doubles caused 'undefined' to be converted to NaN. That's
2968
    // compatible out-of-the box with ordered relational comparisons (<, >, <=,
2969
    // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
2970
    // it is not consistent with the spec. For example, it would cause undefined
2971
    // == undefined (should be true) to be evaluated as NaN == NaN
2972
    // (false). Therefore, any comparisons other than ordered relational
2973
    // comparisons must cause a deopt when one of their arguments is undefined.
2974
    // See also v8:1434
2975
    if (Token::IsOrderedRelationalCompareOp(token_)) {
2976
      SetFlag(kAllowUndefinedAsNaN);
2977
    }
2978
  }
2979
  ChangeRepresentation(rep);
2980
}
2981

    
2982

    
2983
void HParameter::PrintDataTo(StringStream* stream) {
2984
  stream->Add("%u", index());
2985
}
2986

    
2987

    
2988
void HLoadNamedField::PrintDataTo(StringStream* stream) {
2989
  object()->PrintNameTo(stream);
2990
  access_.PrintTo(stream);
2991
}
2992

    
2993

    
2994
HCheckMaps* HCheckMaps::New(Zone* zone,
2995
                            HValue* context,
2996
                            HValue* value,
2997
                            Handle<Map> map,
2998
                            CompilationInfo* info,
2999
                            HValue* typecheck) {
3000
  HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
3001
  check_map->Add(map, zone);
3002
  if (map->CanOmitMapChecks() &&
3003
      value->IsConstant() &&
3004
      HConstant::cast(value)->HasMap(map)) {
3005
    // TODO(titzer): collect dependent map checks into a list.
3006
    check_map->omit_ = true;
3007
    if (map->CanTransition()) {
3008
      map->AddDependentCompilationInfo(
3009
          DependentCode::kPrototypeCheckGroup, info);
3010
    }
3011
  }
3012
  return check_map;
3013
}
3014

    
3015

    
3016
void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
3017
  object()->PrintNameTo(stream);
3018
  stream->Add(".");
3019
  stream->Add(*String::cast(*name())->ToCString());
3020
}
3021

    
3022

    
3023
void HLoadKeyed::PrintDataTo(StringStream* stream) {
3024
  if (!is_external()) {
3025
    elements()->PrintNameTo(stream);
3026
  } else {
3027
    ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
3028
           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
3029
    elements()->PrintNameTo(stream);
3030
    stream->Add(".");
3031
    stream->Add(ElementsKindToString(elements_kind()));
3032
  }
3033

    
3034
  stream->Add("[");
3035
  key()->PrintNameTo(stream);
3036
  if (IsDehoisted()) {
3037
    stream->Add(" + %d]", index_offset());
3038
  } else {
3039
    stream->Add("]");
3040
  }
3041

    
3042
  if (HasDependency()) {
3043
    stream->Add(" ");
3044
    dependency()->PrintNameTo(stream);
3045
  }
3046

    
3047
  if (RequiresHoleCheck()) {
3048
    stream->Add(" check_hole");
3049
  }
3050
}
3051

    
3052

    
3053
bool HLoadKeyed::UsesMustHandleHole() const {
3054
  if (IsFastPackedElementsKind(elements_kind())) {
3055
    return false;
3056
  }
3057

    
3058
  if (IsExternalArrayElementsKind(elements_kind())) {
3059
    return false;
3060
  }
3061

    
3062
  if (hole_mode() == ALLOW_RETURN_HOLE) {
3063
    if (IsFastDoubleElementsKind(elements_kind())) {
3064
      return AllUsesCanTreatHoleAsNaN();
3065
    }
3066
    return true;
3067
  }
3068

    
3069
  if (IsFastDoubleElementsKind(elements_kind())) {
3070
    return false;
3071
  }
3072

    
3073
  // Holes are only returned as tagged values.
3074
  if (!representation().IsTagged()) {
3075
    return false;
3076
  }
3077

    
3078
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3079
    HValue* use = it.value();
3080
    if (!use->IsChange()) return false;
3081
  }
3082

    
3083
  return true;
3084
}
3085

    
3086

    
3087
bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const {
3088
  return IsFastDoubleElementsKind(elements_kind()) &&
3089
      CheckUsesForFlag(HValue::kAllowUndefinedAsNaN);
3090
}
3091

    
3092

    
3093
bool HLoadKeyed::RequiresHoleCheck() const {
3094
  if (IsFastPackedElementsKind(elements_kind())) {
3095
    return false;
3096
  }
3097

    
3098
  if (IsExternalArrayElementsKind(elements_kind())) {
3099
    return false;
3100
  }
3101

    
3102
  return !UsesMustHandleHole();
3103
}
3104

    
3105

    
3106
void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
3107
  object()->PrintNameTo(stream);
3108
  stream->Add("[");
3109
  key()->PrintNameTo(stream);
3110
  stream->Add("]");
3111
}
3112

    
3113

    
3114
HValue* HLoadKeyedGeneric::Canonicalize() {
3115
  // Recognize generic keyed loads that use property name generated
3116
  // by for-in statement as a key and rewrite them into fast property load
3117
  // by index.
3118
  if (key()->IsLoadKeyed()) {
3119
    HLoadKeyed* key_load = HLoadKeyed::cast(key());
3120
    if (key_load->elements()->IsForInCacheArray()) {
3121
      HForInCacheArray* names_cache =
3122
          HForInCacheArray::cast(key_load->elements());
3123

    
3124
      if (names_cache->enumerable() == object()) {
3125
        HForInCacheArray* index_cache =
3126
            names_cache->index_cache();
3127
        HCheckMapValue* map_check =
3128
            HCheckMapValue::New(block()->graph()->zone(),
3129
                                block()->graph()->GetInvalidContext(),
3130
                                object(),
3131
                                names_cache->map());
3132
        HInstruction* index = HLoadKeyed::New(
3133
            block()->graph()->zone(),
3134
            block()->graph()->GetInvalidContext(),
3135
            index_cache,
3136
            key_load->key(),
3137
            key_load->key(),
3138
            key_load->elements_kind());
3139
        map_check->InsertBefore(this);
3140
        index->InsertBefore(this);
3141
        HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
3142
            object(), index);
3143
        load->InsertBefore(this);
3144
        return load;
3145
      }
3146
    }
3147
  }
3148

    
3149
  return this;
3150
}
3151

    
3152

    
3153
void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
3154
  object()->PrintNameTo(stream);
3155
  stream->Add(".");
3156
  ASSERT(name()->IsString());
3157
  stream->Add(*String::cast(*name())->ToCString());
3158
  stream->Add(" = ");
3159
  value()->PrintNameTo(stream);
3160
}
3161

    
3162

    
3163
void HStoreNamedField::PrintDataTo(StringStream* stream) {
3164
  object()->PrintNameTo(stream);
3165
  access_.PrintTo(stream);
3166
  stream->Add(" = ");
3167
  value()->PrintNameTo(stream);
3168
  if (NeedsWriteBarrier()) {
3169
    stream->Add(" (write-barrier)");
3170
  }
3171
  if (has_transition()) {
3172
    stream->Add(" (transition map %p)", *transition_map());
3173
  }
3174
}
3175

    
3176

    
3177
void HStoreKeyed::PrintDataTo(StringStream* stream) {
3178
  if (!is_external()) {
3179
    elements()->PrintNameTo(stream);
3180
  } else {
3181
    elements()->PrintNameTo(stream);
3182
    stream->Add(".");
3183
    stream->Add(ElementsKindToString(elements_kind()));
3184
    ASSERT(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
3185
           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
3186
  }
3187

    
3188
  stream->Add("[");
3189
  key()->PrintNameTo(stream);
3190
  if (IsDehoisted()) {
3191
    stream->Add(" + %d] = ", index_offset());
3192
  } else {
3193
    stream->Add("] = ");
3194
  }
3195

    
3196
  value()->PrintNameTo(stream);
3197
}
3198

    
3199

    
3200
void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
3201
  object()->PrintNameTo(stream);
3202
  stream->Add("[");
3203
  key()->PrintNameTo(stream);
3204
  stream->Add("] = ");
3205
  value()->PrintNameTo(stream);
3206
}
3207

    
3208

    
3209
void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
3210
  object()->PrintNameTo(stream);
3211
  ElementsKind from_kind = original_map().handle()->elements_kind();
3212
  ElementsKind to_kind = transitioned_map().handle()->elements_kind();
3213
  stream->Add(" %p [%s] -> %p [%s]",
3214
              *original_map().handle(),
3215
              ElementsAccessor::ForKind(from_kind)->name(),
3216
              *transitioned_map().handle(),
3217
              ElementsAccessor::ForKind(to_kind)->name());
3218
  if (IsSimpleMapChangeTransition(from_kind, to_kind)) stream->Add(" (simple)");
3219
}
3220

    
3221

    
3222
void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
3223
  stream->Add("[%p]", *cell().handle());
3224
  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
3225
  if (details_.IsReadOnly()) stream->Add(" (read-only)");
3226
}
3227

    
3228

    
3229
bool HLoadGlobalCell::RequiresHoleCheck() const {
3230
  if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
3231
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
3232
    HValue* use = it.value();
3233
    if (!use->IsChange()) return true;
3234
  }
3235
  return false;
3236
}
3237

    
3238

    
3239
void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
3240
  stream->Add("%o ", *name());
3241
}
3242

    
3243

    
3244
void HInnerAllocatedObject::PrintDataTo(StringStream* stream) {
3245
  base_object()->PrintNameTo(stream);
3246
  stream->Add(" offset %d", offset());
3247
}
3248

    
3249

    
3250
void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
3251
  stream->Add("[%p] = ", *cell().handle());
3252
  value()->PrintNameTo(stream);
3253
  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
3254
  if (details_.IsReadOnly()) stream->Add(" (read-only)");
3255
}
3256

    
3257

    
3258
void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
3259
  stream->Add("%o = ", *name());
3260
  value()->PrintNameTo(stream);
3261
}
3262

    
3263

    
3264
void HLoadContextSlot::PrintDataTo(StringStream* stream) {
3265
  value()->PrintNameTo(stream);
3266
  stream->Add("[%d]", slot_index());
3267
}
3268

    
3269

    
3270
void HStoreContextSlot::PrintDataTo(StringStream* stream) {
3271
  context()->PrintNameTo(stream);
3272
  stream->Add("[%d] = ", slot_index());
3273
  value()->PrintNameTo(stream);
3274
}
3275

    
3276

    
3277
// Implementation of type inference and type conversions. Calculates
3278
// the inferred type of this instruction based on the input operands.
3279

    
3280
HType HValue::CalculateInferredType() {
3281
  return type_;
3282
}
3283

    
3284

    
3285
HType HPhi::CalculateInferredType() {
3286
  if (OperandCount() == 0) return HType::Tagged();
3287
  HType result = OperandAt(0)->type();
3288
  for (int i = 1; i < OperandCount(); ++i) {
3289
    HType current = OperandAt(i)->type();
3290
    result = result.Combine(current);
3291
  }
3292
  return result;
3293
}
3294

    
3295

    
3296
HType HChange::CalculateInferredType() {
3297
  if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
3298
  return type();
3299
}
3300

    
3301

    
3302
Representation HUnaryMathOperation::RepresentationFromInputs() {
3303
  Representation rep = representation();
3304
  // If any of the actual input representation is more general than what we
3305
  // have so far but not Tagged, use that representation instead.
3306
  Representation input_rep = value()->representation();
3307
  if (!input_rep.IsTagged()) {
3308
    rep = rep.generalize(input_rep);
3309
  }
3310
  return rep;
3311
}
3312

    
3313

    
3314
void HAllocate::HandleSideEffectDominator(GVNFlag side_effect,
3315
                                          HValue* dominator) {
3316
  ASSERT(side_effect == kChangesNewSpacePromotion);
3317
  Zone* zone = block()->zone();
3318
  if (!FLAG_use_allocation_folding) return;
3319

    
3320
  // Try to fold allocations together with their dominating allocations.
3321
  if (!dominator->IsAllocate()) {
3322
    if (FLAG_trace_allocation_folding) {
3323
      PrintF("#%d (%s) cannot fold into #%d (%s)\n",
3324
          id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3325
    }
3326
    return;
3327
  }
3328

    
3329
  HAllocate* dominator_allocate = HAllocate::cast(dominator);
3330
  HValue* dominator_size = dominator_allocate->size();
3331
  HValue* current_size = size();
3332

    
3333
  // TODO(hpayer): Add support for non-constant allocation in dominator.
3334
  if (!current_size->IsInteger32Constant() ||
3335
      !dominator_size->IsInteger32Constant()) {
3336
    if (FLAG_trace_allocation_folding) {
3337
      PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n",
3338
          id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3339
    }
3340
    return;
3341
  }
3342

    
3343
  dominator_allocate = GetFoldableDominator(dominator_allocate);
3344
  if (dominator_allocate == NULL) {
3345
    return;
3346
  }
3347

    
3348
  ASSERT((IsNewSpaceAllocation() &&
3349
         dominator_allocate->IsNewSpaceAllocation()) ||
3350
         (IsOldDataSpaceAllocation() &&
3351
         dominator_allocate->IsOldDataSpaceAllocation()) ||
3352
         (IsOldPointerSpaceAllocation() &&
3353
         dominator_allocate->IsOldPointerSpaceAllocation()));
3354

    
3355
  // First update the size of the dominator allocate instruction.
3356
  dominator_size = dominator_allocate->size();
3357
  int32_t original_object_size =
3358
      HConstant::cast(dominator_size)->GetInteger32Constant();
3359
  int32_t dominator_size_constant = original_object_size;
3360
  int32_t current_size_constant =
3361
      HConstant::cast(current_size)->GetInteger32Constant();
3362
  int32_t new_dominator_size = dominator_size_constant + current_size_constant;
3363

    
3364
  if (MustAllocateDoubleAligned()) {
3365
    if (!dominator_allocate->MustAllocateDoubleAligned()) {
3366
      dominator_allocate->MakeDoubleAligned();
3367
    }
3368
    if ((dominator_size_constant & kDoubleAlignmentMask) != 0) {
3369
      dominator_size_constant += kDoubleSize / 2;
3370
      new_dominator_size += kDoubleSize / 2;
3371
    }
3372
  }
3373

    
3374
  if (new_dominator_size > Page::kMaxNonCodeHeapObjectSize) {
3375
    if (FLAG_trace_allocation_folding) {
3376
      PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n",
3377
          id(), Mnemonic(), dominator_allocate->id(),
3378
          dominator_allocate->Mnemonic(), new_dominator_size);
3379
    }
3380
    return;
3381
  }
3382

    
3383
  HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore(
3384
      zone,
3385
      context(),
3386
      new_dominator_size,
3387
      Representation::None(),
3388
      dominator_allocate);
3389
  dominator_allocate->UpdateSize(new_dominator_size_constant);
3390

    
3391
#ifdef VERIFY_HEAP
3392
  if (FLAG_verify_heap && dominator_allocate->IsNewSpaceAllocation()) {
3393
    dominator_allocate->MakePrefillWithFiller();
3394
  } else {
3395
    // TODO(hpayer): This is a short-term hack to make allocation mementos
3396
    // work again in new space.
3397
    dominator_allocate->ClearNextMapWord(original_object_size);
3398
  }
3399
#else
3400
  // TODO(hpayer): This is a short-term hack to make allocation mementos
3401
  // work again in new space.
3402
  dominator_allocate->ClearNextMapWord(original_object_size);
3403
#endif
3404

    
3405
  dominator_allocate->clear_next_map_word_ = clear_next_map_word_;
3406

    
3407
  // After that replace the dominated allocate instruction.
3408
  HInstruction* dominated_allocate_instr =
3409
      HInnerAllocatedObject::New(zone,
3410
                                 context(),
3411
                                 dominator_allocate,
3412
                                 dominator_size_constant,
3413
                                 type());
3414
  dominated_allocate_instr->InsertBefore(this);
3415
  DeleteAndReplaceWith(dominated_allocate_instr);
3416
  if (FLAG_trace_allocation_folding) {
3417
    PrintF("#%d (%s) folded into #%d (%s)\n",
3418
        id(), Mnemonic(), dominator_allocate->id(),
3419
        dominator_allocate->Mnemonic());
3420
  }
3421
}
3422

    
3423

    
3424
HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) {
3425
  if (!IsFoldable(dominator)) {
3426
    // We cannot hoist old space allocations over new space allocations.
3427
    if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) {
3428
      if (FLAG_trace_allocation_folding) {
3429
        PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n",
3430
            id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3431
      }
3432
      return NULL;
3433
    }
3434

    
3435
    HAllocate* dominator_dominator = dominator->dominating_allocate_;
3436

    
3437
    // We can hoist old data space allocations over an old pointer space
3438
    // allocation and vice versa. For that we have to check the dominator
3439
    // of the dominator allocate instruction.
3440
    if (dominator_dominator == NULL) {
3441
      dominating_allocate_ = dominator;
3442
      if (FLAG_trace_allocation_folding) {
3443
        PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n",
3444
            id(), Mnemonic(), dominator->id(), dominator->Mnemonic());
3445
      }
3446
      return NULL;
3447
    }
3448

    
3449
    // We can just fold old space allocations that are in the same basic block,
3450
    // since it is not guaranteed that we fill up the whole allocated old
3451
    // space memory.
3452
    // TODO(hpayer): Remove this limitation and add filler maps for each each
3453
    // allocation as soon as we have store elimination.
3454
    if (block()->block_id() != dominator_dominator->block()->block_id()) {
3455
      if (FLAG_trace_allocation_folding) {
3456
        PrintF("#%d (%s) cannot fold into #%d (%s), different basic blocks\n",
3457
            id(), Mnemonic(), dominator_dominator->id(),
3458
            dominator_dominator->Mnemonic());
3459
      }
3460
      return NULL;
3461
    }
3462

    
3463
    ASSERT((IsOldDataSpaceAllocation() &&
3464
           dominator_dominator->IsOldDataSpaceAllocation()) ||
3465
           (IsOldPointerSpaceAllocation() &&
3466
           dominator_dominator->IsOldPointerSpaceAllocation()));
3467

    
3468
    int32_t current_size = HConstant::cast(size())->GetInteger32Constant();
3469
    HStoreNamedField* dominator_free_space_size =
3470
        dominator->filler_free_space_size_;
3471
    if (dominator_free_space_size != NULL) {
3472
      // We already hoisted one old space allocation, i.e., we already installed
3473
      // a filler map. Hence, we just have to update the free space size.
3474
      dominator->UpdateFreeSpaceFiller(current_size);
3475
    } else {
3476
      // This is the first old space allocation that gets hoisted. We have to
3477
      // install a filler map since the follwing allocation may cause a GC.
3478
      dominator->CreateFreeSpaceFiller(current_size);
3479
    }
3480

    
3481
    // We can hoist the old space allocation over the actual dominator.
3482
    return dominator_dominator;
3483
  }
3484
  return dominator;
3485
}
3486

    
3487

    
3488
void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) {
3489
  ASSERT(filler_free_space_size_ != NULL);
3490
  Zone* zone = block()->zone();
3491
  // We must explicitly force Smi representation here because on x64 we
3492
  // would otherwise automatically choose int32, but the actual store
3493
  // requires a Smi-tagged value.
3494
  HConstant* new_free_space_size = HConstant::CreateAndInsertBefore(
3495
      zone,
3496
      context(),
3497
      filler_free_space_size_->value()->GetInteger32Constant() +
3498
          free_space_size,
3499
      Representation::Smi(),
3500
      filler_free_space_size_);
3501
  filler_free_space_size_->UpdateValue(new_free_space_size);
3502
}
3503

    
3504

    
3505
void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) {
3506
  ASSERT(filler_free_space_size_ == NULL);
3507
  Zone* zone = block()->zone();
3508
  int32_t dominator_size =
3509
      HConstant::cast(dominating_allocate_->size())->GetInteger32Constant();
3510
  HInstruction* free_space_instr =
3511
      HInnerAllocatedObject::New(zone, context(), dominating_allocate_,
3512
      dominator_size, type());
3513
  free_space_instr->InsertBefore(this);
3514
  HConstant* filler_map = HConstant::New(
3515
      zone,
3516
      context(),
3517
      isolate()->factory()->free_space_map());
3518
  filler_map->FinalizeUniqueness();  // TODO(titzer): should be init'd a'ready
3519
  filler_map->InsertAfter(free_space_instr);
3520
  HInstruction* store_map = HStoreNamedField::New(zone, context(),
3521
      free_space_instr, HObjectAccess::ForMap(), filler_map);
3522
  store_map->SetFlag(HValue::kHasNoObservableSideEffects);
3523
  store_map->InsertAfter(filler_map);
3524

    
3525
  // We must explicitly force Smi representation here because on x64 we
3526
  // would otherwise automatically choose int32, but the actual store
3527
  // requires a Smi-tagged value.
3528
  HConstant* filler_size = HConstant::CreateAndInsertAfter(
3529
      zone, context(), free_space_size, Representation::Smi(), store_map);
3530
  // Must force Smi representation for x64 (see comment above).
3531
  HObjectAccess access =
3532
      HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset,
3533
          Representation::Smi());
3534
  HStoreNamedField* store_size = HStoreNamedField::New(zone, context(),
3535
      free_space_instr, access, filler_size);
3536
  store_size->SetFlag(HValue::kHasNoObservableSideEffects);
3537
  store_size->InsertAfter(filler_size);
3538
  filler_free_space_size_ = store_size;
3539
}
3540

    
3541

    
3542
void HAllocate::ClearNextMapWord(int offset) {
3543
  if (clear_next_map_word_) {
3544
    Zone* zone = block()->zone();
3545
    HObjectAccess access = HObjectAccess::ForJSObjectOffset(offset);
3546
    HStoreNamedField* clear_next_map =
3547
        HStoreNamedField::New(zone, context(), this, access,
3548
            block()->graph()->GetConstantNull());
3549
    clear_next_map->ClearAllSideEffects();
3550
    clear_next_map->InsertAfter(this);
3551
  }
3552
}
3553

    
3554

    
3555
void HAllocate::PrintDataTo(StringStream* stream) {
3556
  size()->PrintNameTo(stream);
3557
  stream->Add(" (");
3558
  if (IsNewSpaceAllocation()) stream->Add("N");
3559
  if (IsOldPointerSpaceAllocation()) stream->Add("P");
3560
  if (IsOldDataSpaceAllocation()) stream->Add("D");
3561
  if (MustAllocateDoubleAligned()) stream->Add("A");
3562
  if (MustPrefillWithFiller()) stream->Add("F");
3563
  stream->Add(")");
3564
}
3565

    
3566

    
3567
HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
3568
    BitVector* visited) {
3569
  visited->Add(id());
3570
  if (representation().IsSmiOrInteger32() &&
3571
      !value()->representation().Equals(representation())) {
3572
    if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
3573
      SetFlag(kBailoutOnMinusZero);
3574
    }
3575
  }
3576
  if (RequiredInputRepresentation(0).IsSmiOrInteger32() &&
3577
      representation().Equals(RequiredInputRepresentation(0))) {
3578
    return value();
3579
  }
3580
  return NULL;
3581
}
3582

    
3583

    
3584
HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3585
  visited->Add(id());
3586
  if (from().IsSmiOrInteger32()) return NULL;
3587
  if (CanTruncateToInt32()) return NULL;
3588
  if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
3589
    SetFlag(kBailoutOnMinusZero);
3590
  }
3591
  ASSERT(!from().IsSmiOrInteger32() || !to().IsSmiOrInteger32());
3592
  return NULL;
3593
}
3594

    
3595

    
3596
HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
3597
    BitVector* visited) {
3598
  visited->Add(id());
3599
  return value();
3600
}
3601

    
3602

    
3603
HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3604
  visited->Add(id());
3605
  if (range() == NULL || range()->CanBeMinusZero()) {
3606
    SetFlag(kBailoutOnMinusZero);
3607
    return left();
3608
  }
3609
  return NULL;
3610
}
3611

    
3612

    
3613
HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3614
  visited->Add(id());
3615
  if (range() == NULL || range()->CanBeMinusZero()) {
3616
    SetFlag(kBailoutOnMinusZero);
3617
  }
3618
  return NULL;
3619
}
3620

    
3621

    
3622
HValue* HMathFloorOfDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3623
  visited->Add(id());
3624
  SetFlag(kBailoutOnMinusZero);
3625
  return NULL;
3626
}
3627

    
3628

    
3629
HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3630
  visited->Add(id());
3631
  if (range() == NULL || range()->CanBeMinusZero()) {
3632
    SetFlag(kBailoutOnMinusZero);
3633
  }
3634
  return NULL;
3635
}
3636

    
3637

    
3638
HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3639
  visited->Add(id());
3640
  // Propagate to the left argument. If the left argument cannot be -0, then
3641
  // the result of the add operation cannot be either.
3642
  if (range() == NULL || range()->CanBeMinusZero()) {
3643
    return left();
3644
  }
3645
  return NULL;
3646
}
3647

    
3648

    
3649
HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
3650
  visited->Add(id());
3651
  // Propagate to the left argument. If the left argument cannot be -0, then
3652
  // the result of the sub operation cannot be either.
3653
  if (range() == NULL || range()->CanBeMinusZero()) {
3654
    return left();
3655
  }
3656
  return NULL;
3657
}
3658

    
3659

    
3660
bool HStoreKeyed::NeedsCanonicalization() {
3661
  // If value is an integer or smi or comes from the result of a keyed load or
3662
  // constant then it is either be a non-hole value or in the case of a constant
3663
  // the hole is only being stored explicitly: no need for canonicalization.
3664
  //
3665
  // The exception to that is keyed loads from external float or double arrays:
3666
  // these can load arbitrary representation of NaN.
3667

    
3668
  if (value()->IsConstant()) {
3669
    return false;
3670
  }
3671

    
3672
  if (value()->IsLoadKeyed()) {
3673
    return IsExternalFloatOrDoubleElementsKind(
3674
        HLoadKeyed::cast(value())->elements_kind());
3675
  }
3676

    
3677
  if (value()->IsChange()) {
3678
    if (HChange::cast(value())->from().IsSmiOrInteger32()) {
3679
      return false;
3680
    }
3681
    if (HChange::cast(value())->value()->type().IsSmi()) {
3682
      return false;
3683
    }
3684
  }
3685
  return true;
3686
}
3687

    
3688

    
3689
#define H_CONSTANT_INT(val)                                                    \
3690
HConstant::New(zone, context, static_cast<int32_t>(val))
3691
#define H_CONSTANT_DOUBLE(val)                                                 \
3692
HConstant::New(zone, context, static_cast<double>(val))
3693

    
3694
#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op)                       \
3695
HInstruction* HInstr::New(                                                     \
3696
    Zone* zone, HValue* context, HValue* left, HValue* right) {                \
3697
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {      \
3698
    HConstant* c_left = HConstant::cast(left);                                 \
3699
    HConstant* c_right = HConstant::cast(right);                               \
3700
    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
3701
      double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
3702
      if (TypeInfo::IsInt32Double(double_res)) {                               \
3703
        return H_CONSTANT_INT(double_res);                                     \
3704
      }                                                                        \
3705
      return H_CONSTANT_DOUBLE(double_res);                                    \
3706
    }                                                                          \
3707
  }                                                                            \
3708
  return new(zone) HInstr(context, left, right);                               \
3709
}
3710

    
3711

    
3712
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
3713
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
3714
DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
3715

    
3716
#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
3717

    
3718

    
3719
HInstruction* HStringAdd::New(Zone* zone,
3720
                              HValue* context,
3721
                              HValue* left,
3722
                              HValue* right,
3723
                              StringAddFlags flags) {
3724
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3725
    HConstant* c_right = HConstant::cast(right);
3726
    HConstant* c_left = HConstant::cast(left);
3727
    if (c_left->HasStringValue() && c_right->HasStringValue()) {
3728
      Handle<String> concat = zone->isolate()->factory()->NewFlatConcatString(
3729
          c_left->StringValue(), c_right->StringValue());
3730
      return HConstant::New(zone, context, concat);
3731
    }
3732
  }
3733
  return new(zone) HStringAdd(context, left, right, flags);
3734
}
3735

    
3736

    
3737
HInstruction* HStringCharFromCode::New(
3738
    Zone* zone, HValue* context, HValue* char_code) {
3739
  if (FLAG_fold_constants && char_code->IsConstant()) {
3740
    HConstant* c_code = HConstant::cast(char_code);
3741
    Isolate* isolate = zone->isolate();
3742
    if (c_code->HasNumberValue()) {
3743
      if (std::isfinite(c_code->DoubleValue())) {
3744
        uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
3745
        return HConstant::New(zone, context,
3746
            LookupSingleCharacterStringFromCode(isolate, code));
3747
      }
3748
      return HConstant::New(zone, context, isolate->factory()->empty_string());
3749
    }
3750
  }
3751
  return new(zone) HStringCharFromCode(context, char_code);
3752
}
3753

    
3754

    
3755
HInstruction* HUnaryMathOperation::New(
3756
    Zone* zone, HValue* context, HValue* value, BuiltinFunctionId op) {
3757
  do {
3758
    if (!FLAG_fold_constants) break;
3759
    if (!value->IsConstant()) break;
3760
    HConstant* constant = HConstant::cast(value);
3761
    if (!constant->HasNumberValue()) break;
3762
    double d = constant->DoubleValue();
3763
    if (std::isnan(d)) {  // NaN poisons everything.
3764
      return H_CONSTANT_DOUBLE(OS::nan_value());
3765
    }
3766
    if (std::isinf(d)) {  // +Infinity and -Infinity.
3767
      switch (op) {
3768
        case kMathSin:
3769
        case kMathCos:
3770
        case kMathTan:
3771
          return H_CONSTANT_DOUBLE(OS::nan_value());
3772
        case kMathExp:
3773
          return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
3774
        case kMathLog:
3775
        case kMathSqrt:
3776
          return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value());
3777
        case kMathPowHalf:
3778
        case kMathAbs:
3779
          return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d);
3780
        case kMathRound:
3781
        case kMathFloor:
3782
          return H_CONSTANT_DOUBLE(d);
3783
        default:
3784
          UNREACHABLE();
3785
          break;
3786
      }
3787
    }
3788
    switch (op) {
3789
      case kMathSin:
3790
        return H_CONSTANT_DOUBLE(fast_sin(d));
3791
      case kMathCos:
3792
        return H_CONSTANT_DOUBLE(fast_cos(d));
3793
      case kMathTan:
3794
        return H_CONSTANT_DOUBLE(fast_tan(d));
3795
      case kMathExp:
3796
        return H_CONSTANT_DOUBLE(fast_exp(d));
3797
      case kMathLog:
3798
        return H_CONSTANT_DOUBLE(fast_log(d));
3799
      case kMathSqrt:
3800
        return H_CONSTANT_DOUBLE(fast_sqrt(d));
3801
      case kMathPowHalf:
3802
        return H_CONSTANT_DOUBLE(power_double_double(d, 0.5));
3803
      case kMathAbs:
3804
        return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d);
3805
      case kMathRound:
3806
        // -0.5 .. -0.0 round to -0.0.
3807
        if ((d >= -0.5 && Double(d).Sign() < 0)) return H_CONSTANT_DOUBLE(-0.0);
3808
        // Doubles are represented as Significant * 2 ^ Exponent. If the
3809
        // Exponent is not negative, the double value is already an integer.
3810
        if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d);
3811
        return H_CONSTANT_DOUBLE(floor(d + 0.5));
3812
      case kMathFloor:
3813
        return H_CONSTANT_DOUBLE(floor(d));
3814
      default:
3815
        UNREACHABLE();
3816
        break;
3817
    }
3818
  } while (false);
3819
  return new(zone) HUnaryMathOperation(context, value, op);
3820
}
3821

    
3822

    
3823
HInstruction* HPower::New(Zone* zone,
3824
                          HValue* context,
3825
                          HValue* left,
3826
                          HValue* right) {
3827
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3828
    HConstant* c_left = HConstant::cast(left);
3829
    HConstant* c_right = HConstant::cast(right);
3830
    if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
3831
      double result = power_helper(c_left->DoubleValue(),
3832
                                   c_right->DoubleValue());
3833
      return H_CONSTANT_DOUBLE(std::isnan(result) ?  OS::nan_value() : result);
3834
    }
3835
  }
3836
  return new(zone) HPower(left, right);
3837
}
3838

    
3839

    
3840
HInstruction* HMathMinMax::New(
3841
    Zone* zone, HValue* context, HValue* left, HValue* right, Operation op) {
3842
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3843
    HConstant* c_left = HConstant::cast(left);
3844
    HConstant* c_right = HConstant::cast(right);
3845
    if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
3846
      double d_left = c_left->DoubleValue();
3847
      double d_right = c_right->DoubleValue();
3848
      if (op == kMathMin) {
3849
        if (d_left > d_right) return H_CONSTANT_DOUBLE(d_right);
3850
        if (d_left < d_right) return H_CONSTANT_DOUBLE(d_left);
3851
        if (d_left == d_right) {
3852
          // Handle +0 and -0.
3853
          return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_left
3854
                                                                 : d_right);
3855
        }
3856
      } else {
3857
        if (d_left < d_right) return H_CONSTANT_DOUBLE(d_right);
3858
        if (d_left > d_right) return H_CONSTANT_DOUBLE(d_left);
3859
        if (d_left == d_right) {
3860
          // Handle +0 and -0.
3861
          return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_right
3862
                                                                 : d_left);
3863
        }
3864
      }
3865
      // All comparisons failed, must be NaN.
3866
      return H_CONSTANT_DOUBLE(OS::nan_value());
3867
    }
3868
  }
3869
  return new(zone) HMathMinMax(context, left, right, op);
3870
}
3871

    
3872

    
3873
HInstruction* HMod::New(Zone* zone,
3874
                        HValue* context,
3875
                        HValue* left,
3876
                        HValue* right,
3877
                        Maybe<int> fixed_right_arg) {
3878
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3879
    HConstant* c_left = HConstant::cast(left);
3880
    HConstant* c_right = HConstant::cast(right);
3881
    if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
3882
      int32_t dividend = c_left->Integer32Value();
3883
      int32_t divisor = c_right->Integer32Value();
3884
      if (dividend == kMinInt && divisor == -1) {
3885
        return H_CONSTANT_DOUBLE(-0.0);
3886
      }
3887
      if (divisor != 0) {
3888
        int32_t res = dividend % divisor;
3889
        if ((res == 0) && (dividend < 0)) {
3890
          return H_CONSTANT_DOUBLE(-0.0);
3891
        }
3892
        return H_CONSTANT_INT(res);
3893
      }
3894
    }
3895
  }
3896
  return new(zone) HMod(context, left, right, fixed_right_arg);
3897
}
3898

    
3899

    
3900
HInstruction* HDiv::New(
3901
    Zone* zone, HValue* context, HValue* left, HValue* right) {
3902
  // If left and right are constant values, try to return a constant value.
3903
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3904
    HConstant* c_left = HConstant::cast(left);
3905
    HConstant* c_right = HConstant::cast(right);
3906
    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3907
      if (c_right->DoubleValue() != 0) {
3908
        double double_res = c_left->DoubleValue() / c_right->DoubleValue();
3909
        if (TypeInfo::IsInt32Double(double_res)) {
3910
          return H_CONSTANT_INT(double_res);
3911
        }
3912
        return H_CONSTANT_DOUBLE(double_res);
3913
      } else {
3914
        int sign = Double(c_left->DoubleValue()).Sign() *
3915
                   Double(c_right->DoubleValue()).Sign();  // Right could be -0.
3916
        return H_CONSTANT_DOUBLE(sign * V8_INFINITY);
3917
      }
3918
    }
3919
  }
3920
  return new(zone) HDiv(context, left, right);
3921
}
3922

    
3923

    
3924
HInstruction* HBitwise::New(
3925
    Zone* zone, HValue* context, Token::Value op, HValue* left, HValue* right) {
3926
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3927
    HConstant* c_left = HConstant::cast(left);
3928
    HConstant* c_right = HConstant::cast(right);
3929
    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3930
      int32_t result;
3931
      int32_t v_left = c_left->NumberValueAsInteger32();
3932
      int32_t v_right = c_right->NumberValueAsInteger32();
3933
      switch (op) {
3934
        case Token::BIT_XOR:
3935
          result = v_left ^ v_right;
3936
          break;
3937
        case Token::BIT_AND:
3938
          result = v_left & v_right;
3939
          break;
3940
        case Token::BIT_OR:
3941
          result = v_left | v_right;
3942
          break;
3943
        default:
3944
          result = 0;  // Please the compiler.
3945
          UNREACHABLE();
3946
      }
3947
      return H_CONSTANT_INT(result);
3948
    }
3949
  }
3950
  return new(zone) HBitwise(context, op, left, right);
3951
}
3952

    
3953

    
3954
#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result)                             \
3955
HInstruction* HInstr::New(                                                     \
3956
    Zone* zone, HValue* context, HValue* left, HValue* right) {                \
3957
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {      \
3958
    HConstant* c_left = HConstant::cast(left);                                 \
3959
    HConstant* c_right = HConstant::cast(right);                               \
3960
    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
3961
      return H_CONSTANT_INT(result);                                           \
3962
    }                                                                          \
3963
  }                                                                            \
3964
  return new(zone) HInstr(context, left, right);                               \
3965
}
3966

    
3967

    
3968
DEFINE_NEW_H_BITWISE_INSTR(HSar,
3969
c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
3970
DEFINE_NEW_H_BITWISE_INSTR(HShl,
3971
c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
3972

    
3973
#undef DEFINE_NEW_H_BITWISE_INSTR
3974

    
3975

    
3976
HInstruction* HShr::New(
3977
    Zone* zone, HValue* context, HValue* left, HValue* right) {
3978
  if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
3979
    HConstant* c_left = HConstant::cast(left);
3980
    HConstant* c_right = HConstant::cast(right);
3981
    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
3982
      int32_t left_val = c_left->NumberValueAsInteger32();
3983
      int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
3984
      if ((right_val == 0) && (left_val < 0)) {
3985
        return H_CONSTANT_DOUBLE(static_cast<uint32_t>(left_val));
3986
      }
3987
      return H_CONSTANT_INT(static_cast<uint32_t>(left_val) >> right_val);
3988
    }
3989
  }
3990
  return new(zone) HShr(context, left, right);
3991
}
3992

    
3993

    
3994
#undef H_CONSTANT_INT
3995
#undef H_CONSTANT_DOUBLE
3996

    
3997

    
3998
void HBitwise::PrintDataTo(StringStream* stream) {
3999
  stream->Add(Token::Name(op_));
4000
  stream->Add(" ");
4001
  HBitwiseBinaryOperation::PrintDataTo(stream);
4002
}
4003

    
4004

    
4005
void HPhi::SimplifyConstantInputs() {
4006
  // Convert constant inputs to integers when all uses are truncating.
4007
  // This must happen before representation inference takes place.
4008
  if (!CheckUsesForFlag(kTruncatingToInt32)) return;
4009
  for (int i = 0; i < OperandCount(); ++i) {
4010
    if (!OperandAt(i)->IsConstant()) return;
4011
  }
4012
  HGraph* graph = block()->graph();
4013
  for (int i = 0; i < OperandCount(); ++i) {
4014
    HConstant* operand = HConstant::cast(OperandAt(i));
4015
    if (operand->HasInteger32Value()) {
4016
      continue;
4017
    } else if (operand->HasDoubleValue()) {
4018
      HConstant* integer_input =
4019
          HConstant::New(graph->zone(), graph->GetInvalidContext(),
4020
                         DoubleToInt32(operand->DoubleValue()));
4021
      integer_input->InsertAfter(operand);
4022
      SetOperandAt(i, integer_input);
4023
    } else if (operand->HasBooleanValue()) {
4024
      SetOperandAt(i, operand->BooleanValue() ? graph->GetConstant1()
4025
                                              : graph->GetConstant0());
4026
    } else if (operand->ImmortalImmovable()) {
4027
      SetOperandAt(i, graph->GetConstant0());
4028
    }
4029
  }
4030
  // Overwrite observed input representations because they are likely Tagged.
4031
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
4032
    HValue* use = it.value();
4033
    if (use->IsBinaryOperation()) {
4034
      HBinaryOperation::cast(use)->set_observed_input_representation(
4035
          it.index(), Representation::Smi());
4036
    }
4037
  }
4038
}
4039

    
4040

    
4041
void HPhi::InferRepresentation(HInferRepresentationPhase* h_infer) {
4042
  ASSERT(CheckFlag(kFlexibleRepresentation));
4043
  Representation new_rep = RepresentationFromInputs();
4044
  UpdateRepresentation(new_rep, h_infer, "inputs");
4045
  new_rep = RepresentationFromUses();
4046
  UpdateRepresentation(new_rep, h_infer, "uses");
4047
  new_rep = RepresentationFromUseRequirements();
4048
  UpdateRepresentation(new_rep, h_infer, "use requirements");
4049
}
4050

    
4051

    
4052
Representation HPhi::RepresentationFromInputs() {
4053
  Representation r = Representation::None();
4054
  for (int i = 0; i < OperandCount(); ++i) {
4055
    r = r.generalize(OperandAt(i)->KnownOptimalRepresentation());
4056
  }
4057
  return r;
4058
}
4059

    
4060

    
4061
// Returns a representation if all uses agree on the same representation.
4062
// Integer32 is also returned when some uses are Smi but others are Integer32.
4063
Representation HValue::RepresentationFromUseRequirements() {
4064
  Representation rep = Representation::None();
4065
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
4066
    // Ignore the use requirement from never run code
4067
    if (it.value()->block()->IsUnreachable()) continue;
4068

    
4069
    // We check for observed_input_representation elsewhere.
4070
    Representation use_rep =
4071
        it.value()->RequiredInputRepresentation(it.index());
4072
    if (rep.IsNone()) {
4073
      rep = use_rep;
4074
      continue;
4075
    }
4076
    if (use_rep.IsNone() || rep.Equals(use_rep)) continue;
4077
    if (rep.generalize(use_rep).IsInteger32()) {
4078
      rep = Representation::Integer32();
4079
      continue;
4080
    }
4081
    return Representation::None();
4082
  }
4083
  return rep;
4084
}
4085

    
4086

    
4087
bool HValue::HasNonSmiUse() {
4088
  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
4089
    // We check for observed_input_representation elsewhere.
4090
    Representation use_rep =
4091
        it.value()->RequiredInputRepresentation(it.index());
4092
    if (!use_rep.IsNone() &&
4093
        !use_rep.IsSmi() &&
4094
        !use_rep.IsTagged()) {
4095
      return true;
4096
    }
4097
  }
4098
  return false;
4099
}
4100

    
4101

    
4102
// Node-specific verification code is only included in debug mode.
4103
#ifdef DEBUG
4104

    
4105
void HPhi::Verify() {
4106
  ASSERT(OperandCount() == block()->predecessors()->length());
4107
  for (int i = 0; i < OperandCount(); ++i) {
4108
    HValue* value = OperandAt(i);
4109
    HBasicBlock* defining_block = value->block();
4110
    HBasicBlock* predecessor_block = block()->predecessors()->at(i);
4111
    ASSERT(defining_block == predecessor_block ||
4112
           defining_block->Dominates(predecessor_block));
4113
  }
4114
}
4115

    
4116

    
4117
void HSimulate::Verify() {
4118
  HInstruction::Verify();
4119
  ASSERT(HasAstId());
4120
}
4121

    
4122

    
4123
void HCheckHeapObject::Verify() {
4124
  HInstruction::Verify();
4125
  ASSERT(HasNoUses());
4126
}
4127

    
4128

    
4129
void HCheckValue::Verify() {
4130
  HInstruction::Verify();
4131
  ASSERT(HasNoUses());
4132
}
4133

    
4134
#endif
4135

    
4136

    
4137
HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) {
4138
  ASSERT(offset >= 0);
4139
  ASSERT(offset < FixedArray::kHeaderSize);
4140
  if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength();
4141
  return HObjectAccess(kInobject, offset);
4142
}
4143

    
4144

    
4145
HObjectAccess HObjectAccess::ForJSObjectOffset(int offset,
4146
    Representation representation) {
4147
  ASSERT(offset >= 0);
4148
  Portion portion = kInobject;
4149

    
4150
  if (offset == JSObject::kElementsOffset) {
4151
    portion = kElementsPointer;
4152
  } else if (offset == JSObject::kMapOffset) {
4153
    portion = kMaps;
4154
  }
4155
  return HObjectAccess(portion, offset, representation);
4156
}
4157

    
4158

    
4159
HObjectAccess HObjectAccess::ForContextSlot(int index) {
4160
  ASSERT(index >= 0);
4161
  Portion portion = kInobject;
4162
  int offset = Context::kHeaderSize + index * kPointerSize;
4163
  ASSERT_EQ(offset, Context::SlotOffset(index) + kHeapObjectTag);
4164
  return HObjectAccess(portion, offset, Representation::Tagged());
4165
}
4166

    
4167

    
4168
HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
4169
  ASSERT(offset >= 0);
4170
  Portion portion = kInobject;
4171

    
4172
  if (offset == JSObject::kElementsOffset) {
4173
    portion = kElementsPointer;
4174
  } else if (offset == JSArray::kLengthOffset) {
4175
    portion = kArrayLengths;
4176
  } else if (offset == JSObject::kMapOffset) {
4177
    portion = kMaps;
4178
  }
4179
  return HObjectAccess(portion, offset);
4180
}
4181

    
4182

    
4183
HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset,
4184
    Representation representation) {
4185
  ASSERT(offset >= 0);
4186
  return HObjectAccess(kBackingStore, offset, representation);
4187
}
4188

    
4189

    
4190
HObjectAccess HObjectAccess::ForField(Handle<Map> map,
4191
    LookupResult *lookup, Handle<String> name) {
4192
  ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map));
4193
  int index;
4194
  Representation representation;
4195
  if (lookup->IsField()) {
4196
    index = lookup->GetLocalFieldIndexFromMap(*map);
4197
    representation = lookup->representation();
4198
  } else {
4199
    Map* transition = lookup->GetTransitionMapFromMap(*map);
4200
    int descriptor = transition->LastAdded();
4201
    index = transition->instance_descriptors()->GetFieldIndex(descriptor) -
4202
        map->inobject_properties();
4203
    PropertyDetails details =
4204
        transition->instance_descriptors()->GetDetails(descriptor);
4205
    representation = details.representation();
4206
  }
4207
  if (index < 0) {
4208
    // Negative property indices are in-object properties, indexed
4209
    // from the end of the fixed part of the object.
4210
    int offset = (index * kPointerSize) + map->instance_size();
4211
    return HObjectAccess(kInobject, offset, representation);
4212
  } else {
4213
    // Non-negative property indices are in the properties array.
4214
    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
4215
    return HObjectAccess(kBackingStore, offset, representation, name);
4216
  }
4217
}
4218

    
4219

    
4220
HObjectAccess HObjectAccess::ForCellPayload(Isolate* isolate) {
4221
  return HObjectAccess(
4222
      kInobject, Cell::kValueOffset, Representation::Tagged(),
4223
      Handle<String>(isolate->heap()->cell_value_string()));
4224
}
4225

    
4226

    
4227
void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
4228
  // set the appropriate GVN flags for a given load or store instruction
4229
  if (is_store) {
4230
    // track dominating allocations in order to eliminate write barriers
4231
    instr->SetGVNFlag(kDependsOnNewSpacePromotion);
4232
    instr->SetFlag(HValue::kTrackSideEffectDominators);
4233
  } else {
4234
    // try to GVN loads, but don't hoist above map changes
4235
    instr->SetFlag(HValue::kUseGVN);
4236
    instr->SetGVNFlag(kDependsOnMaps);
4237
  }
4238

    
4239
  switch (portion()) {
4240
    case kArrayLengths:
4241
      instr->SetGVNFlag(is_store
4242
          ? kChangesArrayLengths : kDependsOnArrayLengths);
4243
      break;
4244
    case kStringLengths:
4245
      instr->SetGVNFlag(is_store
4246
          ? kChangesStringLengths : kDependsOnStringLengths);
4247
      break;
4248
    case kInobject:
4249
      instr->SetGVNFlag(is_store
4250
          ? kChangesInobjectFields : kDependsOnInobjectFields);
4251
      break;
4252
    case kDouble:
4253
      instr->SetGVNFlag(is_store
4254
          ? kChangesDoubleFields : kDependsOnDoubleFields);
4255
      break;
4256
    case kBackingStore:
4257
      instr->SetGVNFlag(is_store
4258
          ? kChangesBackingStoreFields : kDependsOnBackingStoreFields);
4259
      break;
4260
    case kElementsPointer:
4261
      instr->SetGVNFlag(is_store
4262
          ? kChangesElementsPointer : kDependsOnElementsPointer);
4263
      break;
4264
    case kMaps:
4265
      instr->SetGVNFlag(is_store
4266
          ? kChangesMaps : kDependsOnMaps);
4267
      break;
4268
    case kExternalMemory:
4269
      instr->SetGVNFlag(is_store
4270
          ? kChangesExternalMemory : kDependsOnExternalMemory);
4271
      break;
4272
  }
4273
}
4274

    
4275

    
4276
void HObjectAccess::PrintTo(StringStream* stream) {
4277
  stream->Add(".");
4278

    
4279
  switch (portion()) {
4280
    case kArrayLengths:
4281
    case kStringLengths:
4282
      stream->Add("%length");
4283
      break;
4284
    case kElementsPointer:
4285
      stream->Add("%elements");
4286
      break;
4287
    case kMaps:
4288
      stream->Add("%map");
4289
      break;
4290
    case kDouble:  // fall through
4291
    case kInobject:
4292
      if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
4293
      stream->Add("[in-object]");
4294
      break;
4295
    case kBackingStore:
4296
      if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
4297
      stream->Add("[backing-store]");
4298
      break;
4299
    case kExternalMemory:
4300
      stream->Add("[external-memory]");
4301
      break;
4302
  }
4303

    
4304
  stream->Add("@%d", offset());
4305
}
4306

    
4307
} }  // namespace v8::internal