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 "factory.h"
31#include "hydrogen.h"
32
33#if V8_TARGET_ARCH_IA32
34#include "ia32/lithium-ia32.h"
35#elif V8_TARGET_ARCH_X64
36#include "x64/lithium-x64.h"
37#elif V8_TARGET_ARCH_ARM
38#include "arm/lithium-arm.h"
39#elif V8_TARGET_ARCH_MIPS
40#include "mips/lithium-mips.h"
41#else
42#error Unsupported target architecture.
43#endif
44
45namespace v8 {
46namespace internal {
47
48#define DEFINE_COMPILE(type)                                         \
49  LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) {  \
50    return builder->Do##type(this);                                  \
51  }
52HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
53#undef DEFINE_COMPILE
54
55
56const char* Representation::Mnemonic() const {
57  switch (kind_) {
58    case kNone: return "v";
59    case kTagged: return "t";
60    case kDouble: return "d";
61    case kInteger32: return "i";
62    case kExternal: return "x";
63    default:
64      UNREACHABLE();
65      return NULL;
66  }
67}
68
69
70int HValue::LoopWeight() const {
71  const int w = FLAG_loop_weight;
72  static const int weights[] = { 1, w, w*w, w*w*w, w*w*w*w };
73  return weights[Min(block()->LoopNestingDepth(),
74                     static_cast<int>(ARRAY_SIZE(weights)-1))];
75}
76
77
78void HValue::AssumeRepresentation(Representation r) {
79  if (CheckFlag(kFlexibleRepresentation)) {
80    ChangeRepresentation(r);
81    // The representation of the value is dictated by type feedback and
82    // will not be changed later.
83    ClearFlag(kFlexibleRepresentation);
84  }
85}
86
87
88static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
89  if (result > kMaxInt) {
90    *overflow = true;
91    return kMaxInt;
92  }
93  if (result < kMinInt) {
94    *overflow = true;
95    return kMinInt;
96  }
97  return static_cast<int32_t>(result);
98}
99
100
101static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
102  int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
103  return ConvertAndSetOverflow(result, overflow);
104}
105
106
107static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
108  int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
109  return ConvertAndSetOverflow(result, overflow);
110}
111
112
113static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
114  int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
115  return ConvertAndSetOverflow(result, overflow);
116}
117
118
119int32_t Range::Mask() const {
120  if (lower_ == upper_) return lower_;
121  if (lower_ >= 0) {
122    int32_t res = 1;
123    while (res < upper_) {
124      res = (res << 1) | 1;
125    }
126    return res;
127  }
128  return 0xffffffff;
129}
130
131
132void Range::AddConstant(int32_t value) {
133  if (value == 0) return;
134  bool may_overflow = false;  // Overflow is ignored here.
135  lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
136  upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
137#ifdef DEBUG
138  Verify();
139#endif
140}
141
142
143void Range::Intersect(Range* other) {
144  upper_ = Min(upper_, other->upper_);
145  lower_ = Max(lower_, other->lower_);
146  bool b = CanBeMinusZero() && other->CanBeMinusZero();
147  set_can_be_minus_zero(b);
148}
149
150
151void Range::Union(Range* other) {
152  upper_ = Max(upper_, other->upper_);
153  lower_ = Min(lower_, other->lower_);
154  bool b = CanBeMinusZero() || other->CanBeMinusZero();
155  set_can_be_minus_zero(b);
156}
157
158
159void Range::Sar(int32_t value) {
160  int32_t bits = value & 0x1F;
161  lower_ = lower_ >> bits;
162  upper_ = upper_ >> bits;
163  set_can_be_minus_zero(false);
164}
165
166
167void Range::Shl(int32_t value) {
168  int32_t bits = value & 0x1F;
169  int old_lower = lower_;
170  int old_upper = upper_;
171  lower_ = lower_ << bits;
172  upper_ = upper_ << bits;
173  if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
174    upper_ = kMaxInt;
175    lower_ = kMinInt;
176  }
177  set_can_be_minus_zero(false);
178}
179
180
181bool Range::AddAndCheckOverflow(Range* other) {
182  bool may_overflow = false;
183  lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
184  upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
185  KeepOrder();
186#ifdef DEBUG
187  Verify();
188#endif
189  return may_overflow;
190}
191
192
193bool Range::SubAndCheckOverflow(Range* other) {
194  bool may_overflow = false;
195  lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
196  upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
197  KeepOrder();
198#ifdef DEBUG
199  Verify();
200#endif
201  return may_overflow;
202}
203
204
205void Range::KeepOrder() {
206  if (lower_ > upper_) {
207    int32_t tmp = lower_;
208    lower_ = upper_;
209    upper_ = tmp;
210  }
211}
212
213
214#ifdef DEBUG
215void Range::Verify() const {
216  ASSERT(lower_ <= upper_);
217}
218#endif
219
220
221bool Range::MulAndCheckOverflow(Range* other) {
222  bool may_overflow = false;
223  int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
224  int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
225  int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
226  int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
227  lower_ = Min(Min(v1, v2), Min(v3, v4));
228  upper_ = Max(Max(v1, v2), Max(v3, v4));
229#ifdef DEBUG
230  Verify();
231#endif
232  return may_overflow;
233}
234
235
236const char* HType::ToString() {
237  switch (type_) {
238    case kTagged: return "tagged";
239    case kTaggedPrimitive: return "primitive";
240    case kTaggedNumber: return "number";
241    case kSmi: return "smi";
242    case kHeapNumber: return "heap-number";
243    case kString: return "string";
244    case kBoolean: return "boolean";
245    case kNonPrimitive: return "non-primitive";
246    case kJSArray: return "array";
247    case kJSObject: return "object";
248    case kUninitialized: return "uninitialized";
249  }
250  UNREACHABLE();
251  return "Unreachable code";
252}
253
254
255HType HType::TypeFromValue(Handle<Object> value) {
256  HType result = HType::Tagged();
257  if (value->IsSmi()) {
258    result = HType::Smi();
259  } else if (value->IsHeapNumber()) {
260    result = HType::HeapNumber();
261  } else if (value->IsString()) {
262    result = HType::String();
263  } else if (value->IsBoolean()) {
264    result = HType::Boolean();
265  } else if (value->IsJSObject()) {
266    result = HType::JSObject();
267  } else if (value->IsJSArray()) {
268    result = HType::JSArray();
269  }
270  return result;
271}
272
273
274bool HValue::IsDefinedAfter(HBasicBlock* other) const {
275  return block()->block_id() > other->block_id();
276}
277
278
279HUseListNode* HUseListNode::tail() {
280  // Skip and remove dead items in the use list.
281  while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) {
282    tail_ = tail_->tail_;
283  }
284  return tail_;
285}
286
287
288bool HValue::CheckUsesForFlag(Flag f) {
289  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
290    if (!it.value()->CheckFlag(f)) return false;
291  }
292  return true;
293}
294
295
296HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
297  Advance();
298}
299
300
301void HUseIterator::Advance() {
302  current_ = next_;
303  if (current_ != NULL) {
304    next_ = current_->tail();
305    value_ = current_->value();
306    index_ = current_->index();
307  }
308}
309
310
311int HValue::UseCount() const {
312  int count = 0;
313  for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
314  return count;
315}
316
317
318HUseListNode* HValue::RemoveUse(HValue* value, int index) {
319  HUseListNode* previous = NULL;
320  HUseListNode* current = use_list_;
321  while (current != NULL) {
322    if (current->value() == value && current->index() == index) {
323      if (previous == NULL) {
324        use_list_ = current->tail();
325      } else {
326        previous->set_tail(current->tail());
327      }
328      break;
329    }
330
331    previous = current;
332    current = current->tail();
333  }
334
335#ifdef DEBUG
336  // Do not reuse use list nodes in debug mode, zap them.
337  if (current != NULL) {
338    HUseListNode* temp =
339        new HUseListNode(current->value(), current->index(), NULL);
340    current->Zap();
341    current = temp;
342  }
343#endif
344  return current;
345}
346
347
348bool HValue::Equals(HValue* other) {
349  if (other->opcode() != opcode()) return false;
350  if (!other->representation().Equals(representation())) return false;
351  if (!other->type_.Equals(type_)) return false;
352  if (other->flags() != flags()) return false;
353  if (OperandCount() != other->OperandCount()) return false;
354  for (int i = 0; i < OperandCount(); ++i) {
355    if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
356  }
357  bool result = DataEquals(other);
358  ASSERT(!result || Hashcode() == other->Hashcode());
359  return result;
360}
361
362
363intptr_t HValue::Hashcode() {
364  intptr_t result = opcode();
365  int count = OperandCount();
366  for (int i = 0; i < count; ++i) {
367    result = result * 19 + OperandAt(i)->id() + (result >> 7);
368  }
369  return result;
370}
371
372
373const char* HValue::Mnemonic() const {
374  switch (opcode()) {
375#define MAKE_CASE(type) case k##type: return #type;
376    HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
377#undef MAKE_CASE
378    case kPhi: return "Phi";
379    default: return "";
380  }
381}
382
383
384void HValue::SetOperandAt(int index, HValue* value) {
385  RegisterUse(index, value);
386  InternalSetOperandAt(index, value);
387}
388
389
390void HValue::DeleteAndReplaceWith(HValue* other) {
391  // We replace all uses first, so Delete can assert that there are none.
392  if (other != NULL) ReplaceAllUsesWith(other);
393  ASSERT(HasNoUses());
394  Kill();
395  DeleteFromGraph();
396}
397
398
399void HValue::ReplaceAllUsesWith(HValue* other) {
400  while (use_list_ != NULL) {
401    HUseListNode* list_node = use_list_;
402    HValue* value = list_node->value();
403    ASSERT(!value->block()->IsStartBlock());
404    value->InternalSetOperandAt(list_node->index(), other);
405    use_list_ = list_node->tail();
406    list_node->set_tail(other->use_list_);
407    other->use_list_ = list_node;
408  }
409}
410
411
412void HValue::Kill() {
413  // Instead of going through the entire use list of each operand, we only
414  // check the first item in each use list and rely on the tail() method to
415  // skip dead items, removing them lazily next time we traverse the list.
416  SetFlag(kIsDead);
417  for (int i = 0; i < OperandCount(); ++i) {
418    HValue* operand = OperandAt(i);
419    HUseListNode* first = operand->use_list_;
420    if (first != NULL && first->value() == this && first->index() == i) {
421      operand->use_list_ = first->tail();
422    }
423  }
424}
425
426
427void HValue::SetBlock(HBasicBlock* block) {
428  ASSERT(block_ == NULL || block == NULL);
429  block_ = block;
430  if (id_ == kNoNumber && block != NULL) {
431    id_ = block->graph()->GetNextValueID(this);
432  }
433}
434
435
436void HValue::PrintTypeTo(StringStream* stream) {
437  if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
438  stream->Add(" type[%s]", type().ToString());
439}
440
441
442void HValue::PrintRangeTo(StringStream* stream) {
443  if (range() == NULL || range()->IsMostGeneric()) return;
444  stream->Add(" range[%d,%d,m0=%d]",
445              range()->lower(),
446              range()->upper(),
447              static_cast<int>(range()->CanBeMinusZero()));
448}
449
450
451void HValue::PrintChangesTo(StringStream* stream) {
452  GVNFlagSet changes_flags = ChangesFlags();
453  if (changes_flags.IsEmpty()) return;
454  stream->Add(" changes[");
455  if (changes_flags == AllSideEffectsFlagSet()) {
456    stream->Add("*");
457  } else {
458    bool add_comma = false;
459#define PRINT_DO(type)                            \
460    if (changes_flags.Contains(kChanges##type)) { \
461      if (add_comma) stream->Add(",");            \
462      add_comma = true;                           \
463      stream->Add(#type);                         \
464    }
465    GVN_FLAG_LIST(PRINT_DO);
466#undef PRINT_DO
467  }
468  stream->Add("]");
469}
470
471
472void HValue::PrintNameTo(StringStream* stream) {
473  stream->Add("%s%d", representation_.Mnemonic(), id());
474}
475
476
477bool HValue::UpdateInferredType() {
478  HType type = CalculateInferredType();
479  bool result = (!type.Equals(type_));
480  type_ = type;
481  return result;
482}
483
484
485void HValue::RegisterUse(int index, HValue* new_value) {
486  HValue* old_value = OperandAt(index);
487  if (old_value == new_value) return;
488
489  HUseListNode* removed = NULL;
490  if (old_value != NULL) {
491    removed = old_value->RemoveUse(this, index);
492  }
493
494  if (new_value != NULL) {
495    if (removed == NULL) {
496      new_value->use_list_ =
497          new HUseListNode(this, index, new_value->use_list_);
498    } else {
499      removed->set_tail(new_value->use_list_);
500      new_value->use_list_ = removed;
501    }
502  }
503}
504
505
506void HValue::AddNewRange(Range* r, Zone* zone) {
507  if (!HasRange()) ComputeInitialRange(zone);
508  if (!HasRange()) range_ = new(zone) Range();
509  ASSERT(HasRange());
510  r->StackUpon(range_);
511  range_ = r;
512}
513
514
515void HValue::RemoveLastAddedRange() {
516  ASSERT(HasRange());
517  ASSERT(range_->next() != NULL);
518  range_ = range_->next();
519}
520
521
522void HValue::ComputeInitialRange(Zone* zone) {
523  ASSERT(!HasRange());
524  range_ = InferRange(zone);
525  ASSERT(HasRange());
526}
527
528
529void HInstruction::PrintTo(StringStream* stream) {
530  PrintMnemonicTo(stream);
531  PrintDataTo(stream);
532  PrintRangeTo(stream);
533  PrintChangesTo(stream);
534  PrintTypeTo(stream);
535}
536
537
538void HInstruction::PrintMnemonicTo(StringStream* stream) {
539  stream->Add("%s ", Mnemonic());
540}
541
542
543void HInstruction::Unlink() {
544  ASSERT(IsLinked());
545  ASSERT(!IsControlInstruction());  // Must never move control instructions.
546  ASSERT(!IsBlockEntry());  // Doesn't make sense to delete these.
547  ASSERT(previous_ != NULL);
548  previous_->next_ = next_;
549  if (next_ == NULL) {
550    ASSERT(block()->last() == this);
551    block()->set_last(previous_);
552  } else {
553    next_->previous_ = previous_;
554  }
555  clear_block();
556}
557
558
559void HInstruction::InsertBefore(HInstruction* next) {
560  ASSERT(!IsLinked());
561  ASSERT(!next->IsBlockEntry());
562  ASSERT(!IsControlInstruction());
563  ASSERT(!next->block()->IsStartBlock());
564  ASSERT(next->previous_ != NULL);
565  HInstruction* prev = next->previous();
566  prev->next_ = this;
567  next->previous_ = this;
568  next_ = next;
569  previous_ = prev;
570  SetBlock(next->block());
571}
572
573
574void HInstruction::InsertAfter(HInstruction* previous) {
575  ASSERT(!IsLinked());
576  ASSERT(!previous->IsControlInstruction());
577  ASSERT(!IsControlInstruction() || previous->next_ == NULL);
578  HBasicBlock* block = previous->block();
579  // Never insert anything except constants into the start block after finishing
580  // it.
581  if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
582    ASSERT(block->end()->SecondSuccessor() == NULL);
583    InsertAfter(block->end()->FirstSuccessor()->first());
584    return;
585  }
586
587  // If we're inserting after an instruction with side-effects that is
588  // followed by a simulate instruction, we need to insert after the
589  // simulate instruction instead.
590  HInstruction* next = previous->next_;
591  if (previous->HasObservableSideEffects() && next != NULL) {
592    ASSERT(next->IsSimulate());
593    previous = next;
594    next = previous->next_;
595  }
596
597  previous_ = previous;
598  next_ = next;
599  SetBlock(block);
600  previous->next_ = this;
601  if (next != NULL) next->previous_ = this;
602}
603
604
605#ifdef DEBUG
606void HInstruction::Verify() {
607  // Verify that input operands are defined before use.
608  HBasicBlock* cur_block = block();
609  for (int i = 0; i < OperandCount(); ++i) {
610    HValue* other_operand = OperandAt(i);
611    HBasicBlock* other_block = other_operand->block();
612    if (cur_block == other_block) {
613      if (!other_operand->IsPhi()) {
614        HInstruction* cur = this->previous();
615        while (cur != NULL) {
616          if (cur == other_operand) break;
617          cur = cur->previous();
618        }
619        // Must reach other operand in the same block!
620        ASSERT(cur == other_operand);
621      }
622    } else {
623      // If the following assert fires, you may have forgotten an
624      // AddInstruction.
625      ASSERT(other_block->Dominates(cur_block));
626    }
627  }
628
629  // Verify that instructions that may have side-effects are followed
630  // by a simulate instruction.
631  if (HasObservableSideEffects() && !IsOsrEntry()) {
632    ASSERT(next()->IsSimulate());
633  }
634
635  // Verify that instructions that can be eliminated by GVN have overridden
636  // HValue::DataEquals.  The default implementation is UNREACHABLE.  We
637  // don't actually care whether DataEquals returns true or false here.
638  if (CheckFlag(kUseGVN)) DataEquals(this);
639}
640#endif
641
642
643void HUnaryCall::PrintDataTo(StringStream* stream) {
644  value()->PrintNameTo(stream);
645  stream->Add(" ");
646  stream->Add("#%d", argument_count());
647}
648
649
650void HBinaryCall::PrintDataTo(StringStream* stream) {
651  first()->PrintNameTo(stream);
652  stream->Add(" ");
653  second()->PrintNameTo(stream);
654  stream->Add(" ");
655  stream->Add("#%d", argument_count());
656}
657
658
659void HBoundsCheck::PrintDataTo(StringStream* stream) {
660  index()->PrintNameTo(stream);
661  stream->Add(" ");
662  length()->PrintNameTo(stream);
663}
664
665
666void HCallConstantFunction::PrintDataTo(StringStream* stream) {
667  if (IsApplyFunction()) {
668    stream->Add("optimized apply ");
669  } else {
670    stream->Add("%o ", function()->shared()->DebugName());
671  }
672  stream->Add("#%d", argument_count());
673}
674
675
676void HCallNamed::PrintDataTo(StringStream* stream) {
677  stream->Add("%o ", *name());
678  HUnaryCall::PrintDataTo(stream);
679}
680
681
682void HCallGlobal::PrintDataTo(StringStream* stream) {
683  stream->Add("%o ", *name());
684  HUnaryCall::PrintDataTo(stream);
685}
686
687
688void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
689  stream->Add("o ", target()->shared()->DebugName());
690  stream->Add("#%d", argument_count());
691}
692
693
694void HCallRuntime::PrintDataTo(StringStream* stream) {
695  stream->Add("%o ", *name());
696  stream->Add("#%d", argument_count());
697}
698
699
700void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
701  stream->Add("class_of_test(");
702  value()->PrintNameTo(stream);
703  stream->Add(", \"%o\")", *class_name());
704}
705
706
707void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
708  arguments()->PrintNameTo(stream);
709  stream->Add("[");
710  index()->PrintNameTo(stream);
711  stream->Add("], length ");
712  length()->PrintNameTo(stream);
713}
714
715
716void HControlInstruction::PrintDataTo(StringStream* stream) {
717  stream->Add(" goto (");
718  bool first_block = true;
719  for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
720    stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
721    first_block = false;
722  }
723  stream->Add(")");
724}
725
726
727void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
728  value()->PrintNameTo(stream);
729  HControlInstruction::PrintDataTo(stream);
730}
731
732
733void HIsNilAndBranch::PrintDataTo(StringStream* stream) {
734  value()->PrintNameTo(stream);
735  stream->Add(kind() == kStrictEquality ? " === " : " == ");
736  stream->Add(nil() == kNullValue ? "null" : "undefined");
737  HControlInstruction::PrintDataTo(stream);
738}
739
740
741void HReturn::PrintDataTo(StringStream* stream) {
742  value()->PrintNameTo(stream);
743}
744
745
746void HCompareMap::PrintDataTo(StringStream* stream) {
747  value()->PrintNameTo(stream);
748  stream->Add(" (%p)", *map());
749  HControlInstruction::PrintDataTo(stream);
750}
751
752
753const char* HUnaryMathOperation::OpName() const {
754  switch (op()) {
755    case kMathFloor: return "floor";
756    case kMathRound: return "round";
757    case kMathCeil: return "ceil";
758    case kMathAbs: return "abs";
759    case kMathLog: return "log";
760    case kMathSin: return "sin";
761    case kMathCos: return "cos";
762    case kMathTan: return "tan";
763    case kMathASin: return "asin";
764    case kMathACos: return "acos";
765    case kMathATan: return "atan";
766    case kMathExp: return "exp";
767    case kMathSqrt: return "sqrt";
768    default: break;
769  }
770  return "(unknown operation)";
771}
772
773
774void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
775  const char* name = OpName();
776  stream->Add("%s ", name);
777  value()->PrintNameTo(stream);
778}
779
780
781void HUnaryOperation::PrintDataTo(StringStream* stream) {
782  value()->PrintNameTo(stream);
783}
784
785
786void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
787  value()->PrintNameTo(stream);
788  switch (from_) {
789    case FIRST_JS_RECEIVER_TYPE:
790      if (to_ == LAST_TYPE) stream->Add(" spec_object");
791      break;
792    case JS_REGEXP_TYPE:
793      if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
794      break;
795    case JS_ARRAY_TYPE:
796      if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
797      break;
798    case JS_FUNCTION_TYPE:
799      if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
800      break;
801    default:
802      break;
803  }
804}
805
806
807void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
808  value()->PrintNameTo(stream);
809  stream->Add(" == %o", *type_literal_);
810  HControlInstruction::PrintDataTo(stream);
811}
812
813
814void HCheckMapValue::PrintDataTo(StringStream* stream) {
815  value()->PrintNameTo(stream);
816  stream->Add(" ");
817  map()->PrintNameTo(stream);
818}
819
820
821void HForInPrepareMap::PrintDataTo(StringStream* stream) {
822  enumerable()->PrintNameTo(stream);
823}
824
825
826void HForInCacheArray::PrintDataTo(StringStream* stream) {
827  enumerable()->PrintNameTo(stream);
828  stream->Add(" ");
829  map()->PrintNameTo(stream);
830  stream->Add("[%d]", idx_);
831}
832
833
834void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
835  object()->PrintNameTo(stream);
836  stream->Add(" ");
837  index()->PrintNameTo(stream);
838}
839
840
841HValue* HConstant::Canonicalize() {
842  return HasNoUses() ? NULL : this;
843}
844
845
846HValue* HTypeof::Canonicalize() {
847  return HasNoUses() ? NULL : this;
848}
849
850
851HValue* HBitwise::Canonicalize() {
852  if (!representation().IsInteger32()) return this;
853  // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
854  int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
855  if (left()->IsConstant() &&
856      HConstant::cast(left())->HasInteger32Value() &&
857      HConstant::cast(left())->Integer32Value() == nop_constant) {
858    return right();
859  }
860  if (right()->IsConstant() &&
861      HConstant::cast(right())->HasInteger32Value() &&
862      HConstant::cast(right())->Integer32Value() == nop_constant) {
863    return left();
864  }
865  return this;
866}
867
868
869HValue* HAdd::Canonicalize() {
870  if (!representation().IsInteger32()) return this;
871  if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
872  return this;
873}
874
875
876HValue* HSub::Canonicalize() {
877  if (!representation().IsInteger32()) return this;
878  if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
879  return this;
880}
881
882
883HValue* HChange::Canonicalize() {
884  return (from().Equals(to())) ? value() : this;
885}
886
887
888HValue* HWrapReceiver::Canonicalize() {
889  if (HasNoUses()) return NULL;
890  if (receiver()->type().IsJSObject()) {
891    return receiver();
892  }
893  return this;
894}
895
896
897void HTypeof::PrintDataTo(StringStream* stream) {
898  value()->PrintNameTo(stream);
899}
900
901
902void HChange::PrintDataTo(StringStream* stream) {
903  HUnaryOperation::PrintDataTo(stream);
904  stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
905
906  if (CanTruncateToInt32()) stream->Add(" truncating-int32");
907  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
908  if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
909}
910
911
912void HJSArrayLength::PrintDataTo(StringStream* stream) {
913  value()->PrintNameTo(stream);
914  stream->Add(" ");
915  typecheck()->PrintNameTo(stream);
916}
917
918
919HValue* HCheckInstanceType::Canonicalize() {
920  if (check_ == IS_STRING &&
921      !value()->type().IsUninitialized() &&
922      value()->type().IsString()) {
923    return NULL;
924  }
925  if (check_ == IS_SYMBOL &&
926      value()->IsConstant() &&
927      HConstant::cast(value())->handle()->IsSymbol()) {
928    return NULL;
929  }
930  return this;
931}
932
933
934void HCheckInstanceType::GetCheckInterval(InstanceType* first,
935                                          InstanceType* last) {
936  ASSERT(is_interval_check());
937  switch (check_) {
938    case IS_SPEC_OBJECT:
939      *first = FIRST_SPEC_OBJECT_TYPE;
940      *last = LAST_SPEC_OBJECT_TYPE;
941      return;
942    case IS_JS_ARRAY:
943      *first = *last = JS_ARRAY_TYPE;
944      return;
945    default:
946      UNREACHABLE();
947  }
948}
949
950
951void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
952  ASSERT(!is_interval_check());
953  switch (check_) {
954    case IS_STRING:
955      *mask = kIsNotStringMask;
956      *tag = kStringTag;
957      return;
958    case IS_SYMBOL:
959      *mask = kIsSymbolMask;
960      *tag = kSymbolTag;
961      return;
962    default:
963      UNREACHABLE();
964  }
965}
966
967
968void HCheckMap::PrintDataTo(StringStream* stream) {
969  value()->PrintNameTo(stream);
970  stream->Add(" %p", *map());
971  if (mode() == REQUIRE_EXACT_MAP) {
972    stream->Add(" [EXACT]");
973  } else if (!has_element_transitions_) {
974    stream->Add(" [EXACT*]");
975  } else {
976    stream->Add(" [MATCH ELEMENTS]");
977  }
978}
979
980
981void HCheckFunction::PrintDataTo(StringStream* stream) {
982  value()->PrintNameTo(stream);
983  stream->Add(" %p", *target());
984}
985
986
987const char* HCheckInstanceType::GetCheckName() {
988  switch (check_) {
989    case IS_SPEC_OBJECT: return "object";
990    case IS_JS_ARRAY: return "array";
991    case IS_STRING: return "string";
992    case IS_SYMBOL: return "symbol";
993  }
994  UNREACHABLE();
995  return "";
996}
997
998void HCheckInstanceType::PrintDataTo(StringStream* stream) {
999  stream->Add("%s ", GetCheckName());
1000  HUnaryOperation::PrintDataTo(stream);
1001}
1002
1003
1004void HCallStub::PrintDataTo(StringStream* stream) {
1005  stream->Add("%s ",
1006              CodeStub::MajorName(major_key_, false));
1007  HUnaryCall::PrintDataTo(stream);
1008}
1009
1010
1011void HInstanceOf::PrintDataTo(StringStream* stream) {
1012  left()->PrintNameTo(stream);
1013  stream->Add(" ");
1014  right()->PrintNameTo(stream);
1015  stream->Add(" ");
1016  context()->PrintNameTo(stream);
1017}
1018
1019
1020Range* HValue::InferRange(Zone* zone) {
1021  // Untagged integer32 cannot be -0, all other representations can.
1022  Range* result = new(zone) Range();
1023  result->set_can_be_minus_zero(!representation().IsInteger32());
1024  return result;
1025}
1026
1027
1028Range* HChange::InferRange(Zone* zone) {
1029  Range* input_range = value()->range();
1030  if (from().IsInteger32() &&
1031      to().IsTagged() &&
1032      input_range != NULL && input_range->IsInSmiRange()) {
1033    set_type(HType::Smi());
1034  }
1035  Range* result = (input_range != NULL)
1036      ? input_range->Copy(zone)
1037      : HValue::InferRange(zone);
1038  if (to().IsInteger32()) result->set_can_be_minus_zero(false);
1039  return result;
1040}
1041
1042
1043Range* HConstant::InferRange(Zone* zone) {
1044  if (has_int32_value_) {
1045    Range* result = new(zone) Range(int32_value_, int32_value_);
1046    result->set_can_be_minus_zero(false);
1047    return result;
1048  }
1049  return HValue::InferRange(zone);
1050}
1051
1052
1053Range* HPhi::InferRange(Zone* zone) {
1054  if (representation().IsInteger32()) {
1055    if (block()->IsLoopHeader()) {
1056      Range* range = new(zone) Range(kMinInt, kMaxInt);
1057      return range;
1058    } else {
1059      Range* range = OperandAt(0)->range()->Copy(zone);
1060      for (int i = 1; i < OperandCount(); ++i) {
1061        range->Union(OperandAt(i)->range());
1062      }
1063      return range;
1064    }
1065  } else {
1066    return HValue::InferRange(zone);
1067  }
1068}
1069
1070
1071Range* HAdd::InferRange(Zone* zone) {
1072  if (representation().IsInteger32()) {
1073    Range* a = left()->range();
1074    Range* b = right()->range();
1075    Range* res = a->Copy(zone);
1076    if (!res->AddAndCheckOverflow(b)) {
1077      ClearFlag(kCanOverflow);
1078    }
1079    bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
1080    res->set_can_be_minus_zero(m0);
1081    return res;
1082  } else {
1083    return HValue::InferRange(zone);
1084  }
1085}
1086
1087
1088Range* HSub::InferRange(Zone* zone) {
1089  if (representation().IsInteger32()) {
1090    Range* a = left()->range();
1091    Range* b = right()->range();
1092    Range* res = a->Copy(zone);
1093    if (!res->SubAndCheckOverflow(b)) {
1094      ClearFlag(kCanOverflow);
1095    }
1096    res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
1097    return res;
1098  } else {
1099    return HValue::InferRange(zone);
1100  }
1101}
1102
1103
1104Range* HMul::InferRange(Zone* zone) {
1105  if (representation().IsInteger32()) {
1106    Range* a = left()->range();
1107    Range* b = right()->range();
1108    Range* res = a->Copy(zone);
1109    if (!res->MulAndCheckOverflow(b)) {
1110      ClearFlag(kCanOverflow);
1111    }
1112    bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
1113        (a->CanBeNegative() && b->CanBeZero());
1114    res->set_can_be_minus_zero(m0);
1115    return res;
1116  } else {
1117    return HValue::InferRange(zone);
1118  }
1119}
1120
1121
1122Range* HDiv::InferRange(Zone* zone) {
1123  if (representation().IsInteger32()) {
1124    Range* result = new(zone) Range();
1125    if (left()->range()->CanBeMinusZero()) {
1126      result->set_can_be_minus_zero(true);
1127    }
1128
1129    if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1130      result->set_can_be_minus_zero(true);
1131    }
1132
1133    if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1134      SetFlag(HValue::kCanOverflow);
1135    }
1136
1137    if (!right()->range()->CanBeZero()) {
1138      ClearFlag(HValue::kCanBeDivByZero);
1139    }
1140    return result;
1141  } else {
1142    return HValue::InferRange(zone);
1143  }
1144}
1145
1146
1147Range* HMod::InferRange(Zone* zone) {
1148  if (representation().IsInteger32()) {
1149    Range* a = left()->range();
1150    Range* result = new(zone) Range();
1151    if (a->CanBeMinusZero() || a->CanBeNegative()) {
1152      result->set_can_be_minus_zero(true);
1153    }
1154    if (!right()->range()->CanBeZero()) {
1155      ClearFlag(HValue::kCanBeDivByZero);
1156    }
1157    return result;
1158  } else {
1159    return HValue::InferRange(zone);
1160  }
1161}
1162
1163
1164void HPhi::PrintTo(StringStream* stream) {
1165  stream->Add("[");
1166  for (int i = 0; i < OperandCount(); ++i) {
1167    HValue* value = OperandAt(i);
1168    stream->Add(" ");
1169    value->PrintNameTo(stream);
1170    stream->Add(" ");
1171  }
1172  stream->Add(" uses%d_%di_%dd_%dt",
1173              UseCount(),
1174              int32_non_phi_uses() + int32_indirect_uses(),
1175              double_non_phi_uses() + double_indirect_uses(),
1176              tagged_non_phi_uses() + tagged_indirect_uses());
1177  stream->Add("%s%s]",
1178              is_live() ? "_live" : "",
1179              IsConvertibleToInteger() ? "" : "_ncti");
1180}
1181
1182
1183void HPhi::AddInput(HValue* value) {
1184  inputs_.Add(NULL);
1185  SetOperandAt(OperandCount() - 1, value);
1186  // Mark phis that may have 'arguments' directly or indirectly as an operand.
1187  if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1188    SetFlag(kIsArguments);
1189  }
1190}
1191
1192
1193bool HPhi::HasRealUses() {
1194  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1195    if (!it.value()->IsPhi()) return true;
1196  }
1197  return false;
1198}
1199
1200
1201HValue* HPhi::GetRedundantReplacement() {
1202  HValue* candidate = NULL;
1203  int count = OperandCount();
1204  int position = 0;
1205  while (position < count && candidate == NULL) {
1206    HValue* current = OperandAt(position++);
1207    if (current != this) candidate = current;
1208  }
1209  while (position < count) {
1210    HValue* current = OperandAt(position++);
1211    if (current != this && current != candidate) return NULL;
1212  }
1213  ASSERT(candidate != this);
1214  return candidate;
1215}
1216
1217
1218void HPhi::DeleteFromGraph() {
1219  ASSERT(block() != NULL);
1220  block()->RemovePhi(this);
1221  ASSERT(block() == NULL);
1222}
1223
1224
1225void HPhi::InitRealUses(int phi_id) {
1226  // Initialize real uses.
1227  phi_id_ = phi_id;
1228  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1229    HValue* value = it.value();
1230    if (!value->IsPhi()) {
1231      Representation rep = value->RequiredInputRepresentation(it.index());
1232      non_phi_uses_[rep.kind()] += value->LoopWeight();
1233    }
1234  }
1235}
1236
1237
1238void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1239  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1240    indirect_uses_[i] += other->non_phi_uses_[i];
1241  }
1242}
1243
1244
1245void HPhi::AddIndirectUsesTo(int* dest) {
1246  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1247    dest[i] += indirect_uses_[i];
1248  }
1249}
1250
1251
1252void HSimulate::PrintDataTo(StringStream* stream) {
1253  stream->Add("id=%d", ast_id());
1254  if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
1255  if (values_.length() > 0) {
1256    if (pop_count_ > 0) stream->Add(" /");
1257    for (int i = 0; i < values_.length(); ++i) {
1258      if (i > 0) stream->Add(",");
1259      if (HasAssignedIndexAt(i)) {
1260        stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1261      } else {
1262        stream->Add(" push ");
1263      }
1264      values_[i]->PrintNameTo(stream);
1265    }
1266  }
1267}
1268
1269
1270void HDeoptimize::PrintDataTo(StringStream* stream) {
1271  if (OperandCount() == 0) return;
1272  OperandAt(0)->PrintNameTo(stream);
1273  for (int i = 1; i < OperandCount(); ++i) {
1274    stream->Add(" ");
1275    OperandAt(i)->PrintNameTo(stream);
1276  }
1277}
1278
1279
1280void HEnterInlined::PrintDataTo(StringStream* stream) {
1281  SmartArrayPointer<char> name = function()->debug_name()->ToCString();
1282  stream->Add("%s, id=%d", *name, function()->id());
1283}
1284
1285
1286HConstant::HConstant(Handle<Object> handle, Representation r)
1287    : handle_(handle),
1288      has_int32_value_(false),
1289      has_double_value_(false),
1290      int32_value_(0),
1291      double_value_(0)  {
1292  set_representation(r);
1293  SetFlag(kUseGVN);
1294  if (handle_->IsNumber()) {
1295    double n = handle_->Number();
1296    double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1297    has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
1298    if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1299    double_value_ = n;
1300    has_double_value_ = true;
1301  }
1302}
1303
1304
1305HConstant* HConstant::CopyToRepresentation(Representation r) const {
1306  if (r.IsInteger32() && !has_int32_value_) return NULL;
1307  if (r.IsDouble() && !has_double_value_) return NULL;
1308  return new HConstant(handle_, r);
1309}
1310
1311
1312HConstant* HConstant::CopyToTruncatedInt32() const {
1313  if (!has_double_value_) return NULL;
1314  int32_t truncated = NumberToInt32(*handle_);
1315  return new HConstant(FACTORY->NewNumberFromInt(truncated),
1316                       Representation::Integer32());
1317}
1318
1319
1320bool HConstant::ToBoolean() const {
1321  // Converts the constant's boolean value according to
1322  // ECMAScript section 9.2 ToBoolean conversion.
1323  if (HasInteger32Value()) return Integer32Value() != 0;
1324  if (HasDoubleValue()) {
1325    double v = DoubleValue();
1326    return v != 0 && !isnan(v);
1327  }
1328  if (handle()->IsTrue()) return true;
1329  if (handle()->IsFalse()) return false;
1330  if (handle()->IsUndefined()) return false;
1331  if (handle()->IsNull()) return false;
1332  if (handle()->IsString() &&
1333      String::cast(*handle())->length() == 0) return false;
1334  return true;
1335}
1336
1337void HConstant::PrintDataTo(StringStream* stream) {
1338  handle()->ShortPrint(stream);
1339}
1340
1341
1342bool HArrayLiteral::IsCopyOnWrite() const {
1343  if (!boilerplate_object_->IsJSObject()) return false;
1344  return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
1345      HEAP->fixed_cow_array_map();
1346}
1347
1348
1349void HBinaryOperation::PrintDataTo(StringStream* stream) {
1350  left()->PrintNameTo(stream);
1351  stream->Add(" ");
1352  right()->PrintNameTo(stream);
1353  if (CheckFlag(kCanOverflow)) stream->Add(" !");
1354  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1355}
1356
1357
1358Range* HBitwise::InferRange(Zone* zone) {
1359  if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
1360  const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
1361  int32_t left_mask = (left()->range() != NULL)
1362      ? left()->range()->Mask()
1363      : kDefaultMask;
1364  int32_t right_mask = (right()->range() != NULL)
1365      ? right()->range()->Mask()
1366      : kDefaultMask;
1367  int32_t result_mask = (op() == Token::BIT_AND)
1368      ? left_mask & right_mask
1369      : left_mask | right_mask;
1370  return (result_mask >= 0)
1371      ? new(zone) Range(0, result_mask)
1372      : HValue::InferRange(zone);
1373}
1374
1375
1376Range* HSar::InferRange(Zone* zone) {
1377  if (right()->IsConstant()) {
1378    HConstant* c = HConstant::cast(right());
1379    if (c->HasInteger32Value()) {
1380      Range* result = (left()->range() != NULL)
1381          ? left()->range()->Copy(zone)
1382          : new(zone) Range();
1383      result->Sar(c->Integer32Value());
1384      result->set_can_be_minus_zero(false);
1385      return result;
1386    }
1387  }
1388  return HValue::InferRange(zone);
1389}
1390
1391
1392Range* HShr::InferRange(Zone* zone) {
1393  if (right()->IsConstant()) {
1394    HConstant* c = HConstant::cast(right());
1395    if (c->HasInteger32Value()) {
1396      int shift_count = c->Integer32Value() & 0x1f;
1397      if (left()->range()->CanBeNegative()) {
1398        // Only compute bounds if the result always fits into an int32.
1399        return (shift_count >= 1)
1400            ? new(zone) Range(0,
1401                              static_cast<uint32_t>(0xffffffff) >> shift_count)
1402            : new(zone) Range();
1403      } else {
1404        // For positive inputs we can use the >> operator.
1405        Range* result = (left()->range() != NULL)
1406            ? left()->range()->Copy(zone)
1407            : new(zone) Range();
1408        result->Sar(c->Integer32Value());
1409        result->set_can_be_minus_zero(false);
1410        return result;
1411      }
1412    }
1413  }
1414  return HValue::InferRange(zone);
1415}
1416
1417
1418Range* HShl::InferRange(Zone* zone) {
1419  if (right()->IsConstant()) {
1420    HConstant* c = HConstant::cast(right());
1421    if (c->HasInteger32Value()) {
1422      Range* result = (left()->range() != NULL)
1423          ? left()->range()->Copy(zone)
1424          : new(zone) Range();
1425      result->Shl(c->Integer32Value());
1426      result->set_can_be_minus_zero(false);
1427      return result;
1428    }
1429  }
1430  return HValue::InferRange(zone);
1431}
1432
1433
1434Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
1435  switch (elements_kind()) {
1436    case EXTERNAL_PIXEL_ELEMENTS:
1437      return new(zone) Range(0, 255);
1438    case EXTERNAL_BYTE_ELEMENTS:
1439      return new(zone) Range(-128, 127);
1440    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1441      return new(zone) Range(0, 255);
1442    case EXTERNAL_SHORT_ELEMENTS:
1443      return new(zone) Range(-32768, 32767);
1444    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1445      return new(zone) Range(0, 65535);
1446    default:
1447      return HValue::InferRange(zone);
1448  }
1449}
1450
1451
1452void HCompareGeneric::PrintDataTo(StringStream* stream) {
1453  stream->Add(Token::Name(token()));
1454  stream->Add(" ");
1455  HBinaryOperation::PrintDataTo(stream);
1456}
1457
1458
1459void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
1460  stream->Add(Token::Name(token()));
1461  stream->Add(" ");
1462  HControlInstruction::PrintDataTo(stream);
1463}
1464
1465
1466void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
1467  stream->Add(Token::Name(token()));
1468  stream->Add(" ");
1469  left()->PrintNameTo(stream);
1470  stream->Add(" ");
1471  right()->PrintNameTo(stream);
1472  HControlInstruction::PrintDataTo(stream);
1473}
1474
1475
1476void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
1477  left()->PrintNameTo(stream);
1478  stream->Add(" ");
1479  right()->PrintNameTo(stream);
1480  HControlInstruction::PrintDataTo(stream);
1481}
1482
1483
1484void HGoto::PrintDataTo(StringStream* stream) {
1485  stream->Add("B%d", SuccessorAt(0)->block_id());
1486}
1487
1488
1489void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
1490  input_representation_ = r;
1491  if (r.IsDouble()) {
1492    // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
1493    // and !=) have special handling of undefined, e.g. undefined == undefined
1494    // is 'true'. Relational comparisons have a different semantic, first
1495    // calling ToPrimitive() on their arguments.  The standard Crankshaft
1496    // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
1497    // are doubles caused 'undefined' to be converted to NaN. That's compatible
1498    // out-of-the box with ordered relational comparisons (<, >, <=,
1499    // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
1500    // it is not consistent with the spec. For example, it would cause undefined
1501    // == undefined (should be true) to be evaluated as NaN == NaN
1502    // (false). Therefore, any comparisons other than ordered relational
1503    // comparisons must cause a deopt when one of their arguments is undefined.
1504    // See also v8:1434
1505    if (!Token::IsOrderedRelationalCompareOp(token_)) {
1506      SetFlag(kDeoptimizeOnUndefined);
1507    }
1508  } else {
1509    ASSERT(r.IsInteger32());
1510  }
1511}
1512
1513
1514void HParameter::PrintDataTo(StringStream* stream) {
1515  stream->Add("%u", index());
1516}
1517
1518
1519void HLoadNamedField::PrintDataTo(StringStream* stream) {
1520  object()->PrintNameTo(stream);
1521  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1522}
1523
1524
1525HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1526                                                       HValue* object,
1527                                                       SmallMapList* types,
1528                                                       Handle<String> name)
1529    : types_(Min(types->length(), kMaxLoadPolymorphism)),
1530      name_(name),
1531      need_generic_(false) {
1532  SetOperandAt(0, context);
1533  SetOperandAt(1, object);
1534  set_representation(Representation::Tagged());
1535  SetGVNFlag(kDependsOnMaps);
1536  for (int i = 0;
1537       i < types->length() && types_.length() < kMaxLoadPolymorphism;
1538       ++i) {
1539    Handle<Map> map = types->at(i);
1540    LookupResult lookup(map->GetIsolate());
1541    map->LookupInDescriptors(NULL, *name, &lookup);
1542    if (lookup.IsFound()) {
1543      switch (lookup.type()) {
1544        case FIELD: {
1545          int index = lookup.GetLocalFieldIndexFromMap(*map);
1546          if (index < 0) {
1547            SetGVNFlag(kDependsOnInobjectFields);
1548          } else {
1549            SetGVNFlag(kDependsOnBackingStoreFields);
1550          }
1551          types_.Add(types->at(i));
1552          break;
1553        }
1554        case CONSTANT_FUNCTION:
1555          types_.Add(types->at(i));
1556          break;
1557        default:
1558          break;
1559      }
1560    }
1561  }
1562
1563  if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1564    SetFlag(kUseGVN);
1565  } else {
1566    SetAllSideEffects();
1567    need_generic_ = true;
1568  }
1569}
1570
1571
1572bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1573  HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1574  if (types_.length() != other->types()->length()) return false;
1575  if (!name_.is_identical_to(other->name())) return false;
1576  if (need_generic_ != other->need_generic_) return false;
1577  for (int i = 0; i < types_.length(); i++) {
1578    bool found = false;
1579    for (int j = 0; j < types_.length(); j++) {
1580      if (types_.at(j).is_identical_to(other->types()->at(i))) {
1581        found = true;
1582        break;
1583      }
1584    }
1585    if (!found) return false;
1586  }
1587  return true;
1588}
1589
1590
1591void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
1592  object()->PrintNameTo(stream);
1593  stream->Add(".");
1594  stream->Add(*String::cast(*name())->ToCString());
1595}
1596
1597
1598void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
1599  object()->PrintNameTo(stream);
1600  stream->Add(".");
1601  stream->Add(*String::cast(*name())->ToCString());
1602}
1603
1604
1605void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
1606  object()->PrintNameTo(stream);
1607  stream->Add("[");
1608  key()->PrintNameTo(stream);
1609  stream->Add("]");
1610}
1611
1612
1613bool HLoadKeyedFastElement::RequiresHoleCheck() {
1614  if (hole_check_mode_ == OMIT_HOLE_CHECK) {
1615    return false;
1616  }
1617
1618  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1619    HValue* use = it.value();
1620    if (!use->IsChange()) return true;
1621  }
1622
1623  return false;
1624}
1625
1626
1627void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1628  elements()->PrintNameTo(stream);
1629  stream->Add("[");
1630  key()->PrintNameTo(stream);
1631  stream->Add("]");
1632}
1633
1634
1635void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1636  object()->PrintNameTo(stream);
1637  stream->Add("[");
1638  key()->PrintNameTo(stream);
1639  stream->Add("]");
1640}
1641
1642
1643HValue* HLoadKeyedGeneric::Canonicalize() {
1644  // Recognize generic keyed loads that use property name generated
1645  // by for-in statement as a key and rewrite them into fast property load
1646  // by index.
1647  if (key()->IsLoadKeyedFastElement()) {
1648    HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
1649    if (key_load->object()->IsForInCacheArray()) {
1650      HForInCacheArray* names_cache =
1651          HForInCacheArray::cast(key_load->object());
1652
1653      if (names_cache->enumerable() == object()) {
1654        HForInCacheArray* index_cache =
1655            names_cache->index_cache();
1656        HCheckMapValue* map_check =
1657            new(block()->zone()) HCheckMapValue(object(), names_cache->map());
1658        HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
1659            index_cache,
1660            key_load->key(),
1661            HLoadKeyedFastElement::OMIT_HOLE_CHECK);
1662        HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
1663            object(), index);
1664        map_check->InsertBefore(this);
1665        index->InsertBefore(this);
1666        load->InsertBefore(this);
1667        return load;
1668      }
1669    }
1670  }
1671
1672  return this;
1673}
1674
1675
1676void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1677    StringStream* stream) {
1678  external_pointer()->PrintNameTo(stream);
1679  stream->Add(".");
1680  switch (elements_kind()) {
1681    case EXTERNAL_BYTE_ELEMENTS:
1682      stream->Add("byte");
1683      break;
1684    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1685      stream->Add("u_byte");
1686      break;
1687    case EXTERNAL_SHORT_ELEMENTS:
1688      stream->Add("short");
1689      break;
1690    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1691      stream->Add("u_short");
1692      break;
1693    case EXTERNAL_INT_ELEMENTS:
1694      stream->Add("int");
1695      break;
1696    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
1697      stream->Add("u_int");
1698      break;
1699    case EXTERNAL_FLOAT_ELEMENTS:
1700      stream->Add("float");
1701      break;
1702    case EXTERNAL_DOUBLE_ELEMENTS:
1703      stream->Add("double");
1704      break;
1705    case EXTERNAL_PIXEL_ELEMENTS:
1706      stream->Add("pixel");
1707      break;
1708    case FAST_ELEMENTS:
1709    case FAST_SMI_ONLY_ELEMENTS:
1710    case FAST_DOUBLE_ELEMENTS:
1711    case DICTIONARY_ELEMENTS:
1712    case NON_STRICT_ARGUMENTS_ELEMENTS:
1713      UNREACHABLE();
1714      break;
1715  }
1716  stream->Add("[");
1717  key()->PrintNameTo(stream);
1718  stream->Add("]");
1719}
1720
1721
1722void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
1723  object()->PrintNameTo(stream);
1724  stream->Add(".");
1725  ASSERT(name()->IsString());
1726  stream->Add(*String::cast(*name())->ToCString());
1727  stream->Add(" = ");
1728  value()->PrintNameTo(stream);
1729}
1730
1731
1732void HStoreNamedField::PrintDataTo(StringStream* stream) {
1733  object()->PrintNameTo(stream);
1734  stream->Add(".");
1735  stream->Add(*String::cast(*name())->ToCString());
1736  stream->Add(" = ");
1737  value()->PrintNameTo(stream);
1738  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1739  if (!transition().is_null()) {
1740    stream->Add(" (transition map %p)", *transition());
1741  }
1742}
1743
1744
1745void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
1746  object()->PrintNameTo(stream);
1747  stream->Add("[");
1748  key()->PrintNameTo(stream);
1749  stream->Add("] = ");
1750  value()->PrintNameTo(stream);
1751}
1752
1753
1754void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1755  elements()->PrintNameTo(stream);
1756  stream->Add("[");
1757  key()->PrintNameTo(stream);
1758  stream->Add("] = ");
1759  value()->PrintNameTo(stream);
1760}
1761
1762
1763void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1764  object()->PrintNameTo(stream);
1765  stream->Add("[");
1766  key()->PrintNameTo(stream);
1767  stream->Add("] = ");
1768  value()->PrintNameTo(stream);
1769}
1770
1771
1772void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1773    StringStream* stream) {
1774  external_pointer()->PrintNameTo(stream);
1775  stream->Add(".");
1776  switch (elements_kind()) {
1777    case EXTERNAL_BYTE_ELEMENTS:
1778      stream->Add("byte");
1779      break;
1780    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1781      stream->Add("u_byte");
1782      break;
1783    case EXTERNAL_SHORT_ELEMENTS:
1784      stream->Add("short");
1785      break;
1786    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1787      stream->Add("u_short");
1788      break;
1789    case EXTERNAL_INT_ELEMENTS:
1790      stream->Add("int");
1791      break;
1792    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
1793      stream->Add("u_int");
1794      break;
1795    case EXTERNAL_FLOAT_ELEMENTS:
1796      stream->Add("float");
1797      break;
1798    case EXTERNAL_DOUBLE_ELEMENTS:
1799      stream->Add("double");
1800      break;
1801    case EXTERNAL_PIXEL_ELEMENTS:
1802      stream->Add("pixel");
1803      break;
1804    case FAST_SMI_ONLY_ELEMENTS:
1805    case FAST_ELEMENTS:
1806    case FAST_DOUBLE_ELEMENTS:
1807    case DICTIONARY_ELEMENTS:
1808    case NON_STRICT_ARGUMENTS_ELEMENTS:
1809      UNREACHABLE();
1810      break;
1811  }
1812  stream->Add("[");
1813  key()->PrintNameTo(stream);
1814  stream->Add("] = ");
1815  value()->PrintNameTo(stream);
1816}
1817
1818
1819void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
1820  object()->PrintNameTo(stream);
1821  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
1822}
1823
1824
1825void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
1826  stream->Add("[%p]", *cell());
1827  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
1828  if (details_.IsReadOnly()) stream->Add(" (read-only)");
1829}
1830
1831
1832bool HLoadGlobalCell::RequiresHoleCheck() {
1833  if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
1834  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1835    HValue* use = it.value();
1836    if (!use->IsChange()) return true;
1837  }
1838  return false;
1839}
1840
1841
1842void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1843  stream->Add("%o ", *name());
1844}
1845
1846
1847void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
1848  stream->Add("[%p] = ", *cell());
1849  value()->PrintNameTo(stream);
1850  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
1851  if (details_.IsReadOnly()) stream->Add(" (read-only)");
1852}
1853
1854
1855void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1856  stream->Add("%o = ", *name());
1857  value()->PrintNameTo(stream);
1858}
1859
1860
1861void HLoadContextSlot::PrintDataTo(StringStream* stream) {
1862  value()->PrintNameTo(stream);
1863  stream->Add("[%d]", slot_index());
1864}
1865
1866
1867void HStoreContextSlot::PrintDataTo(StringStream* stream) {
1868  context()->PrintNameTo(stream);
1869  stream->Add("[%d] = ", slot_index());
1870  value()->PrintNameTo(stream);
1871}
1872
1873
1874// Implementation of type inference and type conversions. Calculates
1875// the inferred type of this instruction based on the input operands.
1876
1877HType HValue::CalculateInferredType() {
1878  return type_;
1879}
1880
1881
1882HType HCheckMap::CalculateInferredType() {
1883  return value()->type();
1884}
1885
1886
1887HType HCheckFunction::CalculateInferredType() {
1888  return value()->type();
1889}
1890
1891
1892HType HCheckNonSmi::CalculateInferredType() {
1893  // TODO(kasperl): Is there any way to signal that this isn't a smi?
1894  return HType::Tagged();
1895}
1896
1897
1898HType HCheckSmi::CalculateInferredType() {
1899  return HType::Smi();
1900}
1901
1902
1903HType HPhi::CalculateInferredType() {
1904  HType result = HType::Uninitialized();
1905  for (int i = 0; i < OperandCount(); ++i) {
1906    HType current = OperandAt(i)->type();
1907    result = result.Combine(current);
1908  }
1909  return result;
1910}
1911
1912
1913HType HConstant::CalculateInferredType() {
1914  return HType::TypeFromValue(handle_);
1915}
1916
1917
1918HType HCompareGeneric::CalculateInferredType() {
1919  return HType::Boolean();
1920}
1921
1922
1923HType HInstanceOf::CalculateInferredType() {
1924  return HType::Boolean();
1925}
1926
1927
1928HType HDeleteProperty::CalculateInferredType() {
1929  return HType::Boolean();
1930}
1931
1932
1933HType HInstanceOfKnownGlobal::CalculateInferredType() {
1934  return HType::Boolean();
1935}
1936
1937
1938HType HChange::CalculateInferredType() {
1939  if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
1940  return type();
1941}
1942
1943
1944HType HBitwiseBinaryOperation::CalculateInferredType() {
1945  return HType::TaggedNumber();
1946}
1947
1948
1949HType HArithmeticBinaryOperation::CalculateInferredType() {
1950  return HType::TaggedNumber();
1951}
1952
1953
1954HType HAdd::CalculateInferredType() {
1955  return HType::Tagged();
1956}
1957
1958
1959HType HBitNot::CalculateInferredType() {
1960  return HType::TaggedNumber();
1961}
1962
1963
1964HType HUnaryMathOperation::CalculateInferredType() {
1965  return HType::TaggedNumber();
1966}
1967
1968
1969HType HStringCharFromCode::CalculateInferredType() {
1970  return HType::String();
1971}
1972
1973
1974HType HAllocateObject::CalculateInferredType() {
1975  return HType::JSObject();
1976}
1977
1978
1979HType HFastLiteral::CalculateInferredType() {
1980  // TODO(mstarzinger): Be smarter, could also be JSArray here.
1981  return HType::JSObject();
1982}
1983
1984
1985HType HArrayLiteral::CalculateInferredType() {
1986  return HType::JSArray();
1987}
1988
1989
1990HType HObjectLiteral::CalculateInferredType() {
1991  return HType::JSObject();
1992}
1993
1994
1995HType HRegExpLiteral::CalculateInferredType() {
1996  return HType::JSObject();
1997}
1998
1999
2000HType HFunctionLiteral::CalculateInferredType() {
2001  return HType::JSObject();
2002}
2003
2004
2005HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
2006    BitVector* visited) {
2007  visited->Add(id());
2008  if (representation().IsInteger32() &&
2009      !value()->representation().IsInteger32()) {
2010    if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2011      SetFlag(kBailoutOnMinusZero);
2012    }
2013  }
2014  if (RequiredInputRepresentation(0).IsInteger32() &&
2015      representation().IsInteger32()) {
2016    return value();
2017  }
2018  return NULL;
2019}
2020
2021
2022
2023HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2024  visited->Add(id());
2025  if (from().IsInteger32()) return NULL;
2026  if (CanTruncateToInt32()) return NULL;
2027  if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2028    SetFlag(kBailoutOnMinusZero);
2029  }
2030  ASSERT(!from().IsInteger32() || !to().IsInteger32());
2031  return NULL;
2032}
2033
2034
2035HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
2036    BitVector* visited) {
2037  visited->Add(id());
2038  return value();
2039}
2040
2041
2042HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2043  visited->Add(id());
2044  if (range() == NULL || range()->CanBeMinusZero()) {
2045    SetFlag(kBailoutOnMinusZero);
2046    return left();
2047  }
2048  return NULL;
2049}
2050
2051
2052HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2053  visited->Add(id());
2054  if (range() == NULL || range()->CanBeMinusZero()) {
2055    SetFlag(kBailoutOnMinusZero);
2056  }
2057  return NULL;
2058}
2059
2060
2061HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2062  visited->Add(id());
2063  if (range() == NULL || range()->CanBeMinusZero()) {
2064    SetFlag(kBailoutOnMinusZero);
2065  }
2066  return NULL;
2067}
2068
2069
2070HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2071  visited->Add(id());
2072  // Propagate to the left argument. If the left argument cannot be -0, then
2073  // the result of the add operation cannot be either.
2074  if (range() == NULL || range()->CanBeMinusZero()) {
2075    return left();
2076  }
2077  return NULL;
2078}
2079
2080
2081HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2082  visited->Add(id());
2083  // Propagate to the left argument. If the left argument cannot be -0, then
2084  // the result of the sub operation cannot be either.
2085  if (range() == NULL || range()->CanBeMinusZero()) {
2086    return left();
2087  }
2088  return NULL;
2089}
2090
2091
2092#define H_CONSTANT_INT32(val)                                                  \
2093new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED),                   \
2094                    Representation::Integer32())
2095#define H_CONSTANT_DOUBLE(val)                                                 \
2096new(zone) HConstant(FACTORY->NewNumber(val, TENURED),                          \
2097                    Representation::Double())
2098
2099#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op)                       \
2100HInstruction* HInstr::New##HInstr(Zone* zone,                                  \
2101                                  HValue* context,                             \
2102                                  HValue* left,                                \
2103                                  HValue* right) {                             \
2104  if (left->IsConstant() && right->IsConstant()) {                             \
2105    HConstant* c_left = HConstant::cast(left);                                 \
2106    HConstant* c_right = HConstant::cast(right);                               \
2107    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
2108      double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
2109      if (TypeInfo::IsInt32Double(double_res)) {                               \
2110        return H_CONSTANT_INT32(static_cast<int32_t>(double_res));             \
2111      }                                                                        \
2112      return H_CONSTANT_DOUBLE(double_res);                                    \
2113    }                                                                          \
2114  }                                                                            \
2115  return new(zone) HInstr(context, left, right);                               \
2116}
2117
2118
2119DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
2120DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
2121DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
2122
2123#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
2124
2125
2126HInstruction* HMod::NewHMod(Zone* zone,
2127                            HValue* context,
2128                            HValue* left,
2129                            HValue* right) {
2130  if (left->IsConstant() && right->IsConstant()) {
2131    HConstant* c_left = HConstant::cast(left);
2132    HConstant* c_right = HConstant::cast(right);
2133    if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
2134      int32_t dividend = c_left->Integer32Value();
2135      int32_t divisor = c_right->Integer32Value();
2136      if (divisor != 0) {
2137        int32_t res = dividend % divisor;
2138        if ((res == 0) && (dividend < 0)) {
2139          return H_CONSTANT_DOUBLE(-0.0);
2140        }
2141        return H_CONSTANT_INT32(res);
2142      }
2143    }
2144  }
2145  return new(zone) HMod(context, left, right);
2146}
2147
2148
2149HInstruction* HDiv::NewHDiv(Zone* zone,
2150                            HValue* context,
2151                            HValue* left,
2152                            HValue* right) {
2153  // If left and right are constant values, try to return a constant value.
2154  if (left->IsConstant() && right->IsConstant()) {
2155    HConstant* c_left = HConstant::cast(left);
2156    HConstant* c_right = HConstant::cast(right);
2157    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2158      if (c_right->DoubleValue() != 0) {
2159        double double_res = c_left->DoubleValue() / c_right->DoubleValue();
2160        if (TypeInfo::IsInt32Double(double_res)) {
2161          return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
2162        }
2163        return H_CONSTANT_DOUBLE(double_res);
2164      }
2165    }
2166  }
2167  return new(zone) HDiv(context, left, right);
2168}
2169
2170
2171HInstruction* HBitwise::NewHBitwise(Zone* zone,
2172                                    Token::Value op,
2173                                    HValue* context,
2174                                    HValue* left,
2175                                    HValue* right) {
2176  if (left->IsConstant() && right->IsConstant()) {
2177    HConstant* c_left = HConstant::cast(left);
2178    HConstant* c_right = HConstant::cast(right);
2179    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2180      int32_t result;
2181      int32_t v_left = c_left->NumberValueAsInteger32();
2182      int32_t v_right = c_right->NumberValueAsInteger32();
2183      switch (op) {
2184        case Token::BIT_XOR:
2185          result = v_left ^ v_right;
2186          break;
2187        case Token::BIT_AND:
2188          result = v_left & v_right;
2189          break;
2190        case Token::BIT_OR:
2191          result = v_left | v_right;
2192          break;
2193        default:
2194          result = 0;  // Please the compiler.
2195          UNREACHABLE();
2196      }
2197      return H_CONSTANT_INT32(result);
2198    }
2199  }
2200  return new(zone) HBitwise(op, context, left, right);
2201}
2202
2203
2204#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result)                             \
2205HInstruction* HInstr::New##HInstr(Zone* zone,                                  \
2206                                  HValue* context,                             \
2207                                  HValue* left,                                \
2208                                  HValue* right) {                             \
2209  if (left->IsConstant() && right->IsConstant()) {                             \
2210    HConstant* c_left = HConstant::cast(left);                                 \
2211    HConstant* c_right = HConstant::cast(right);                               \
2212    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
2213      return H_CONSTANT_INT32(result);                                         \
2214    }                                                                          \
2215  }                                                                            \
2216  return new(zone) HInstr(context, left, right);                               \
2217}
2218
2219
2220DEFINE_NEW_H_BITWISE_INSTR(HSar,
2221c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
2222DEFINE_NEW_H_BITWISE_INSTR(HShl,
2223c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
2224
2225#undef DEFINE_NEW_H_BITWISE_INSTR
2226
2227
2228HInstruction* HShr::NewHShr(Zone* zone,
2229                            HValue* context,
2230                            HValue* left,
2231                            HValue* right) {
2232  if (left->IsConstant() && right->IsConstant()) {
2233    HConstant* c_left = HConstant::cast(left);
2234    HConstant* c_right = HConstant::cast(right);
2235    if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2236      int32_t left_val = c_left->NumberValueAsInteger32();
2237      int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
2238      if ((right_val == 0) && (left_val < 0)) {
2239        return H_CONSTANT_DOUBLE(
2240            static_cast<double>(static_cast<uint32_t>(left_val)));
2241      }
2242      return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
2243    }
2244  }
2245  return new(zone) HShr(context, left, right);
2246}
2247
2248
2249#undef H_CONSTANT_INT32
2250#undef H_CONSTANT_DOUBLE
2251
2252
2253void HIn::PrintDataTo(StringStream* stream) {
2254  key()->PrintNameTo(stream);
2255  stream->Add(" ");
2256  object()->PrintNameTo(stream);
2257}
2258
2259
2260Representation HPhi::InferredRepresentation() {
2261  bool double_occurred = false;
2262  bool int32_occurred = false;
2263  for (int i = 0; i < OperandCount(); ++i) {
2264    HValue* value = OperandAt(i);
2265    if (value->IsUnknownOSRValue()) {
2266      HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
2267      if (hint_value != NULL) {
2268        Representation hint = hint_value->representation();
2269        if (hint.IsDouble()) double_occurred = true;
2270        if (hint.IsInteger32()) int32_occurred = true;
2271      }
2272      continue;
2273    }
2274    if (value->representation().IsDouble()) double_occurred = true;
2275    if (value->representation().IsInteger32()) int32_occurred = true;
2276    if (value->representation().IsTagged()) {
2277      if (value->IsConstant()) {
2278        HConstant* constant = HConstant::cast(value);
2279        if (constant->IsConvertibleToInteger()) {
2280          int32_occurred = true;
2281        } else if (constant->HasNumberValue()) {
2282          double_occurred = true;
2283        } else {
2284          return Representation::Tagged();
2285        }
2286      } else {
2287        return Representation::Tagged();
2288      }
2289    }
2290  }
2291
2292  if (double_occurred) return Representation::Double();
2293
2294  if (int32_occurred) return Representation::Integer32();
2295
2296  return Representation::None();
2297}
2298
2299
2300// Node-specific verification code is only included in debug mode.
2301#ifdef DEBUG
2302
2303void HPhi::Verify() {
2304  ASSERT(OperandCount() == block()->predecessors()->length());
2305  for (int i = 0; i < OperandCount(); ++i) {
2306    HValue* value = OperandAt(i);
2307    HBasicBlock* defining_block = value->block();
2308    HBasicBlock* predecessor_block = block()->predecessors()->at(i);
2309    ASSERT(defining_block == predecessor_block ||
2310           defining_block->Dominates(predecessor_block));
2311  }
2312}
2313
2314
2315void HSimulate::Verify() {
2316  HInstruction::Verify();
2317  ASSERT(HasAstId());
2318}
2319
2320
2321void HCheckSmi::Verify() {
2322  HInstruction::Verify();
2323  ASSERT(HasNoUses());
2324}
2325
2326
2327void HCheckNonSmi::Verify() {
2328  HInstruction::Verify();
2329  ASSERT(HasNoUses());
2330}
2331
2332
2333void HCheckFunction::Verify() {
2334  HInstruction::Verify();
2335  ASSERT(HasNoUses());
2336}
2337
2338
2339void HCheckPrototypeMaps::Verify() {
2340  HInstruction::Verify();
2341  ASSERT(HasNoUses());
2342}
2343
2344#endif
2345
2346} }  // namespace v8::internal
2347