v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hydrogen-instructions.cc
Go to the documentation of this file.
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 
45 namespace v8 {
46 namespace internal {
47 
48 #define DEFINE_COMPILE(type) \
49  LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
50  return builder->Do##type(this); \
51  }
53 #undef DEFINE_COMPILE
54 
55 
56 const 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 
70 int 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 
81  // The representation of the value is dictated by type feedback and
82  // will not be changed later.
84  }
85 }
86 
87 
88 static 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 
101 static 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 
107 static 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 
113 static 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 
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 
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 
143 void Range::Intersect(Range* other) {
144  upper_ = Min(upper_, other->upper_);
145  lower_ = Max(lower_, other->lower_);
146  bool b = CanBeMinusZero() && other->CanBeMinusZero();
148 }
149 
150 
151 void Range::Union(Range* other) {
152  upper_ = Max(upper_, other->upper_);
153  lower_ = Min(lower_, other->lower_);
154  bool b = CanBeMinusZero() || other->CanBeMinusZero();
156 }
157 
158 
159 void 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 
167 void 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 
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 
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 
206  if (lower_ > upper_) {
207  int32_t tmp = lower_;
208  lower_ = upper_;
209  upper_ = tmp;
210  }
211 }
212 
213 
214 #ifdef DEBUG
215 void Range::Verify() const {
216  ASSERT(lower_ <= upper_);
217 }
218 #endif
219 
220 
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 
236 const 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 
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 
275  return block()->block_id() > other->block_id();
276 }
277 
278 
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 
289  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
290  if (!it.value()->CheckFlag(f)) return false;
291  }
292  return true;
293 }
294 
295 
296 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
297  Advance();
298 }
299 
300 
301 void 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 
311 int HValue::UseCount() const {
312  int count = 0;
313  for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
314  return count;
315 }
316 
317 
318 HUseListNode* 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(block()->zone())
340  HUseListNode(current->value(), current->index(), NULL);
341  current->Zap();
342  current = temp;
343  }
344 #endif
345  return current;
346 }
347 
348 
349 bool HValue::Equals(HValue* other) {
350  if (other->opcode() != opcode()) return false;
351  if (!other->representation().Equals(representation())) return false;
352  if (!other->type_.Equals(type_)) return false;
353  if (other->flags() != flags()) return false;
354  if (OperandCount() != other->OperandCount()) return false;
355  for (int i = 0; i < OperandCount(); ++i) {
356  if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
357  }
358  bool result = DataEquals(other);
359  ASSERT(!result || Hashcode() == other->Hashcode());
360  return result;
361 }
362 
363 
364 intptr_t HValue::Hashcode() {
365  intptr_t result = opcode();
366  int count = OperandCount();
367  for (int i = 0; i < count; ++i) {
368  result = result * 19 + OperandAt(i)->id() + (result >> 7);
369  }
370  return result;
371 }
372 
373 
374 const char* HValue::Mnemonic() const {
375  switch (opcode()) {
376 #define MAKE_CASE(type) case k##type: return #type;
378 #undef MAKE_CASE
379  case kPhi: return "Phi";
380  default: return "";
381  }
382 }
383 
384 
385 void HValue::SetOperandAt(int index, HValue* value) {
386  RegisterUse(index, value);
387  InternalSetOperandAt(index, value);
388 }
389 
390 
392  // We replace all uses first, so Delete can assert that there are none.
393  if (other != NULL) ReplaceAllUsesWith(other);
394  ASSERT(HasNoUses());
395  Kill();
396  DeleteFromGraph();
397 }
398 
399 
401  while (use_list_ != NULL) {
402  HUseListNode* list_node = use_list_;
403  HValue* value = list_node->value();
404  ASSERT(!value->block()->IsStartBlock());
405  value->InternalSetOperandAt(list_node->index(), other);
406  use_list_ = list_node->tail();
407  list_node->set_tail(other->use_list_);
408  other->use_list_ = list_node;
409  }
410 }
411 
412 
413 void HValue::Kill() {
414  // Instead of going through the entire use list of each operand, we only
415  // check the first item in each use list and rely on the tail() method to
416  // skip dead items, removing them lazily next time we traverse the list.
417  SetFlag(kIsDead);
418  for (int i = 0; i < OperandCount(); ++i) {
419  HValue* operand = OperandAt(i);
420  if (operand == NULL) continue;
421  HUseListNode* first = operand->use_list_;
422  if (first != NULL && first->value() == this && first->index() == i) {
423  operand->use_list_ = first->tail();
424  }
425  }
426 }
427 
428 
430  ASSERT(block_ == NULL || block == NULL);
431  block_ = block;
432  if (id_ == kNoNumber && block != NULL) {
433  id_ = block->graph()->GetNextValueID(this);
434  }
435 }
436 
437 
439  if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
440  stream->Add(" type[%s]", type().ToString());
441 }
442 
443 
445  if (range() == NULL || range()->IsMostGeneric()) return;
446  stream->Add(" range[%d,%d,m0=%d]",
447  range()->lower(),
448  range()->upper(),
449  static_cast<int>(range()->CanBeMinusZero()));
450 }
451 
452 
454  GVNFlagSet changes_flags = ChangesFlags();
455  if (changes_flags.IsEmpty()) return;
456  stream->Add(" changes[");
457  if (changes_flags == AllSideEffectsFlagSet()) {
458  stream->Add("*");
459  } else {
460  bool add_comma = false;
461 #define PRINT_DO(type) \
462  if (changes_flags.Contains(kChanges##type)) { \
463  if (add_comma) stream->Add(","); \
464  add_comma = true; \
465  stream->Add(#type); \
466  }
469 #undef PRINT_DO
470  }
471  stream->Add("]");
472 }
473 
474 
476  stream->Add("%s%d", representation_.Mnemonic(), id());
477 }
478 
479 
482  bool result = (!type.Equals(type_));
483  type_ = type;
484  return result;
485 }
486 
487 
488 void HValue::RegisterUse(int index, HValue* new_value) {
489  HValue* old_value = OperandAt(index);
490  if (old_value == new_value) return;
491 
492  HUseListNode* removed = NULL;
493  if (old_value != NULL) {
494  removed = old_value->RemoveUse(this, index);
495  }
496 
497  if (new_value != NULL) {
498  if (removed == NULL) {
499  new_value->use_list_ = new(new_value->block()->zone()) HUseListNode(
500  this, index, new_value->use_list_);
501  } else {
502  removed->set_tail(new_value->use_list_);
503  new_value->use_list_ = removed;
504  }
505  }
506 }
507 
508 
509 void HValue::AddNewRange(Range* r, Zone* zone) {
510  if (!HasRange()) ComputeInitialRange(zone);
511  if (!HasRange()) range_ = new(zone) Range();
512  ASSERT(HasRange());
513  r->StackUpon(range_);
514  range_ = r;
515 }
516 
517 
519  ASSERT(HasRange());
520  ASSERT(range_->next() != NULL);
521  range_ = range_->next();
522 }
523 
524 
526  ASSERT(!HasRange());
527  range_ = InferRange(zone);
528  ASSERT(HasRange());
529 }
530 
531 
533  PrintMnemonicTo(stream);
534  PrintDataTo(stream);
535  PrintRangeTo(stream);
536  PrintChangesTo(stream);
537  PrintTypeTo(stream);
538 }
539 
540 
541 void HInstruction::PrintMnemonicTo(StringStream* stream) {
542  stream->Add("%s ", Mnemonic());
543 }
544 
545 
547  ASSERT(IsLinked());
548  ASSERT(!IsControlInstruction()); // Must never move control instructions.
549  ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these.
550  ASSERT(previous_ != NULL);
551  previous_->next_ = next_;
552  if (next_ == NULL) {
553  ASSERT(block()->last() == this);
554  block()->set_last(previous_);
555  } else {
556  next_->previous_ = previous_;
557  }
558  clear_block();
559 }
560 
561 
563  ASSERT(!IsLinked());
564  ASSERT(!next->IsBlockEntry());
565  ASSERT(!IsControlInstruction());
566  ASSERT(!next->block()->IsStartBlock());
567  ASSERT(next->previous_ != NULL);
568  HInstruction* prev = next->previous();
569  prev->next_ = this;
570  next->previous_ = this;
571  next_ = next;
572  previous_ = prev;
573  SetBlock(next->block());
574 }
575 
576 
578  ASSERT(!IsLinked());
579  ASSERT(!previous->IsControlInstruction());
580  ASSERT(!IsControlInstruction() || previous->next_ == NULL);
581  HBasicBlock* block = previous->block();
582  // Never insert anything except constants into the start block after finishing
583  // it.
584  if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
585  ASSERT(block->end()->SecondSuccessor() == NULL);
586  InsertAfter(block->end()->FirstSuccessor()->first());
587  return;
588  }
589 
590  // If we're inserting after an instruction with side-effects that is
591  // followed by a simulate instruction, we need to insert after the
592  // simulate instruction instead.
593  HInstruction* next = previous->next_;
594  if (previous->HasObservableSideEffects() && next != NULL) {
595  ASSERT(next->IsSimulate());
596  previous = next;
597  next = previous->next_;
598  }
599 
600  previous_ = previous;
601  next_ = next;
602  SetBlock(block);
603  previous->next_ = this;
604  if (next != NULL) next->previous_ = this;
605  if (block->last() == previous) {
606  block->set_last(this);
607  }
608 }
609 
610 
611 #ifdef DEBUG
612 void HInstruction::Verify() {
613  // Verify that input operands are defined before use.
614  HBasicBlock* cur_block = block();
615  for (int i = 0; i < OperandCount(); ++i) {
616  HValue* other_operand = OperandAt(i);
617  if (other_operand == NULL) continue;
618  HBasicBlock* other_block = other_operand->block();
619  if (cur_block == other_block) {
620  if (!other_operand->IsPhi()) {
621  HInstruction* cur = this->previous();
622  while (cur != NULL) {
623  if (cur == other_operand) break;
624  cur = cur->previous();
625  }
626  // Must reach other operand in the same block!
627  ASSERT(cur == other_operand);
628  }
629  } else {
630  // If the following assert fires, you may have forgotten an
631  // AddInstruction.
632  ASSERT(other_block->Dominates(cur_block));
633  }
634  }
635 
636  // Verify that instructions that may have side-effects are followed
637  // by a simulate instruction.
638  if (HasObservableSideEffects() && !IsOsrEntry()) {
639  ASSERT(next()->IsSimulate());
640  }
641 
642  // Verify that instructions that can be eliminated by GVN have overridden
643  // HValue::DataEquals. The default implementation is UNREACHABLE. We
644  // don't actually care whether DataEquals returns true or false here.
645  if (CheckFlag(kUseGVN)) DataEquals(this);
646 }
647 #endif
648 
649 
651  value()->PrintNameTo(stream);
652  stream->Add(" ");
653  stream->Add("#%d", argument_count());
654 }
655 
656 
658  first()->PrintNameTo(stream);
659  stream->Add(" ");
660  second()->PrintNameTo(stream);
661  stream->Add(" ");
662  stream->Add("#%d", argument_count());
663 }
664 
665 
667  index()->PrintNameTo(stream);
668  stream->Add(" ");
669  length()->PrintNameTo(stream);
670 }
671 
672 
674  if (IsApplyFunction()) {
675  stream->Add("optimized apply ");
676  } else {
677  stream->Add("%o ", function()->shared()->DebugName());
678  }
679  stream->Add("#%d", argument_count());
680 }
681 
682 
684  stream->Add("%o ", *name());
685  HUnaryCall::PrintDataTo(stream);
686 }
687 
688 
690  stream->Add("%o ", *name());
691  HUnaryCall::PrintDataTo(stream);
692 }
693 
694 
696  stream->Add("o ", target()->shared()->DebugName());
697  stream->Add("#%d", argument_count());
698 }
699 
700 
702  stream->Add("%o ", *name());
703  stream->Add("#%d", argument_count());
704 }
705 
706 
708  stream->Add("class_of_test(");
709  value()->PrintNameTo(stream);
710  stream->Add(", \"%o\")", *class_name());
711 }
712 
713 
715  arguments()->PrintNameTo(stream);
716  stream->Add("[");
717  index()->PrintNameTo(stream);
718  stream->Add("], length ");
719  length()->PrintNameTo(stream);
720 }
721 
722 
724  stream->Add(" goto (");
725  bool first_block = true;
726  for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
727  stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
728  first_block = false;
729  }
730  stream->Add(")");
731 }
732 
733 
735  value()->PrintNameTo(stream);
737 }
738 
739 
741  value()->PrintNameTo(stream);
742  stream->Add(kind() == kStrictEquality ? " === " : " == ");
743  stream->Add(nil() == kNullValue ? "null" : "undefined");
745 }
746 
747 
749  value()->PrintNameTo(stream);
750 }
751 
752 
754  value()->PrintNameTo(stream);
755  stream->Add(" (%p)", *map());
757 }
758 
759 
760 const char* HUnaryMathOperation::OpName() const {
761  switch (op()) {
762  case kMathFloor: return "floor";
763  case kMathRound: return "round";
764  case kMathCeil: return "ceil";
765  case kMathAbs: return "abs";
766  case kMathLog: return "log";
767  case kMathSin: return "sin";
768  case kMathCos: return "cos";
769  case kMathTan: return "tan";
770  case kMathASin: return "asin";
771  case kMathACos: return "acos";
772  case kMathATan: return "atan";
773  case kMathExp: return "exp";
774  case kMathSqrt: return "sqrt";
775  default: break;
776  }
777  return "(unknown operation)";
778 }
779 
780 
782  const char* name = OpName();
783  stream->Add("%s ", name);
784  value()->PrintNameTo(stream);
785 }
786 
787 
789  value()->PrintNameTo(stream);
790 }
791 
792 
794  value()->PrintNameTo(stream);
795  switch (from_) {
797  if (to_ == LAST_TYPE) stream->Add(" spec_object");
798  break;
799  case JS_REGEXP_TYPE:
800  if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
801  break;
802  case JS_ARRAY_TYPE:
803  if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
804  break;
805  case JS_FUNCTION_TYPE:
806  if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
807  break;
808  default:
809  break;
810  }
811 }
812 
813 
815  value()->PrintNameTo(stream);
816  stream->Add(" == %o", *type_literal_);
818 }
819 
820 
822  value()->PrintNameTo(stream);
823  stream->Add(" ");
824  map()->PrintNameTo(stream);
825 }
826 
827 
829  enumerable()->PrintNameTo(stream);
830 }
831 
832 
834  enumerable()->PrintNameTo(stream);
835  stream->Add(" ");
836  map()->PrintNameTo(stream);
837  stream->Add("[%d]", idx_);
838 }
839 
840 
842  object()->PrintNameTo(stream);
843  stream->Add(" ");
844  index()->PrintNameTo(stream);
845 }
846 
847 
849  return HasNoUses() ? NULL : this;
850 }
851 
852 
854  return HasNoUses() ? NULL : this;
855 }
856 
857 
859  if (!representation().IsInteger32()) return this;
860  // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
861  int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
862  if (left()->IsConstant() &&
863  HConstant::cast(left())->HasInteger32Value() &&
864  HConstant::cast(left())->Integer32Value() == nop_constant) {
865  return right();
866  }
867  if (right()->IsConstant() &&
868  HConstant::cast(right())->HasInteger32Value() &&
869  HConstant::cast(right())->Integer32Value() == nop_constant) {
870  return left();
871  }
872  return this;
873 }
874 
875 
877  // Optimize ~~x, a common pattern used for ToInt32(x).
878  if (value()->IsBitNot()) {
879  HValue* result = HBitNot::cast(value())->value();
880  ASSERT(result->representation().IsInteger32());
881  return result;
882  }
883  return this;
884 }
885 
886 
888  if (!representation().IsInteger32()) return this;
890  return this;
891 }
892 
893 
895  if (!representation().IsInteger32()) return this;
897  return this;
898 }
899 
900 
902  return (from().Equals(to())) ? value() : this;
903 }
904 
905 
907  if (HasNoUses()) return NULL;
908  if (receiver()->type().IsJSObject()) {
909  return receiver();
910  }
911  return this;
912 }
913 
914 
916  value()->PrintNameTo(stream);
917 }
918 
919 
922  stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
923 
924  if (CanTruncateToInt32()) stream->Add(" truncating-int32");
925  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
926  if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
927 }
928 
929 
931  value()->PrintNameTo(stream);
932  stream->Add(" ");
933  typecheck()->PrintNameTo(stream);
934 }
935 
936 
938  if (op() == kMathFloor) {
939  // If the input is integer32 then we replace the floor instruction
940  // with its input. This happens before the representation changes are
941  // introduced.
942  if (value()->representation().IsInteger32()) return value();
943 
944 #ifdef V8_TARGET_ARCH_ARM
945  if (value()->IsDiv() && (value()->UseCount() == 1)) {
946  // TODO(2038): Implement this optimization for non ARM architectures.
947  HDiv* hdiv = HDiv::cast(value());
948  HValue* left = hdiv->left();
949  HValue* right = hdiv->right();
950  // Try to simplify left and right values of the division.
951  HValue* new_left =
952  LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(left);
953  HValue* new_right =
954  LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
955 
956  // Return if left or right are not optimizable.
957  if ((new_left == NULL) || (new_right == NULL)) return this;
958 
959  // Insert the new values in the graph.
960  if (new_left->IsInstruction() &&
961  !HInstruction::cast(new_left)->IsLinked()) {
962  HInstruction::cast(new_left)->InsertBefore(this);
963  }
964  if (new_right->IsInstruction() &&
965  !HInstruction::cast(new_right)->IsLinked()) {
966  HInstruction::cast(new_right)->InsertBefore(this);
967  }
968  HMathFloorOfDiv* instr = new(block()->zone()) HMathFloorOfDiv(context(),
969  new_left,
970  new_right);
971  // Replace this HMathFloor instruction by the new HMathFloorOfDiv.
972  instr->InsertBefore(this);
973  ReplaceAllUsesWith(instr);
974  Kill();
975  // We know the division had no other uses than this HMathFloor. Delete it.
976  // Also delete the arguments of the division if they are not used any
977  // more.
978  hdiv->DeleteAndReplaceWith(NULL);
979  ASSERT(left->IsChange() || left->IsConstant());
980  ASSERT(right->IsChange() || right->IsConstant());
981  if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL);
982  if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL);
983 
984  // Return NULL to remove this instruction from the graph.
985  return NULL;
986  }
987 #endif // V8_TARGET_ARCH_ARM
988  }
989  return this;
990 }
991 
992 
994  if (check_ == IS_STRING &&
995  !value()->type().IsUninitialized() &&
996  value()->type().IsString()) {
997  return NULL;
998  }
999  if (check_ == IS_SYMBOL &&
1000  value()->IsConstant() &&
1001  HConstant::cast(value())->handle()->IsSymbol()) {
1002  return NULL;
1003  }
1004  return this;
1005 }
1006 
1007 
1009  InstanceType* last) {
1011  switch (check_) {
1012  case IS_SPEC_OBJECT:
1013  *first = FIRST_SPEC_OBJECT_TYPE;
1014  *last = LAST_SPEC_OBJECT_TYPE;
1015  return;
1016  case IS_JS_ARRAY:
1017  *first = *last = JS_ARRAY_TYPE;
1018  return;
1019  default:
1020  UNREACHABLE();
1021  }
1022 }
1023 
1024 
1025 void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
1027  switch (check_) {
1028  case IS_STRING:
1029  *mask = kIsNotStringMask;
1030  *tag = kStringTag;
1031  return;
1032  case IS_SYMBOL:
1033  *mask = kIsSymbolMask;
1034  *tag = kSymbolTag;
1035  return;
1036  default:
1037  UNREACHABLE();
1038  }
1039 }
1040 
1041 
1043  value()->PrintNameTo(stream);
1044  stream->Add(" [%p", *map_set()->first());
1045  for (int i = 1; i < map_set()->length(); ++i) {
1046  stream->Add(",%p", *map_set()->at(i));
1047  }
1048  stream->Add("]");
1049 }
1050 
1051 
1053  value()->PrintNameTo(stream);
1054  stream->Add(" %p", *target());
1055 }
1056 
1057 
1058 const char* HCheckInstanceType::GetCheckName() {
1059  switch (check_) {
1060  case IS_SPEC_OBJECT: return "object";
1061  case IS_JS_ARRAY: return "array";
1062  case IS_STRING: return "string";
1063  case IS_SYMBOL: return "symbol";
1064  }
1065  UNREACHABLE();
1066  return "";
1067 }
1068 
1070  stream->Add("%s ", GetCheckName());
1072 }
1073 
1074 
1076  stream->Add("%s ",
1077  CodeStub::MajorName(major_key_, false));
1078  HUnaryCall::PrintDataTo(stream);
1079 }
1080 
1081 
1083  left()->PrintNameTo(stream);
1084  stream->Add(" ");
1085  right()->PrintNameTo(stream);
1086  stream->Add(" ");
1087  context()->PrintNameTo(stream);
1088 }
1089 
1090 
1092  // Untagged integer32 cannot be -0, all other representations can.
1093  Range* result = new(zone) Range();
1094  result->set_can_be_minus_zero(!representation().IsInteger32());
1095  return result;
1096 }
1097 
1098 
1100  Range* input_range = value()->range();
1101  if (from().IsInteger32() &&
1102  to().IsTagged() &&
1103  input_range != NULL && input_range->IsInSmiRange()) {
1104  set_type(HType::Smi());
1105  }
1106  Range* result = (input_range != NULL)
1107  ? input_range->Copy(zone)
1108  : HValue::InferRange(zone);
1109  if (to().IsInteger32()) result->set_can_be_minus_zero(false);
1110  return result;
1111 }
1112 
1113 
1115  if (has_int32_value_) {
1116  Range* result = new(zone) Range(int32_value_, int32_value_);
1117  result->set_can_be_minus_zero(false);
1118  return result;
1119  }
1120  return HValue::InferRange(zone);
1121 }
1122 
1123 
1125  if (representation().IsInteger32()) {
1126  if (block()->IsLoopHeader()) {
1127  Range* range = new(zone) Range(kMinInt, kMaxInt);
1128  return range;
1129  } else {
1130  Range* range = OperandAt(0)->range()->Copy(zone);
1131  for (int i = 1; i < OperandCount(); ++i) {
1132  range->Union(OperandAt(i)->range());
1133  }
1134  return range;
1135  }
1136  } else {
1137  return HValue::InferRange(zone);
1138  }
1139 }
1140 
1141 
1143  if (representation().IsInteger32()) {
1144  Range* a = left()->range();
1145  Range* b = right()->range();
1146  Range* res = a->Copy(zone);
1147  if (!res->AddAndCheckOverflow(b)) {
1149  }
1150  bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
1151  res->set_can_be_minus_zero(m0);
1152  return res;
1153  } else {
1154  return HValue::InferRange(zone);
1155  }
1156 }
1157 
1158 
1160  if (representation().IsInteger32()) {
1161  Range* a = left()->range();
1162  Range* b = right()->range();
1163  Range* res = a->Copy(zone);
1164  if (!res->SubAndCheckOverflow(b)) {
1166  }
1167  res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
1168  return res;
1169  } else {
1170  return HValue::InferRange(zone);
1171  }
1172 }
1173 
1174 
1176  if (representation().IsInteger32()) {
1177  Range* a = left()->range();
1178  Range* b = right()->range();
1179  Range* res = a->Copy(zone);
1180  if (!res->MulAndCheckOverflow(b)) {
1182  }
1183  bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
1184  (a->CanBeNegative() && b->CanBeZero());
1185  res->set_can_be_minus_zero(m0);
1186  return res;
1187  } else {
1188  return HValue::InferRange(zone);
1189  }
1190 }
1191 
1192 
1194  if (representation().IsInteger32()) {
1195  Range* result = new(zone) Range();
1196  if (left()->range()->CanBeMinusZero()) {
1197  result->set_can_be_minus_zero(true);
1198  }
1199 
1200  if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1201  result->set_can_be_minus_zero(true);
1202  }
1203 
1204  if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1206  }
1207 
1208  if (!right()->range()->CanBeZero()) {
1210  }
1211  return result;
1212  } else {
1213  return HValue::InferRange(zone);
1214  }
1215 }
1216 
1217 
1219  if (representation().IsInteger32()) {
1220  Range* a = left()->range();
1221  Range* result = new(zone) Range();
1222  if (a->CanBeMinusZero() || a->CanBeNegative()) {
1223  result->set_can_be_minus_zero(true);
1224  }
1225  if (!right()->range()->CanBeZero()) {
1227  }
1228  return result;
1229  } else {
1230  return HValue::InferRange(zone);
1231  }
1232 }
1233 
1234 
1236  stream->Add("[");
1237  for (int i = 0; i < OperandCount(); ++i) {
1238  HValue* value = OperandAt(i);
1239  stream->Add(" ");
1240  value->PrintNameTo(stream);
1241  stream->Add(" ");
1242  }
1243  stream->Add(" uses%d_%di_%dd_%dt",
1244  UseCount(),
1248  stream->Add("%s%s]",
1249  is_live() ? "_live" : "",
1250  IsConvertibleToInteger() ? "" : "_ncti");
1251 }
1252 
1253 
1254 void HPhi::AddInput(HValue* value) {
1255  inputs_.Add(NULL, value->block()->zone());
1256  SetOperandAt(OperandCount() - 1, value);
1257  // Mark phis that may have 'arguments' directly or indirectly as an operand.
1258  if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1260  }
1261 }
1262 
1263 
1265  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1266  if (!it.value()->IsPhi()) return true;
1267  }
1268  return false;
1269 }
1270 
1271 
1273  HValue* candidate = NULL;
1274  int count = OperandCount();
1275  int position = 0;
1276  while (position < count && candidate == NULL) {
1277  HValue* current = OperandAt(position++);
1278  if (current != this) candidate = current;
1279  }
1280  while (position < count) {
1281  HValue* current = OperandAt(position++);
1282  if (current != this && current != candidate) return NULL;
1283  }
1284  ASSERT(candidate != this);
1285  return candidate;
1286 }
1287 
1288 
1290  ASSERT(block() != NULL);
1291  block()->RemovePhi(this);
1292  ASSERT(block() == NULL);
1293 }
1294 
1295 
1296 void HPhi::InitRealUses(int phi_id) {
1297  // Initialize real uses.
1298  phi_id_ = phi_id;
1299  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1300  HValue* value = it.value();
1301  if (!value->IsPhi()) {
1302  Representation rep = value->ObservedInputRepresentation(it.index());
1303  non_phi_uses_[rep.kind()] += value->LoopWeight();
1304  if (FLAG_trace_representation) {
1305  PrintF("%d %s is used by %d %s as %s\n",
1306  this->id(),
1307  this->Mnemonic(),
1308  value->id(),
1309  value->Mnemonic(),
1310  rep.Mnemonic());
1311  }
1312  }
1313  }
1314 }
1315 
1316 
1318  if (FLAG_trace_representation) {
1319  PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n",
1320  this->id(),
1321  this->Mnemonic(),
1322  other->id(),
1323  other->Mnemonic(),
1324  other->non_phi_uses_[Representation::kInteger32],
1325  other->non_phi_uses_[Representation::kDouble],
1326  other->non_phi_uses_[Representation::kTagged]);
1327  }
1328 
1329  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1330  indirect_uses_[i] += other->non_phi_uses_[i];
1331  }
1332 }
1333 
1334 
1335 void HPhi::AddIndirectUsesTo(int* dest) {
1336  for (int i = 0; i < Representation::kNumRepresentations; i++) {
1337  dest[i] += indirect_uses_[i];
1338  }
1339 }
1340 
1341 
1343  non_phi_uses_[Representation::kInteger32] = 0;
1344  indirect_uses_[Representation::kInteger32] = 0;
1345 }
1346 
1347 
1349  stream->Add("id=%d", ast_id());
1350  if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
1351  if (values_.length() > 0) {
1352  if (pop_count_ > 0) stream->Add(" /");
1353  for (int i = 0; i < values_.length(); ++i) {
1354  if (i > 0) stream->Add(",");
1355  if (HasAssignedIndexAt(i)) {
1356  stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1357  } else {
1358  stream->Add(" push ");
1359  }
1360  values_[i]->PrintNameTo(stream);
1361  }
1362  }
1363 }
1364 
1365 
1367  if (OperandCount() == 0) return;
1368  OperandAt(0)->PrintNameTo(stream);
1369  for (int i = 1; i < OperandCount(); ++i) {
1370  stream->Add(" ");
1371  OperandAt(i)->PrintNameTo(stream);
1372  }
1373 }
1374 
1375 
1377  SmartArrayPointer<char> name = function()->debug_name()->ToCString();
1378  stream->Add("%s, id=%d", *name, function()->id());
1379 }
1380 
1381 
1383  : handle_(handle),
1384  has_int32_value_(false),
1385  has_double_value_(false),
1386  int32_value_(0),
1387  double_value_(0) {
1388  set_representation(r);
1389  SetFlag(kUseGVN);
1390  if (handle_->IsNumber()) {
1391  double n = handle_->Number();
1392  double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1393  has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
1394  if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1395  double_value_ = n;
1396  has_double_value_ = true;
1397  }
1398 }
1399 
1400 
1402  if (r.IsInteger32() && !has_int32_value_) return NULL;
1403  if (r.IsDouble() && !has_double_value_) return NULL;
1404  return new(zone) HConstant(handle_, r);
1405 }
1406 
1407 
1409  if (!has_double_value_) return NULL;
1410  int32_t truncated = NumberToInt32(*handle_);
1411  return new(zone) HConstant(FACTORY->NewNumberFromInt(truncated),
1413 }
1414 
1415 
1416 bool HConstant::ToBoolean() const {
1417  // Converts the constant's boolean value according to
1418  // ECMAScript section 9.2 ToBoolean conversion.
1419  if (HasInteger32Value()) return Integer32Value() != 0;
1420  if (HasDoubleValue()) {
1421  double v = DoubleValue();
1422  return v != 0 && !isnan(v);
1423  }
1424  if (handle()->IsTrue()) return true;
1425  if (handle()->IsFalse()) return false;
1426  if (handle()->IsUndefined()) return false;
1427  if (handle()->IsNull()) return false;
1428  if (handle()->IsString() &&
1429  String::cast(*handle())->length() == 0) return false;
1430  return true;
1431 }
1432 
1434  handle()->ShortPrint(stream);
1435 }
1436 
1437 
1439  if (!boilerplate_object_->IsJSObject()) return false;
1440  return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
1441  HEAP->fixed_cow_array_map();
1442 }
1443 
1444 
1446  left()->PrintNameTo(stream);
1447  stream->Add(" ");
1448  right()->PrintNameTo(stream);
1449  if (CheckFlag(kCanOverflow)) stream->Add(" !");
1450  if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1451 }
1452 
1453 
1455  if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
1456  const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
1457  int32_t left_mask = (left()->range() != NULL)
1458  ? left()->range()->Mask()
1459  : kDefaultMask;
1460  int32_t right_mask = (right()->range() != NULL)
1461  ? right()->range()->Mask()
1462  : kDefaultMask;
1463  int32_t result_mask = (op() == Token::BIT_AND)
1464  ? left_mask & right_mask
1465  : left_mask | right_mask;
1466  return (result_mask >= 0)
1467  ? new(zone) Range(0, result_mask)
1468  : HValue::InferRange(zone);
1469 }
1470 
1471 
1473  if (right()->IsConstant()) {
1475  if (c->HasInteger32Value()) {
1476  Range* result = (left()->range() != NULL)
1477  ? left()->range()->Copy(zone)
1478  : new(zone) Range();
1479  result->Sar(c->Integer32Value());
1480  result->set_can_be_minus_zero(false);
1481  return result;
1482  }
1483  }
1484  return HValue::InferRange(zone);
1485 }
1486 
1487 
1489  if (right()->IsConstant()) {
1491  if (c->HasInteger32Value()) {
1492  int shift_count = c->Integer32Value() & 0x1f;
1493  if (left()->range()->CanBeNegative()) {
1494  // Only compute bounds if the result always fits into an int32.
1495  return (shift_count >= 1)
1496  ? new(zone) Range(0,
1497  static_cast<uint32_t>(0xffffffff) >> shift_count)
1498  : new(zone) Range();
1499  } else {
1500  // For positive inputs we can use the >> operator.
1501  Range* result = (left()->range() != NULL)
1502  ? left()->range()->Copy(zone)
1503  : new(zone) Range();
1504  result->Sar(c->Integer32Value());
1505  result->set_can_be_minus_zero(false);
1506  return result;
1507  }
1508  }
1509  }
1510  return HValue::InferRange(zone);
1511 }
1512 
1513 
1515  if (right()->IsConstant()) {
1517  if (c->HasInteger32Value()) {
1518  Range* result = (left()->range() != NULL)
1519  ? left()->range()->Copy(zone)
1520  : new(zone) Range();
1521  result->Shl(c->Integer32Value());
1522  result->set_can_be_minus_zero(false);
1523  return result;
1524  }
1525  }
1526  return HValue::InferRange(zone);
1527 }
1528 
1529 
1531  switch (elements_kind()) {
1533  return new(zone) Range(0, 255);
1535  return new(zone) Range(-128, 127);
1537  return new(zone) Range(0, 255);
1539  return new(zone) Range(-32768, 32767);
1541  return new(zone) Range(0, 65535);
1542  default:
1543  return HValue::InferRange(zone);
1544  }
1545 }
1546 
1547 
1549  stream->Add(Token::Name(token()));
1550  stream->Add(" ");
1552 }
1553 
1554 
1556  stream->Add(Token::Name(token()));
1557  stream->Add(" ");
1559 }
1560 
1561 
1563  stream->Add(Token::Name(token()));
1564  stream->Add(" ");
1565  left()->PrintNameTo(stream);
1566  stream->Add(" ");
1567  right()->PrintNameTo(stream);
1569 }
1570 
1571 
1573  left()->PrintNameTo(stream);
1574  stream->Add(" ");
1575  right()->PrintNameTo(stream);
1577 }
1578 
1579 
1581  stream->Add("B%d", SuccessorAt(0)->block_id());
1582 }
1583 
1584 
1586  input_representation_ = r;
1587  if (r.IsDouble()) {
1588  // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
1589  // and !=) have special handling of undefined, e.g. undefined == undefined
1590  // is 'true'. Relational comparisons have a different semantic, first
1591  // calling ToPrimitive() on their arguments. The standard Crankshaft
1592  // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
1593  // are doubles caused 'undefined' to be converted to NaN. That's compatible
1594  // out-of-the box with ordered relational comparisons (<, >, <=,
1595  // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
1596  // it is not consistent with the spec. For example, it would cause undefined
1597  // == undefined (should be true) to be evaluated as NaN == NaN
1598  // (false). Therefore, any comparisons other than ordered relational
1599  // comparisons must cause a deopt when one of their arguments is undefined.
1600  // See also v8:1434
1601  if (!Token::IsOrderedRelationalCompareOp(token_)) {
1603  }
1604  } else {
1605  ASSERT(r.IsInteger32());
1606  }
1607 }
1608 
1609 
1611  stream->Add("%u", index());
1612 }
1613 
1614 
1616  object()->PrintNameTo(stream);
1617  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1618 }
1619 
1620 
1621 // Returns true if an instance of this map can never find a property with this
1622 // name in its prototype chain. This means all prototypes up to the top are
1623 // fast and don't have the name in them. It would be good if we could optimize
1624 // polymorphic loads where the property is sometimes found in the prototype
1625 // chain.
1626 static bool PrototypeChainCanNeverResolve(
1628  Isolate* isolate = map->GetIsolate();
1629  Object* current = map->prototype();
1630  while (current != isolate->heap()->null_value()) {
1631  if (current->IsJSGlobalProxy() ||
1632  current->IsGlobalObject() ||
1633  !current->IsJSObject() ||
1634  JSObject::cast(current)->IsAccessCheckNeeded() ||
1635  !JSObject::cast(current)->HasFastProperties()) {
1636  return false;
1637  }
1638 
1639  LookupResult lookup(isolate);
1640  JSObject::cast(current)->map()->LookupInDescriptors(NULL, *name, &lookup);
1641  if (lookup.IsFound()) {
1642  if (lookup.type() != MAP_TRANSITION) return false;
1643  } else if (!lookup.IsCacheable()) {
1644  return false;
1645  }
1646 
1647  current = JSObject::cast(current)->GetPrototype();
1648  }
1649  return true;
1650 }
1651 
1652 
1654  HValue* object,
1655  SmallMapList* types,
1656  Handle<String> name,
1657  Zone* zone)
1658  : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
1659  name_(name),
1660  need_generic_(false) {
1661  SetOperandAt(0, context);
1662  SetOperandAt(1, object);
1664  SetGVNFlag(kDependsOnMaps);
1665  SmallMapList negative_lookups;
1666  for (int i = 0;
1667  i < types->length() && types_.length() < kMaxLoadPolymorphism;
1668  ++i) {
1669  Handle<Map> map = types->at(i);
1670  LookupResult lookup(map->GetIsolate());
1671  map->LookupInDescriptors(NULL, *name, &lookup);
1672  if (lookup.IsFound()) {
1673  switch (lookup.type()) {
1674  case FIELD: {
1675  int index = lookup.GetLocalFieldIndexFromMap(*map);
1676  if (index < 0) {
1677  SetGVNFlag(kDependsOnInobjectFields);
1678  } else {
1679  SetGVNFlag(kDependsOnBackingStoreFields);
1680  }
1681  types_.Add(types->at(i), zone);
1682  break;
1683  }
1684  case CONSTANT_FUNCTION:
1685  types_.Add(types->at(i), zone);
1686  break;
1687  case MAP_TRANSITION:
1688  if (PrototypeChainCanNeverResolve(map, name)) {
1689  negative_lookups.Add(types->at(i), zone);
1690  }
1691  break;
1692  default:
1693  break;
1694  }
1695  } else if (lookup.IsCacheable()) {
1696  if (PrototypeChainCanNeverResolve(map, name)) {
1697  negative_lookups.Add(types->at(i), zone);
1698  }
1699  }
1700  }
1701 
1702  bool need_generic =
1703  (types->length() != negative_lookups.length() + types_.length());
1704  if (!need_generic && FLAG_deoptimize_uncommon_cases) {
1705  SetFlag(kUseGVN);
1706  for (int i = 0; i < negative_lookups.length(); i++) {
1707  types_.Add(negative_lookups.at(i), zone);
1708  }
1709  } else {
1710  // We don't have an easy way to handle both a call (to the generic stub) and
1711  // a deopt in the same hydrogen instruction, so in this case we don't add
1712  // the negative lookups which can deopt - just let the generic stub handle
1713  // them.
1715  need_generic_ = true;
1716  }
1717 }
1718 
1719 
1722  if (types_.length() != other->types()->length()) return false;
1723  if (!name_.is_identical_to(other->name())) return false;
1724  if (need_generic_ != other->need_generic_) return false;
1725  for (int i = 0; i < types_.length(); i++) {
1726  bool found = false;
1727  for (int j = 0; j < types_.length(); j++) {
1728  if (types_.at(j).is_identical_to(other->types()->at(i))) {
1729  found = true;
1730  break;
1731  }
1732  }
1733  if (!found) return false;
1734  }
1735  return true;
1736 }
1737 
1738 
1740  object()->PrintNameTo(stream);
1741  stream->Add(".");
1742  stream->Add(*String::cast(*name())->ToCString());
1743 }
1744 
1745 
1747  object()->PrintNameTo(stream);
1748  stream->Add(".");
1749  stream->Add(*String::cast(*name())->ToCString());
1750 }
1751 
1752 
1754  object()->PrintNameTo(stream);
1755  stream->Add("[");
1756  key()->PrintNameTo(stream);
1757  stream->Add("]");
1758  if (RequiresHoleCheck()) {
1759  stream->Add(" check_hole");
1760  }
1761 }
1762 
1763 
1766  return false;
1767  }
1768 
1769  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1770  HValue* use = it.value();
1771  if (!use->IsChange()) return true;
1772  }
1773 
1774  return false;
1775 }
1776 
1777 
1779  elements()->PrintNameTo(stream);
1780  stream->Add("[");
1781  key()->PrintNameTo(stream);
1782  stream->Add("]");
1783 }
1784 
1785 
1787  object()->PrintNameTo(stream);
1788  stream->Add("[");
1789  key()->PrintNameTo(stream);
1790  stream->Add("]");
1791 }
1792 
1793 
1795  // Recognize generic keyed loads that use property name generated
1796  // by for-in statement as a key and rewrite them into fast property load
1797  // by index.
1798  if (key()->IsLoadKeyedFastElement()) {
1800  if (key_load->object()->IsForInCacheArray()) {
1801  HForInCacheArray* names_cache =
1802  HForInCacheArray::cast(key_load->object());
1803 
1804  if (names_cache->enumerable() == object()) {
1805  HForInCacheArray* index_cache =
1806  names_cache->index_cache();
1807  HCheckMapValue* map_check =
1808  new(block()->zone()) HCheckMapValue(object(), names_cache->map());
1809  HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
1810  index_cache,
1811  key_load->key());
1812  map_check->InsertBefore(this);
1813  index->InsertBefore(this);
1814  HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
1815  object(), index);
1816  load->InsertBefore(this);
1817  return load;
1818  }
1819  }
1820  }
1821 
1822  return this;
1823 }
1824 
1825 
1827  StringStream* stream) {
1828  external_pointer()->PrintNameTo(stream);
1829  stream->Add(".");
1830  switch (elements_kind()) {
1832  stream->Add("byte");
1833  break;
1835  stream->Add("u_byte");
1836  break;
1838  stream->Add("short");
1839  break;
1841  stream->Add("u_short");
1842  break;
1843  case EXTERNAL_INT_ELEMENTS:
1844  stream->Add("int");
1845  break;
1847  stream->Add("u_int");
1848  break;
1850  stream->Add("float");
1851  break;
1853  stream->Add("double");
1854  break;
1856  stream->Add("pixel");
1857  break;
1858  case FAST_ELEMENTS:
1859  case FAST_SMI_ELEMENTS:
1860  case FAST_DOUBLE_ELEMENTS:
1861  case FAST_HOLEY_ELEMENTS:
1864  case DICTIONARY_ELEMENTS:
1866  UNREACHABLE();
1867  break;
1868  }
1869  stream->Add("[");
1870  key()->PrintNameTo(stream);
1871  stream->Add("]");
1872 }
1873 
1874 
1876  object()->PrintNameTo(stream);
1877  stream->Add(".");
1878  ASSERT(name()->IsString());
1879  stream->Add(*String::cast(*name())->ToCString());
1880  stream->Add(" = ");
1881  value()->PrintNameTo(stream);
1882 }
1883 
1884 
1886  object()->PrintNameTo(stream);
1887  stream->Add(".");
1888  stream->Add(*String::cast(*name())->ToCString());
1889  stream->Add(" = ");
1890  value()->PrintNameTo(stream);
1891  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1892  if (NeedsWriteBarrier()) {
1893  stream->Add(" (write-barrier)");
1894  }
1895  if (!transition().is_null()) {
1896  stream->Add(" (transition map %p)", *transition());
1897  }
1898 }
1899 
1900 
1902  object()->PrintNameTo(stream);
1903  stream->Add("[");
1904  key()->PrintNameTo(stream);
1905  stream->Add("] = ");
1906  value()->PrintNameTo(stream);
1907 }
1908 
1909 
1911  elements()->PrintNameTo(stream);
1912  stream->Add("[");
1913  key()->PrintNameTo(stream);
1914  stream->Add("] = ");
1915  value()->PrintNameTo(stream);
1916 }
1917 
1918 
1920  object()->PrintNameTo(stream);
1921  stream->Add("[");
1922  key()->PrintNameTo(stream);
1923  stream->Add("] = ");
1924  value()->PrintNameTo(stream);
1925 }
1926 
1927 
1929  StringStream* stream) {
1930  external_pointer()->PrintNameTo(stream);
1931  stream->Add(".");
1932  switch (elements_kind()) {
1934  stream->Add("byte");
1935  break;
1937  stream->Add("u_byte");
1938  break;
1940  stream->Add("short");
1941  break;
1943  stream->Add("u_short");
1944  break;
1945  case EXTERNAL_INT_ELEMENTS:
1946  stream->Add("int");
1947  break;
1949  stream->Add("u_int");
1950  break;
1952  stream->Add("float");
1953  break;
1955  stream->Add("double");
1956  break;
1958  stream->Add("pixel");
1959  break;
1960  case FAST_SMI_ELEMENTS:
1961  case FAST_ELEMENTS:
1962  case FAST_DOUBLE_ELEMENTS:
1964  case FAST_HOLEY_ELEMENTS:
1966  case DICTIONARY_ELEMENTS:
1968  UNREACHABLE();
1969  break;
1970  }
1971  stream->Add("[");
1972  key()->PrintNameTo(stream);
1973  stream->Add("] = ");
1974  value()->PrintNameTo(stream);
1975 }
1976 
1977 
1979  object()->PrintNameTo(stream);
1980  ElementsKind from_kind = original_map()->elements_kind();
1981  ElementsKind to_kind = transitioned_map()->elements_kind();
1982  stream->Add(" %p [%s] -> %p [%s]",
1983  *original_map(),
1984  ElementsAccessor::ForKind(from_kind)->name(),
1985  *transitioned_map(),
1986  ElementsAccessor::ForKind(to_kind)->name());
1987 }
1988 
1989 
1991  stream->Add("[%p]", *cell());
1992  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
1993  if (details_.IsReadOnly()) stream->Add(" (read-only)");
1994 }
1995 
1996 
1998  if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
1999  for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2000  HValue* use = it.value();
2001  if (!use->IsChange()) return true;
2002  }
2003  return false;
2004 }
2005 
2006 
2008  stream->Add("%o ", *name());
2009 }
2010 
2011 
2013  stream->Add("[%p] = ", *cell());
2014  value()->PrintNameTo(stream);
2015  if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
2016  if (details_.IsReadOnly()) stream->Add(" (read-only)");
2017 }
2018 
2019 
2021  stream->Add("%o = ", *name());
2022  value()->PrintNameTo(stream);
2023 }
2024 
2025 
2027  value()->PrintNameTo(stream);
2028  stream->Add("[%d]", slot_index());
2029 }
2030 
2031 
2033  context()->PrintNameTo(stream);
2034  stream->Add("[%d] = ", slot_index());
2035  value()->PrintNameTo(stream);
2036 }
2037 
2038 
2039 // Implementation of type inference and type conversions. Calculates
2040 // the inferred type of this instruction based on the input operands.
2041 
2043  return type_;
2044 }
2045 
2046 
2048  return value()->type();
2049 }
2050 
2051 
2053  return value()->type();
2054 }
2055 
2056 
2058  // TODO(kasperl): Is there any way to signal that this isn't a smi?
2059  return HType::Tagged();
2060 }
2061 
2062 
2064  return HType::Smi();
2065 }
2066 
2067 
2069  HType result = HType::Uninitialized();
2070  for (int i = 0; i < OperandCount(); ++i) {
2071  HType current = OperandAt(i)->type();
2072  result = result.Combine(current);
2073  }
2074  return result;
2075 }
2076 
2077 
2079  return HType::TypeFromValue(handle_);
2080 }
2081 
2082 
2084  return HType::Boolean();
2085 }
2086 
2087 
2089  return HType::Boolean();
2090 }
2091 
2092 
2094  return HType::Boolean();
2095 }
2096 
2097 
2099  return HType::Boolean();
2100 }
2101 
2102 
2104  if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
2105  return type();
2106 }
2107 
2108 
2110  return HType::TaggedNumber();
2111 }
2112 
2113 
2115  return HType::TaggedNumber();
2116 }
2117 
2118 
2120  return HType::Tagged();
2121 }
2122 
2123 
2125  return HType::TaggedNumber();
2126 }
2127 
2128 
2130  return HType::TaggedNumber();
2131 }
2132 
2133 
2135  return HType::String();
2136 }
2137 
2138 
2140  return HType::JSObject();
2141 }
2142 
2143 
2145  // TODO(mstarzinger): Be smarter, could also be JSArray here.
2146  return HType::JSObject();
2147 }
2148 
2149 
2151  return HType::JSArray();
2152 }
2153 
2154 
2156  return HType::JSObject();
2157 }
2158 
2159 
2161  return HType::JSObject();
2162 }
2163 
2164 
2166  return HType::JSObject();
2167 }
2168 
2169 
2171  BitVector* visited) {
2172  visited->Add(id());
2173  if (representation().IsInteger32() &&
2174  !value()->representation().IsInteger32()) {
2175  if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2177  }
2178  }
2179  if (RequiredInputRepresentation(0).IsInteger32() &&
2180  representation().IsInteger32()) {
2181  return value();
2182  }
2183  return NULL;
2184 }
2185 
2186 
2187 
2189  visited->Add(id());
2190  if (from().IsInteger32()) return NULL;
2191  if (CanTruncateToInt32()) return NULL;
2192  if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2194  }
2195  ASSERT(!from().IsInteger32() || !to().IsInteger32());
2196  return NULL;
2197 }
2198 
2199 
2201  BitVector* visited) {
2202  visited->Add(id());
2203  return value();
2204 }
2205 
2206 
2208  visited->Add(id());
2209  if (range() == NULL || range()->CanBeMinusZero()) {
2211  return left();
2212  }
2213  return NULL;
2214 }
2215 
2216 
2218  visited->Add(id());
2219  if (range() == NULL || range()->CanBeMinusZero()) {
2221  }
2222  return NULL;
2223 }
2224 
2225 
2227  visited->Add(id());
2228  if (range() == NULL || range()->CanBeMinusZero()) {
2230  }
2231  return NULL;
2232 }
2233 
2234 
2236  visited->Add(id());
2237  // Propagate to the left argument. If the left argument cannot be -0, then
2238  // the result of the add operation cannot be either.
2239  if (range() == NULL || range()->CanBeMinusZero()) {
2240  return left();
2241  }
2242  return NULL;
2243 }
2244 
2245 
2247  visited->Add(id());
2248  // Propagate to the left argument. If the left argument cannot be -0, then
2249  // the result of the sub operation cannot be either.
2250  if (range() == NULL || range()->CanBeMinusZero()) {
2251  return left();
2252  }
2253  return NULL;
2254 }
2255 
2256 
2258  // If value was loaded from unboxed double backing store or
2259  // converted from an integer then we don't have to canonicalize it.
2260  if (value()->IsLoadKeyedFastDoubleElement() ||
2261  (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) {
2262  return false;
2263  }
2264  return true;
2265 }
2266 
2267 
2268 #define H_CONSTANT_INT32(val) \
2269 new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \
2270  Representation::Integer32())
2271 #define H_CONSTANT_DOUBLE(val) \
2272 new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \
2273  Representation::Double())
2274 
2275 #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \
2276 HInstruction* HInstr::New##HInstr(Zone* zone, \
2277  HValue* context, \
2278  HValue* left, \
2279  HValue* right) { \
2280  if (left->IsConstant() && right->IsConstant()) { \
2281  HConstant* c_left = HConstant::cast(left); \
2282  HConstant* c_right = HConstant::cast(right); \
2283  if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
2284  double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
2285  if (TypeInfo::IsInt32Double(double_res)) { \
2286  return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); \
2287  } \
2288  return H_CONSTANT_DOUBLE(double_res); \
2289  } \
2290  } \
2291  return new(zone) HInstr(context, left, right); \
2292 }
2293 
2294 
2298 
2299 #undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
2300 
2301 
2303  HValue* context,
2304  HValue* left,
2305  HValue* right) {
2306  if (left->IsConstant() && right->IsConstant()) {
2307  HConstant* c_left = HConstant::cast(left);
2308  HConstant* c_right = HConstant::cast(right);
2309  if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
2310  int32_t dividend = c_left->Integer32Value();
2311  int32_t divisor = c_right->Integer32Value();
2312  if (divisor != 0) {
2313  int32_t res = dividend % divisor;
2314  if ((res == 0) && (dividend < 0)) {
2315  return H_CONSTANT_DOUBLE(-0.0);
2316  }
2317  return H_CONSTANT_INT32(res);
2318  }
2319  }
2320  }
2321  return new(zone) HMod(context, left, right);
2322 }
2323 
2324 
2326  HValue* context,
2327  HValue* left,
2328  HValue* right) {
2329  // If left and right are constant values, try to return a constant value.
2330  if (left->IsConstant() && right->IsConstant()) {
2331  HConstant* c_left = HConstant::cast(left);
2332  HConstant* c_right = HConstant::cast(right);
2333  if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2334  if (c_right->DoubleValue() != 0) {
2335  double double_res = c_left->DoubleValue() / c_right->DoubleValue();
2336  if (TypeInfo::IsInt32Double(double_res)) {
2337  return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
2338  }
2339  return H_CONSTANT_DOUBLE(double_res);
2340  }
2341  }
2342  }
2343  return new(zone) HDiv(context, left, right);
2344 }
2345 
2346 
2348  Token::Value op,
2349  HValue* context,
2350  HValue* left,
2351  HValue* right) {
2352  if (left->IsConstant() && right->IsConstant()) {
2353  HConstant* c_left = HConstant::cast(left);
2354  HConstant* c_right = HConstant::cast(right);
2355  if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2356  int32_t result;
2357  int32_t v_left = c_left->NumberValueAsInteger32();
2358  int32_t v_right = c_right->NumberValueAsInteger32();
2359  switch (op) {
2360  case Token::BIT_XOR:
2361  result = v_left ^ v_right;
2362  break;
2363  case Token::BIT_AND:
2364  result = v_left & v_right;
2365  break;
2366  case Token::BIT_OR:
2367  result = v_left | v_right;
2368  break;
2369  default:
2370  result = 0; // Please the compiler.
2371  UNREACHABLE();
2372  }
2373  return H_CONSTANT_INT32(result);
2374  }
2375  }
2376  return new(zone) HBitwise(op, context, left, right);
2377 }
2378 
2379 
2380 #define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \
2381 HInstruction* HInstr::New##HInstr(Zone* zone, \
2382  HValue* context, \
2383  HValue* left, \
2384  HValue* right) { \
2385  if (left->IsConstant() && right->IsConstant()) { \
2386  HConstant* c_left = HConstant::cast(left); \
2387  HConstant* c_right = HConstant::cast(right); \
2388  if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
2389  return H_CONSTANT_INT32(result); \
2390  } \
2391  } \
2392  return new(zone) HInstr(context, left, right); \
2393 }
2394 
2395 
2397 c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
2399 c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
2400 
2401 #undef DEFINE_NEW_H_BITWISE_INSTR
2402 
2403 
2405  HValue* context,
2406  HValue* left,
2407  HValue* right) {
2408  if (left->IsConstant() && right->IsConstant()) {
2409  HConstant* c_left = HConstant::cast(left);
2410  HConstant* c_right = HConstant::cast(right);
2411  if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2412  int32_t left_val = c_left->NumberValueAsInteger32();
2413  int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
2414  if ((right_val == 0) && (left_val < 0)) {
2415  return H_CONSTANT_DOUBLE(
2416  static_cast<double>(static_cast<uint32_t>(left_val)));
2417  }
2418  return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
2419  }
2420  }
2421  return new(zone) HShr(context, left, right);
2422 }
2423 
2424 
2425 #undef H_CONSTANT_INT32
2426 #undef H_CONSTANT_DOUBLE
2427 
2428 
2430  key()->PrintNameTo(stream);
2431  stream->Add(" ");
2432  object()->PrintNameTo(stream);
2433 }
2434 
2435 
2437  stream->Add(Token::Name(op_));
2438  stream->Add(" ");
2440 }
2441 
2442 
2444  bool double_occurred = false;
2445  bool int32_occurred = false;
2446  for (int i = 0; i < OperandCount(); ++i) {
2447  HValue* value = OperandAt(i);
2448  if (value->IsUnknownOSRValue()) {
2449  HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
2450  if (hint_value != NULL) {
2451  Representation hint = hint_value->representation();
2452  if (hint.IsDouble()) double_occurred = true;
2453  if (hint.IsInteger32()) int32_occurred = true;
2454  }
2455  continue;
2456  }
2457  if (value->representation().IsDouble()) double_occurred = true;
2458  if (value->representation().IsInteger32()) int32_occurred = true;
2459  if (value->representation().IsTagged()) {
2460  if (value->IsConstant()) {
2461  HConstant* constant = HConstant::cast(value);
2462  if (constant->IsConvertibleToInteger()) {
2463  int32_occurred = true;
2464  } else if (constant->HasNumberValue()) {
2465  double_occurred = true;
2466  } else {
2467  return Representation::Tagged();
2468  }
2469  } else {
2470  return Representation::Tagged();
2471  }
2472  }
2473  }
2474 
2475  if (double_occurred) return Representation::Double();
2476 
2477  if (int32_occurred) return Representation::Integer32();
2478 
2479  return Representation::None();
2480 }
2481 
2482 
2483 // Node-specific verification code is only included in debug mode.
2484 #ifdef DEBUG
2485 
2486 void HPhi::Verify() {
2487  ASSERT(OperandCount() == block()->predecessors()->length());
2488  for (int i = 0; i < OperandCount(); ++i) {
2489  HValue* value = OperandAt(i);
2490  HBasicBlock* defining_block = value->block();
2491  HBasicBlock* predecessor_block = block()->predecessors()->at(i);
2492  ASSERT(defining_block == predecessor_block ||
2493  defining_block->Dominates(predecessor_block));
2494  }
2495 }
2496 
2497 
2498 void HSimulate::Verify() {
2499  HInstruction::Verify();
2500  ASSERT(HasAstId());
2501 }
2502 
2503 
2504 void HCheckSmi::Verify() {
2505  HInstruction::Verify();
2506  ASSERT(HasNoUses());
2507 }
2508 
2509 
2510 void HCheckNonSmi::Verify() {
2511  HInstruction::Verify();
2512  ASSERT(HasNoUses());
2513 }
2514 
2515 
2516 void HCheckFunction::Verify() {
2517  HInstruction::Verify();
2518  ASSERT(HasNoUses());
2519 }
2520 
2521 
2522 void HCheckPrototypeMaps::Verify() {
2523  HInstruction::Verify();
2524  ASSERT(HasNoUses());
2525 }
2526 
2527 #endif
2528 
2529 } } // namespace v8::internal
virtual void PrintDataTo(StringStream *stream)
bool HasObservableSideEffects() const
void set_can_be_minus_zero(bool b)
const int kMinInt
Definition: globals.h:225
virtual bool IsConvertibleToInteger() const
Handle< String > name() const
bool IsFinished() const
Definition: hydrogen.h:101
virtual void PrintDataTo(StringStream *stream)
Handle< Map > at(int i) const
Definition: ast.h:282
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
static bool IsInt32Double(double value)
Definition: type-info.h:106
HType Combine(HType other)
const char * ToCString(const v8::String::Utf8Value &value)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void PrintF(const char *format,...)
Definition: v8utils.cc:40
HDiv(HValue *context, HValue *left, HValue *right)
Handle< Object > handle() const
virtual bool DataEquals(HValue *other)
static String * cast(Object *obj)
bool Equals(const HType &other)
virtual void PrintDataTo(StringStream *stream)
HConstant * CopyToRepresentation(Representation r, Zone *zone) const
virtual void PrintDataTo(StringStream *stream)
HUseListNode * RemoveUse(HValue *value, int index)
#define PRINT_DO(type)
HInstruction * previous() const
static const char * Name(Value tok)
Definition: token.h:196
HLoadNamedFieldPolymorphic(HValue *context, HValue *object, SmallMapList *types, Handle< String > name, Zone *zone)
virtual void PrintDataTo(StringStream *stream)
int current_
bool Dominates(HBasicBlock *other) const
Definition: hydrogen.cc:223
virtual void PrintDataTo(StringStream *stream)
void Intersect(Range *other)
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
virtual HType CalculateInferredType()
HBitwise(Token::Value op, HValue *context, HValue *left, HValue *right)
HBasicBlock * block() const
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
static Representation Integer32()
Handle< JSGlobalPropertyCell > cell() const
T Max(T a, T b)
Definition: utils.h:222
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
bool is_identical_to(const Handle< T > other) const
Definition: handles.h:67
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< String > name() const
virtual void PrintDataTo(StringStream *stream)
HInstruction * first() const
Definition: hydrogen.h:65
HGraph * graph() const
Definition: hydrogen.h:63
int int32_t
Definition: unicode.cc:47
Token::Value op() const
void AssumeRepresentation(Representation r)
const int kMaxInt
Definition: globals.h:224
virtual void PrintDataTo(StringStream *stream)
void AddConstant(int32_t value)
#define ASSERT(condition)
Definition: checks.h:270
virtual Range * InferRange(Zone *zone)
static HInstruction * NewHMod(Zone *zone, HValue *context, HValue *left, HValue *right)
const ZoneList< HBasicBlock * > * predecessors() const
Definition: hydrogen.h:71
bool IsEmpty() const
Definition: utils.h:958
virtual void PrintDataTo(StringStream *stream)
HControlInstruction * end() const
Definition: hydrogen.h:69
virtual Representation InferredRepresentation()
static Representation Double()
bool Equals(const Representation &other)
virtual void PrintDataTo(StringStream *stream)
int isnan(double x)
virtual void PrintDataTo(StringStream *stream)
Representation representation() const
virtual void PrintDataTo(StringStream *stream)
DEFINE_NEW_H_BITWISE_INSTR(HSar, c_left->NumberValueAsInteger32() >>(c_right->NumberValueAsInteger32()&0x1f)) DEFINE_NEW_H_BITWISE_INSTR(HShl
virtual void PrintDataTo(StringStream *stream)
void set_representation(Representation r)
virtual void PrintDataTo(StringStream *stream)
virtual int argument_count() const
virtual Range * InferRange(Zone *zone)
virtual void PrintDataTo(StringStream *stream)
void Add(Vector< const char > format, Vector< FmtElm > elms)
virtual void PrintDataTo(StringStream *stream)
Handle< JSFunction > target() const
virtual HType CalculateInferredType()
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
Handle< JSFunction > target() const
#define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V)
virtual HType CalculateInferredType()
void AddNewRange(Range *r, Zone *zone)
void RemovePhi(HPhi *phi)
Definition: hydrogen.cc:96
virtual int OperandCount()=0
#define UNREACHABLE()
Definition: checks.h:50
bool Equals(HValue *other)
void PrintRangeTo(StringStream *stream)
const uint32_t kIsSymbolMask
Definition: objects.h:443
virtual HType CalculateInferredType()
virtual void PrintDataTo(StringStream *stream)
static GVNFlagSet AllSideEffectsFlagSet()
HMod(HValue *context, HValue *left, HValue *right)
bool IsFastPackedElementsKind(ElementsKind kind)
void PrintChangesTo(StringStream *stream)
#define DEFINE_COMPILE(type)
static HUnaryOperation * cast(HValue *value)
virtual void PrintDataTo(StringStream *stream)
virtual Range * InferRange(Zone *zone)
virtual void PrintDataTo(StringStream *stream)
virtual Range * InferRange(Zone *zone)
Handle< String > name() const
Range * Copy(Zone *zone) const
int length() const
Definition: ast.h:276
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
bool IsDefinedAfter(HBasicBlock *other) const
int GetAssignedIndexAt(int index) const
virtual void PrintDataTo(StringStream *stream)
void ComputeInitialRange(Zone *zone)
#define GVN_TRACKED_FLAG_LIST(V)
virtual HValue * OperandAt(int index)
virtual void PrintDataTo(StringStream *stream)
void AddInput(HValue *value)
virtual Range * InferRange(Zone *zone)
GVNFlagSet ChangesFlags() const
virtual HValue * Canonicalize()
virtual Range * InferRange(Zone *zone)
void LookupInDescriptors(JSObject *holder, String *name, LookupResult *result)
Definition: objects.cc:2180
virtual Range * InferRange(Zone *zone)
HInstruction * next() const
virtual bool IsConvertibleToInteger() const
virtual HValue * Canonicalize()
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
void set_type(HType new_type)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
static HInstruction * NewHShr(Zone *zone, HValue *context, HValue *left, HValue *right)
#define MAKE_CASE(type)
static HInstruction * NewHBitwise(Zone *zone, Token::Value op, HValue *context, HValue *left, HValue *right)
const uint32_t kStringTag
Definition: objects.h:437
virtual void PrintDataTo(StringStream *stream)
HInstruction * last() const
Definition: hydrogen.h:66
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintTo(StringStream *stream)
virtual HValue * Canonicalize()
void AddNonPhiUsesFrom(HPhi *other)
void DeleteAndReplaceWith(HValue *other)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
static HInstruction * NewHDiv(Zone *zone, HValue *context, HValue *left, HValue *right)
virtual void PrintDataTo(StringStream *stream)
#define GVN_UNTRACKED_FLAG_LIST(V)
virtual void PrintDataTo(StringStream *stream)
void set_last(HInstruction *instr)
Definition: hydrogen.h:67
virtual intptr_t Hashcode()
bool SubAndCheckOverflow(Range *other)
virtual void PrintDataTo(StringStream *stream)
static ElementsAccessor * ForKind(ElementsKind elements_kind)
Definition: elements.h:134
virtual HValue * OperandAt(int index)=0
virtual Representation ObservedInputRepresentation(int index)
void PrintNameTo(StringStream *stream)
HConstant(Handle< Object > handle, Representation r)
void InsertAfter(HInstruction *previous)
virtual Opcode opcode() const =0
virtual void DeleteFromGraph()=0
virtual void PrintTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
const uint32_t kIsNotStringMask
Definition: objects.h:436
virtual void PrintDataTo(StringStream *stream)
void ChangeRepresentation(Representation r)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
HShr(HValue *context, HValue *left, HValue *right)
virtual HType CalculateInferredType()
void SetOperandAt(int index, HValue *value)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
virtual Range * InferRange(Zone *zone)
bool CheckFlag(Flag f) const
virtual void PrintDataTo(StringStream *stream)
virtual HValue * Canonicalize()
#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op)
int32_t NumberValueAsInteger32() const
void InsertBefore(HInstruction *next)
static HType TypeFromValue(Handle< Object > value)
virtual Range * InferRange(Zone *zone)
#define H_CONSTANT_DOUBLE(val)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
bool IsStartBlock() const
Definition: hydrogen.h:98
virtual void PrintDataTo(StringStream *stream)
#define HEAP
Definition: isolate.h:1408
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void SetBlock(HBasicBlock *block)
int32_t NumberToInt32(Object *number)
Definition: v8conversions.h:37
void Sar(int32_t value)
virtual void PrintDataTo(StringStream *stream)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
virtual void PrintDataTo(StringStream *stream)
virtual void PrintDataTo(StringStream *stream)
#define FACTORY
Definition: isolate.h:1409
virtual Range * InferRange(Zone *zone)
int GetNextValueID(HValue *value)
Definition: hydrogen.h:306
void Shl(int32_t value)
virtual void PrintDataTo(StringStream *stream)
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
HConstant * CopyToTruncatedInt32(Zone *zone) const
virtual void PrintDataTo(StringStream *stream)
const char * Mnemonic() const
void AddIndirectUsesTo(int *use_count)
virtual void PrintDataTo(StringStream *stream)
const char * name_
Definition: flags.cc:1352
virtual Range * InferRange(Zone *zone)
virtual void InternalSetOperandAt(int index, HValue *value)=0
virtual void PrintDataTo(StringStream *stream)
int block_id() const
Definition: hydrogen.h:61
const uint32_t kSymbolTag
Definition: objects.h:445
virtual void PrintDataTo(StringStream *stream)
void set_tail(HUseListNode *list)
virtual Range * InferRange(Zone *zone)
static Representation Tagged()
void GetCheckMaskAndTag(uint8_t *mask, uint8_t *tag)
void PrintTypeTo(StringStream *stream)
Handle< JSGlobalPropertyCell > cell() const
void StackUpon(Range *other)
virtual void PrintDataTo(StringStream *stream)
void Add(Handle< Map > handle, Zone *zone)
Definition: ast.h:278
T Min(T a, T b)
Definition: utils.h:229
Zone * zone() const
Definition: hydrogen.h:399
#define H_CONSTANT_INT32(val)
void RegisterUse(int index, HValue *new_value)
bool HasAssignedIndexAt(int index) const
virtual Representation RequiredInputRepresentation(int index)
void Union(Range *other)
void GetCheckInterval(InstanceType *first, InstanceType *last)
virtual void PrintDataTo(StringStream *stream)
static HValue * cast(HValue *value)
void ReplaceAllUsesWith(HValue *other)
#define ARRAY_SIZE(a)
Definition: globals.h:295
bool AddAndCheckOverflow(Range *other)
virtual void PrintDataTo(StringStream *stream)
static JSObject * cast(Object *obj)
c_left NumberValueAsInteger32()<< (c_right-> NumberValueAsInteger32()&0x1f)) HInstruction *HShr::NewHShr(Zone *zone, HValue *context, HValue *left, HValue *right)
virtual HValue * Canonicalize()
virtual HValue * EnsureAndPropagateNotMinusZero(BitVector *visited)
bool MulAndCheckOverflow(Range *other)
static bool IsOrderedRelationalCompareOp(Value op)
Definition: token.h:218
virtual HValue * OperandAt(int index)
HUseIterator uses() const
virtual Range * InferRange(Zone *zone)
virtual void PrintDataTo(StringStream *stream)
virtual HValue * Canonicalize()