v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
lithium-arm.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 "lithium-allocator-inl.h"
31 #include "arm/lithium-arm.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 #define DEFINE_COMPILE(type) \
38  void L##type::CompileToNative(LCodeGen* generator) { \
39  generator->Do##type(this); \
40  }
42 #undef DEFINE_COMPILE
43 
45  for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
46  register_spills_[i] = NULL;
47  }
48  for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
49  double_register_spills_[i] = NULL;
50  }
51 }
52 
53 
54 void LOsrEntry::MarkSpilledRegister(int allocation_index,
55  LOperand* spill_operand) {
56  ASSERT(spill_operand->IsStackSlot());
57  ASSERT(register_spills_[allocation_index] == NULL);
58  register_spills_[allocation_index] = spill_operand;
59 }
60 
61 
62 #ifdef DEBUG
63 void LInstruction::VerifyCall() {
64  // Call instructions can use only fixed registers as temporaries and
65  // outputs because all registers are blocked by the calling convention.
66  // Inputs operands must use a fixed register or use-at-start policy or
67  // a non-register policy.
68  ASSERT(Output() == NULL ||
69  LUnallocated::cast(Output())->HasFixedPolicy() ||
70  !LUnallocated::cast(Output())->HasRegisterPolicy());
71  for (UseIterator it(this); !it.Done(); it.Advance()) {
72  LUnallocated* operand = LUnallocated::cast(it.Current());
73  ASSERT(operand->HasFixedPolicy() ||
74  operand->IsUsedAtStart());
75  }
76  for (TempIterator it(this); !it.Done(); it.Advance()) {
77  LUnallocated* operand = LUnallocated::cast(it.Current());
78  ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
79  }
80 }
81 #endif
82 
83 
84 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
85  LOperand* spill_operand) {
86  ASSERT(spill_operand->IsDoubleStackSlot());
87  ASSERT(double_register_spills_[allocation_index] == NULL);
88  double_register_spills_[allocation_index] = spill_operand;
89 }
90 
91 
93  stream->Add("%s ", this->Mnemonic());
94 
95  PrintOutputOperandTo(stream);
96 
97  PrintDataTo(stream);
98 
99  if (HasEnvironment()) {
100  stream->Add(" ");
101  environment()->PrintTo(stream);
102  }
103 
104  if (HasPointerMap()) {
105  stream->Add(" ");
106  pointer_map()->PrintTo(stream);
107  }
108 }
109 
110 
112  stream->Add("= ");
113  for (int i = 0; i < InputCount(); i++) {
114  if (i > 0) stream->Add(" ");
115  InputAt(i)->PrintTo(stream);
116  }
117 }
118 
119 
121  if (HasResult()) result()->PrintTo(stream);
122 }
123 
124 
126  LGap::PrintDataTo(stream);
127  LLabel* rep = replacement();
128  if (rep != NULL) {
129  stream->Add(" Dead block replaced with B%d", rep->block_id());
130  }
131 }
132 
133 
134 bool LGap::IsRedundant() const {
135  for (int i = 0; i < 4; i++) {
136  if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
137  return false;
138  }
139  }
140 
141  return true;
142 }
143 
144 
146  for (int i = 0; i < 4; i++) {
147  stream->Add("(");
148  if (parallel_moves_[i] != NULL) {
149  parallel_moves_[i]->PrintDataTo(stream);
150  }
151  stream->Add(") ");
152  }
153 }
154 
155 
156 const char* LArithmeticD::Mnemonic() const {
157  switch (op()) {
158  case Token::ADD: return "add-d";
159  case Token::SUB: return "sub-d";
160  case Token::MUL: return "mul-d";
161  case Token::DIV: return "div-d";
162  case Token::MOD: return "mod-d";
163  default:
164  UNREACHABLE();
165  return NULL;
166  }
167 }
168 
169 
170 const char* LArithmeticT::Mnemonic() const {
171  switch (op()) {
172  case Token::ADD: return "add-t";
173  case Token::SUB: return "sub-t";
174  case Token::MUL: return "mul-t";
175  case Token::MOD: return "mod-t";
176  case Token::DIV: return "div-t";
177  case Token::BIT_AND: return "bit-and-t";
178  case Token::BIT_OR: return "bit-or-t";
179  case Token::BIT_XOR: return "bit-xor-t";
180  case Token::SHL: return "shl-t";
181  case Token::SAR: return "sar-t";
182  case Token::SHR: return "shr-t";
183  default:
184  UNREACHABLE();
185  return NULL;
186  }
187 }
188 
189 
191  stream->Add("B%d", block_id());
192 }
193 
194 
196  stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
197  value()->PrintTo(stream);
198 }
199 
200 
202  stream->Add("if ");
203  left()->PrintTo(stream);
204  stream->Add(" %s ", Token::String(op()));
205  right()->PrintTo(stream);
206  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
207 }
208 
209 
211  stream->Add("if ");
212  value()->PrintTo(stream);
213  stream->Add(kind() == kStrictEquality ? " === " : " == ");
214  stream->Add(nil() == kNullValue ? "null" : "undefined");
215  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
216 }
217 
218 
220  stream->Add("if is_object(");
221  value()->PrintTo(stream);
222  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
223 }
224 
225 
227  stream->Add("if is_string(");
228  value()->PrintTo(stream);
229  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
230 }
231 
232 
234  stream->Add("if is_smi(");
235  value()->PrintTo(stream);
236  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
237 }
238 
239 
241  stream->Add("if is_undetectable(");
242  value()->PrintTo(stream);
243  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
244 }
245 
246 
248  stream->Add("if string_compare(");
249  left()->PrintTo(stream);
250  right()->PrintTo(stream);
251  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
252 }
253 
254 
256  stream->Add("if has_instance_type(");
257  value()->PrintTo(stream);
258  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
259 }
260 
261 
262 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
263  stream->Add("if has_cached_array_index(");
264  value()->PrintTo(stream);
265  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
266 }
267 
268 
269 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
270  stream->Add("if class_of_test(");
271  value()->PrintTo(stream);
272  stream->Add(", \"%o\") then B%d else B%d",
273  *hydrogen()->class_name(),
274  true_block_id(),
275  false_block_id());
276 }
277 
278 
280  stream->Add("if typeof ");
281  value()->PrintTo(stream);
282  stream->Add(" == \"%s\" then B%d else B%d",
283  *hydrogen()->type_literal()->ToCString(),
285 }
286 
287 
289  stream->Add("#%d / ", arity());
290 }
291 
292 
294  stream->Add("/%s ", hydrogen()->OpName());
295  value()->PrintTo(stream);
296 }
297 
298 
300  context()->PrintTo(stream);
301  stream->Add("[%d]", slot_index());
302 }
303 
304 
306  context()->PrintTo(stream);
307  stream->Add("[%d] <- ", slot_index());
308  value()->PrintTo(stream);
309 }
310 
311 
313  stream->Add("= ");
314  function()->PrintTo(stream);
315  stream->Add(" #%d / ", arity());
316 }
317 
318 
320  stream->Add("[r2] #%d / ", arity());
321 }
322 
323 
325  SmartArrayPointer<char> name_string = name()->ToCString();
326  stream->Add("%s #%d / ", *name_string, arity());
327 }
328 
329 
331  SmartArrayPointer<char> name_string = name()->ToCString();
332  stream->Add("%s #%d / ", *name_string, arity());
333 }
334 
335 
337  stream->Add("#%d / ", arity());
338 }
339 
340 
342  stream->Add("= ");
343  constructor()->PrintTo(stream);
344  stream->Add(" #%d / ", arity());
345 }
346 
347 
349  arguments()->PrintTo(stream);
350  stream->Add(" length ");
351  length()->PrintTo(stream);
352  stream->Add(" index ");
353  index()->PrintTo(stream);
354 }
355 
356 
358  object()->PrintTo(stream);
359  stream->Add(".");
360  stream->Add(*String::cast(*name())->ToCString());
361  stream->Add(" <- ");
362  value()->PrintTo(stream);
363 }
364 
365 
367  object()->PrintTo(stream);
368  stream->Add(".");
369  stream->Add(*String::cast(*name())->ToCString());
370  stream->Add(" <- ");
371  value()->PrintTo(stream);
372 }
373 
374 
376  object()->PrintTo(stream);
377  stream->Add("[");
378  key()->PrintTo(stream);
379  stream->Add("] <- ");
380  value()->PrintTo(stream);
381 }
382 
383 
384 void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
385  elements()->PrintTo(stream);
386  stream->Add("[");
387  key()->PrintTo(stream);
388  stream->Add("] <- ");
389  value()->PrintTo(stream);
390 }
391 
392 
394  object()->PrintTo(stream);
395  stream->Add("[");
396  key()->PrintTo(stream);
397  stream->Add("] <- ");
398  value()->PrintTo(stream);
399 }
400 
401 
403  object()->PrintTo(stream);
404  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
405 }
406 
407 
409  // Skip a slot if for a double-width slot.
410  if (is_double) spill_slot_count_++;
411  return spill_slot_count_++;
412 }
413 
414 
416  int index = GetNextSpillIndex(is_double);
417  if (is_double) {
418  return LDoubleStackSlot::Create(index, zone());
419  } else {
420  return LStackSlot::Create(index, zone());
421  }
422 }
423 
424 
425 LPlatformChunk* LChunkBuilder::Build() {
426  ASSERT(is_unused());
427  chunk_ = new(zone()) LPlatformChunk(info(), graph());
428  HPhase phase("L_Building chunk", chunk_);
429  status_ = BUILDING;
430  const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
431  for (int i = 0; i < blocks->length(); i++) {
432  HBasicBlock* next = NULL;
433  if (i < blocks->length() - 1) next = blocks->at(i + 1);
434  DoBasicBlock(blocks->at(i), next);
435  if (is_aborted()) return NULL;
436  }
437  status_ = DONE;
438  return chunk_;
439 }
440 
441 
442 void LChunkBuilder::Abort(const char* reason) {
443  info()->set_bailout_reason(reason);
444  status_ = ABORTED;
445 }
446 
447 
448 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
449  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
451 }
452 
453 
454 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
455  return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
457 }
458 
459 
460 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
461  return Use(value, ToUnallocated(fixed_register));
462 }
463 
464 
465 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
466  return Use(value, ToUnallocated(reg));
467 }
468 
469 
470 LOperand* LChunkBuilder::UseRegister(HValue* value) {
471  return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
472 }
473 
474 
475 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
476  return Use(value,
477  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
479 }
480 
481 
482 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
483  return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
484 }
485 
486 
487 LOperand* LChunkBuilder::Use(HValue* value) {
488  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
489 }
490 
491 
492 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
493  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
495 }
496 
497 
498 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
499  return value->IsConstant()
500  ? chunk_->DefineConstantOperand(HConstant::cast(value))
501  : Use(value);
502 }
503 
504 
505 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
506  return value->IsConstant()
507  ? chunk_->DefineConstantOperand(HConstant::cast(value))
508  : UseAtStart(value);
509 }
510 
511 
512 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
513  return value->IsConstant()
514  ? chunk_->DefineConstantOperand(HConstant::cast(value))
515  : UseRegister(value);
516 }
517 
518 
519 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
520  return value->IsConstant()
521  ? chunk_->DefineConstantOperand(HConstant::cast(value))
522  : UseRegisterAtStart(value);
523 }
524 
525 
526 LOperand* LChunkBuilder::UseAny(HValue* value) {
527  return value->IsConstant()
528  ? chunk_->DefineConstantOperand(HConstant::cast(value))
529  : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
530 }
531 
532 
533 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
534  if (value->EmitAtUses()) {
535  HInstruction* instr = HInstruction::cast(value);
536  VisitInstruction(instr);
537  }
538  operand->set_virtual_register(value->id());
539  return operand;
540 }
541 
542 
543 template<int I, int T>
544 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
545  LUnallocated* result) {
546  result->set_virtual_register(current_instruction_->id());
547  instr->set_result(result);
548  return instr;
549 }
550 
551 
552 template<int I, int T>
553 LInstruction* LChunkBuilder::DefineAsRegister(
554  LTemplateInstruction<1, I, T>* instr) {
555  return Define(instr,
556  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
557 }
558 
559 
560 template<int I, int T>
561 LInstruction* LChunkBuilder::DefineAsSpilled(
562  LTemplateInstruction<1, I, T>* instr, int index) {
563  return Define(instr,
564  new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
565 }
566 
567 
568 template<int I, int T>
569 LInstruction* LChunkBuilder::DefineSameAsFirst(
570  LTemplateInstruction<1, I, T>* instr) {
571  return Define(instr,
572  new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
573 }
574 
575 
576 template<int I, int T>
577 LInstruction* LChunkBuilder::DefineFixed(
578  LTemplateInstruction<1, I, T>* instr, Register reg) {
579  return Define(instr, ToUnallocated(reg));
580 }
581 
582 
583 template<int I, int T>
584 LInstruction* LChunkBuilder::DefineFixedDouble(
585  LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
586  return Define(instr, ToUnallocated(reg));
587 }
588 
589 
590 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
591  HEnvironment* hydrogen_env = current_block_->last_environment();
592  int argument_index_accumulator = 0;
593  instr->set_environment(CreateEnvironment(hydrogen_env,
594  &argument_index_accumulator));
595  return instr;
596 }
597 
598 
599 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
600  HInstruction* hinstr,
601  CanDeoptimize can_deoptimize) {
602 #ifdef DEBUG
603  instr->VerifyCall();
604 #endif
605  instr->MarkAsCall();
606  instr = AssignPointerMap(instr);
607 
608  if (hinstr->HasObservableSideEffects()) {
609  ASSERT(hinstr->next()->IsSimulate());
610  HSimulate* sim = HSimulate::cast(hinstr->next());
611  ASSERT(instruction_pending_deoptimization_environment_ == NULL);
612  ASSERT(pending_deoptimization_ast_id_.IsNone());
613  instruction_pending_deoptimization_environment_ = instr;
614  pending_deoptimization_ast_id_ = sim->ast_id();
615  }
616 
617  // If instruction does not have side-effects lazy deoptimization
618  // after the call will try to deoptimize to the point before the call.
619  // Thus we still need to attach environment to this call even if
620  // call sequence can not deoptimize eagerly.
621  bool needs_environment =
622  (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
623  !hinstr->HasObservableSideEffects();
624  if (needs_environment && !instr->HasEnvironment()) {
625  instr = AssignEnvironment(instr);
626  }
627 
628  return instr;
629 }
630 
631 
632 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
633  ASSERT(!instr->HasPointerMap());
634  instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
635  return instr;
636 }
637 
638 
639 LUnallocated* LChunkBuilder::TempRegister() {
640  LUnallocated* operand =
641  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
642  operand->set_virtual_register(allocator_->GetVirtualRegister());
643  if (!allocator_->AllocationOk()) Abort("Not enough virtual registers.");
644  return operand;
645 }
646 
647 
648 LOperand* LChunkBuilder::FixedTemp(Register reg) {
649  LUnallocated* operand = ToUnallocated(reg);
650  ASSERT(operand->HasFixedPolicy());
651  return operand;
652 }
653 
654 
655 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
656  LUnallocated* operand = ToUnallocated(reg);
657  ASSERT(operand->HasFixedPolicy());
658  return operand;
659 }
660 
661 
662 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
663  return new(zone()) LLabel(instr->block());
664 }
665 
666 
667 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
668  return AssignEnvironment(new(zone()) LDeoptimize);
669 }
670 
671 
672 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
673  return AssignEnvironment(new(zone()) LDeoptimize);
674 }
675 
676 
677 LInstruction* LChunkBuilder::DoShift(Token::Value op,
678  HBitwiseBinaryOperation* instr) {
679  if (instr->representation().IsTagged()) {
680  ASSERT(instr->left()->representation().IsTagged());
681  ASSERT(instr->right()->representation().IsTagged());
682 
683  LOperand* left = UseFixed(instr->left(), r1);
684  LOperand* right = UseFixed(instr->right(), r0);
685  LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
686  return MarkAsCall(DefineFixed(result, r0), instr);
687  }
688 
689  ASSERT(instr->representation().IsInteger32());
690  ASSERT(instr->left()->representation().IsInteger32());
691  ASSERT(instr->right()->representation().IsInteger32());
692  LOperand* left = UseRegisterAtStart(instr->left());
693 
694  HValue* right_value = instr->right();
695  LOperand* right = NULL;
696  int constant_value = 0;
697  if (right_value->IsConstant()) {
698  HConstant* constant = HConstant::cast(right_value);
699  right = chunk_->DefineConstantOperand(constant);
700  constant_value = constant->Integer32Value() & 0x1f;
701  } else {
702  right = UseRegisterAtStart(right_value);
703  }
704 
705  // Shift operations can only deoptimize if we do a logical shift
706  // by 0 and the result cannot be truncated to int32.
707  bool does_deopt = false;
708  if (op == Token::SHR && constant_value == 0) {
709  if (FLAG_opt_safe_uint32_operations) {
710  does_deopt = !instr->CheckFlag(HInstruction::kUint32);
711  } else {
712  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
713  if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
714  does_deopt = true;
715  break;
716  }
717  }
718  }
719  }
720 
721  LInstruction* result =
722  DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
723  return does_deopt ? AssignEnvironment(result) : result;
724 }
725 
726 
727 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
728  HArithmeticBinaryOperation* instr) {
729  ASSERT(instr->representation().IsDouble());
730  ASSERT(instr->left()->representation().IsDouble());
731  ASSERT(instr->right()->representation().IsDouble());
732  ASSERT(op != Token::MOD);
733  LOperand* left = UseRegisterAtStart(instr->left());
734  LOperand* right = UseRegisterAtStart(instr->right());
735  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
736  return DefineAsRegister(result);
737 }
738 
739 
740 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
741  HArithmeticBinaryOperation* instr) {
742  ASSERT(op == Token::ADD ||
743  op == Token::DIV ||
744  op == Token::MOD ||
745  op == Token::MUL ||
746  op == Token::SUB);
747  HValue* left = instr->left();
748  HValue* right = instr->right();
749  ASSERT(left->representation().IsTagged());
750  ASSERT(right->representation().IsTagged());
751  LOperand* left_operand = UseFixed(left, r1);
752  LOperand* right_operand = UseFixed(right, r0);
753  LArithmeticT* result =
754  new(zone()) LArithmeticT(op, left_operand, right_operand);
755  return MarkAsCall(DefineFixed(result, r0), instr);
756 }
757 
758 
759 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
760  ASSERT(is_building());
761  current_block_ = block;
762  next_block_ = next_block;
763  if (block->IsStartBlock()) {
764  block->UpdateEnvironment(graph_->start_environment());
765  argument_count_ = 0;
766  } else if (block->predecessors()->length() == 1) {
767  // We have a single predecessor => copy environment and outgoing
768  // argument count from the predecessor.
769  ASSERT(block->phis()->length() == 0);
770  HBasicBlock* pred = block->predecessors()->at(0);
771  HEnvironment* last_environment = pred->last_environment();
772  ASSERT(last_environment != NULL);
773  // Only copy the environment, if it is later used again.
774  if (pred->end()->SecondSuccessor() == NULL) {
775  ASSERT(pred->end()->FirstSuccessor() == block);
776  } else {
777  if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
778  pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
779  last_environment = last_environment->Copy();
780  }
781  }
782  block->UpdateEnvironment(last_environment);
783  ASSERT(pred->argument_count() >= 0);
784  argument_count_ = pred->argument_count();
785  } else {
786  // We are at a state join => process phis.
787  HBasicBlock* pred = block->predecessors()->at(0);
788  // No need to copy the environment, it cannot be used later.
789  HEnvironment* last_environment = pred->last_environment();
790  for (int i = 0; i < block->phis()->length(); ++i) {
791  HPhi* phi = block->phis()->at(i);
792  last_environment->SetValueAt(phi->merged_index(), phi);
793  }
794  for (int i = 0; i < block->deleted_phis()->length(); ++i) {
795  last_environment->SetValueAt(block->deleted_phis()->at(i),
796  graph_->GetConstantUndefined());
797  }
798  block->UpdateEnvironment(last_environment);
799  // Pick up the outgoing argument count of one of the predecessors.
800  argument_count_ = pred->argument_count();
801  }
802  HInstruction* current = block->first();
803  int start = chunk_->instructions()->length();
804  while (current != NULL && !is_aborted()) {
805  // Code for constants in registers is generated lazily.
806  if (!current->EmitAtUses()) {
807  VisitInstruction(current);
808  }
809  current = current->next();
810  }
811  int end = chunk_->instructions()->length() - 1;
812  if (end >= start) {
813  block->set_first_instruction_index(start);
814  block->set_last_instruction_index(end);
815  }
816  block->set_argument_count(argument_count_);
817  next_block_ = NULL;
818  current_block_ = NULL;
819 }
820 
821 
822 void LChunkBuilder::VisitInstruction(HInstruction* current) {
823  HInstruction* old_current = current_instruction_;
824  current_instruction_ = current;
825  if (current->has_position()) position_ = current->position();
826  LInstruction* instr = current->CompileToLithium(this);
827 
828  if (instr != NULL) {
829  if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
830  instr = AssignPointerMap(instr);
831  }
832  if (FLAG_stress_environments && !instr->HasEnvironment()) {
833  instr = AssignEnvironment(instr);
834  }
835  instr->set_hydrogen_value(current);
836  chunk_->AddInstruction(instr, current_block_);
837  }
838  current_instruction_ = old_current;
839 }
840 
841 
842 LEnvironment* LChunkBuilder::CreateEnvironment(
843  HEnvironment* hydrogen_env,
844  int* argument_index_accumulator) {
845  if (hydrogen_env == NULL) return NULL;
846 
847  LEnvironment* outer =
848  CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
849  BailoutId ast_id = hydrogen_env->ast_id();
850  ASSERT(!ast_id.IsNone() ||
851  hydrogen_env->frame_type() != JS_FUNCTION);
852  int value_count = hydrogen_env->length();
853  LEnvironment* result = new(zone()) LEnvironment(
854  hydrogen_env->closure(),
855  hydrogen_env->frame_type(),
856  ast_id,
857  hydrogen_env->parameter_count(),
858  argument_count_,
859  value_count,
860  outer,
861  hydrogen_env->entry(),
862  zone());
863  int argument_index = *argument_index_accumulator;
864  for (int i = 0; i < value_count; ++i) {
865  if (hydrogen_env->is_special_index(i)) continue;
866 
867  HValue* value = hydrogen_env->values()->at(i);
868  LOperand* op = NULL;
869  if (value->IsArgumentsObject()) {
870  op = NULL;
871  } else if (value->IsPushArgument()) {
872  op = new(zone()) LArgument(argument_index++);
873  } else {
874  op = UseAny(value);
875  }
876  result->AddValue(op,
877  value->representation(),
878  value->CheckFlag(HInstruction::kUint32));
879  }
880 
881  if (hydrogen_env->frame_type() == JS_FUNCTION) {
882  *argument_index_accumulator = argument_index;
883  }
884 
885  return result;
886 }
887 
888 
889 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
890  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
891 }
892 
893 
894 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
895  HValue* value = instr->value();
896  if (value->EmitAtUses()) {
897  HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
898  ? instr->FirstSuccessor()
899  : instr->SecondSuccessor();
900  return new(zone()) LGoto(successor->block_id());
901  }
902 
903  LBranch* result = new(zone()) LBranch(UseRegister(value));
904  // Tagged values that are not known smis or booleans require a
905  // deoptimization environment.
906  Representation rep = value->representation();
907  HType type = value->type();
908  if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
909  return AssignEnvironment(result);
910  }
911  return result;
912 }
913 
914 
915 
916 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
917  ASSERT(instr->value()->representation().IsTagged());
918  LOperand* value = UseRegisterAtStart(instr->value());
919  LOperand* temp = TempRegister();
920  return new(zone()) LCmpMapAndBranch(value, temp);
921 }
922 
923 
924 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
925  LOperand* value = UseRegister(instr->value());
926  return DefineAsRegister(new(zone()) LArgumentsLength(value));
927 }
928 
929 
930 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
931  return DefineAsRegister(new(zone()) LArgumentsElements);
932 }
933 
934 
935 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
936  LInstanceOf* result =
937  new(zone()) LInstanceOf(UseFixed(instr->left(), r0),
938  UseFixed(instr->right(), r1));
939  return MarkAsCall(DefineFixed(result, r0), instr);
940 }
941 
942 
943 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
944  HInstanceOfKnownGlobal* instr) {
945  LInstanceOfKnownGlobal* result =
946  new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), r0),
947  FixedTemp(r4));
948  return MarkAsCall(DefineFixed(result, r0), instr);
949 }
950 
951 
952 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
953  LOperand* receiver = UseRegisterAtStart(instr->receiver());
954  LOperand* function = UseRegisterAtStart(instr->function());
955  LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
956  return AssignEnvironment(DefineSameAsFirst(result));
957 }
958 
959 
960 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
961  LOperand* function = UseFixed(instr->function(), r1);
962  LOperand* receiver = UseFixed(instr->receiver(), r0);
963  LOperand* length = UseFixed(instr->length(), r2);
964  LOperand* elements = UseFixed(instr->elements(), r3);
965  LApplyArguments* result = new(zone()) LApplyArguments(function,
966  receiver,
967  length,
968  elements);
969  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
970 }
971 
972 
973 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
974  ++argument_count_;
975  LOperand* argument = Use(instr->argument());
976  return new(zone()) LPushArgument(argument);
977 }
978 
979 
980 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
981  return instr->HasNoUses()
982  ? NULL
983  : DefineAsRegister(new(zone()) LThisFunction);
984 }
985 
986 
987 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
988  return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
989 }
990 
991 
992 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
993  LOperand* context = UseRegisterAtStart(instr->value());
994  return DefineAsRegister(new(zone()) LOuterContext(context));
995 }
996 
997 
998 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
999  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
1000 }
1001 
1002 
1003 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1004  LOperand* context = UseRegisterAtStart(instr->value());
1005  return DefineAsRegister(new(zone()) LGlobalObject(context));
1006 }
1007 
1008 
1009 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1010  LOperand* global_object = UseRegisterAtStart(instr->value());
1011  return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1012 }
1013 
1014 
1015 LInstruction* LChunkBuilder::DoCallConstantFunction(
1016  HCallConstantFunction* instr) {
1017  argument_count_ -= instr->argument_count();
1018  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, r0), instr);
1019 }
1020 
1021 
1022 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1023  LOperand* function = UseFixed(instr->function(), r1);
1024  argument_count_ -= instr->argument_count();
1025  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1026  return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1027 }
1028 
1029 
1030 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1031  BuiltinFunctionId op = instr->op();
1032  if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1033  LOperand* input = UseFixedDouble(instr->value(), d2);
1034  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
1035  return MarkAsCall(DefineFixedDouble(result, d2), instr);
1036  } else if (op == kMathPowHalf) {
1037  LOperand* input = UseFixedDouble(instr->value(), d2);
1038  LOperand* temp = FixedTemp(d3);
1039  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1040  return DefineFixedDouble(result, d2);
1041  } else {
1042  LOperand* input = UseRegisterAtStart(instr->value());
1043 
1044  LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
1045  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1046  switch (op) {
1047  case kMathAbs:
1048  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1049  case kMathFloor:
1050  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1051  case kMathSqrt:
1052  return DefineAsRegister(result);
1053  case kMathRound:
1054  return AssignEnvironment(DefineAsRegister(result));
1055  default:
1056  UNREACHABLE();
1057  return NULL;
1058  }
1059  }
1060 }
1061 
1062 
1063 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1064  ASSERT(instr->key()->representation().IsTagged());
1065  argument_count_ -= instr->argument_count();
1066  LOperand* key = UseFixed(instr->key(), r2);
1067  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), r0), instr);
1068 }
1069 
1070 
1071 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1072  argument_count_ -= instr->argument_count();
1073  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, r0), instr);
1074 }
1075 
1076 
1077 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1078  argument_count_ -= instr->argument_count();
1079  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, r0), instr);
1080 }
1081 
1082 
1083 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1084  argument_count_ -= instr->argument_count();
1085  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, r0), instr);
1086 }
1087 
1088 
1089 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1090  LOperand* constructor = UseFixed(instr->constructor(), r1);
1091  argument_count_ -= instr->argument_count();
1092  LCallNew* result = new(zone()) LCallNew(constructor);
1093  return MarkAsCall(DefineFixed(result, r0), instr);
1094 }
1095 
1096 
1097 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1098  LOperand* function = UseFixed(instr->function(), r1);
1099  argument_count_ -= instr->argument_count();
1100  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), r0),
1101  instr);
1102 }
1103 
1104 
1105 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1106  argument_count_ -= instr->argument_count();
1107  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, r0), instr);
1108 }
1109 
1110 
1111 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1112  return DoShift(Token::SHR, instr);
1113 }
1114 
1115 
1116 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1117  return DoShift(Token::SAR, instr);
1118 }
1119 
1120 
1121 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1122  return DoShift(Token::SHL, instr);
1123 }
1124 
1125 
1126 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1127  if (instr->representation().IsInteger32()) {
1128  ASSERT(instr->left()->representation().IsInteger32());
1129  ASSERT(instr->right()->representation().IsInteger32());
1130 
1131  LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1132  LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1133  return DefineAsRegister(new(zone()) LBitI(left, right));
1134  } else {
1135  ASSERT(instr->representation().IsTagged());
1136  ASSERT(instr->left()->representation().IsTagged());
1137  ASSERT(instr->right()->representation().IsTagged());
1138 
1139  LOperand* left = UseFixed(instr->left(), r1);
1140  LOperand* right = UseFixed(instr->right(), r0);
1141  LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1142  return MarkAsCall(DefineFixed(result, r0), instr);
1143  }
1144 }
1145 
1146 
1147 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1148  ASSERT(instr->value()->representation().IsInteger32());
1149  ASSERT(instr->representation().IsInteger32());
1150  if (instr->HasNoUses()) return NULL;
1151  LOperand* value = UseRegisterAtStart(instr->value());
1152  return DefineAsRegister(new(zone()) LBitNotI(value));
1153 }
1154 
1155 
1156 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1157  if (instr->representation().IsDouble()) {
1158  return DoArithmeticD(Token::DIV, instr);
1159  } else if (instr->representation().IsInteger32()) {
1160  // TODO(1042) The fixed register allocation
1161  // is needed because we call TypeRecordingBinaryOpStub from
1162  // the generated code, which requires registers r0
1163  // and r1 to be used. We should remove that
1164  // when we provide a native implementation.
1165  LOperand* dividend = UseFixed(instr->left(), r0);
1166  LOperand* divisor = UseFixed(instr->right(), r1);
1167  return AssignEnvironment(AssignPointerMap(
1168  DefineFixed(new(zone()) LDivI(dividend, divisor), r0)));
1169  } else {
1170  return DoArithmeticT(Token::DIV, instr);
1171  }
1172 }
1173 
1174 
1175 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
1176  uint32_t divisor_abs = abs(divisor);
1177  // Dividing by 0, 1, and powers of 2 is easy.
1178  // Note that IsPowerOf2(0) returns true;
1179  ASSERT(IsPowerOf2(0) == true);
1180  if (IsPowerOf2(divisor_abs)) return true;
1181 
1182  // We have magic numbers for a few specific divisors.
1183  // Details and proofs can be found in:
1184  // - Hacker's Delight, Henry S. Warren, Jr.
1185  // - The PowerPC Compiler Writer’s Guide
1186  // and probably many others.
1187  //
1188  // We handle
1189  // <divisor with magic numbers> * <power of 2>
1190  // but not
1191  // <divisor with magic numbers> * <other divisor with magic numbers>
1192  int32_t power_of_2_factor =
1193  CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1194  DivMagicNumbers magic_numbers =
1195  DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1196  if (magic_numbers.M != InvalidDivMagicNumber.M) return true;
1197 
1198  return false;
1199 }
1200 
1201 
1202 HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1203  // A value with an integer representation does not need to be transformed.
1204  if (dividend->representation().IsInteger32()) {
1205  return dividend;
1206  // A change from an integer32 can be replaced by the integer32 value.
1207  } else if (dividend->IsChange() &&
1208  HChange::cast(dividend)->from().IsInteger32()) {
1209  return HChange::cast(dividend)->value();
1210  }
1211  return NULL;
1212 }
1213 
1214 
1215 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1216  // Only optimize when we have magic numbers for the divisor.
1217  // The standard integer division routine is usually slower than transitionning
1218  // to VFP.
1219  if (divisor->IsConstant() &&
1220  HConstant::cast(divisor)->HasInteger32Value()) {
1221  HConstant* constant_val = HConstant::cast(divisor);
1222  int32_t int32_val = constant_val->Integer32Value();
1223  if (LChunkBuilder::HasMagicNumberForDivisor(int32_val)) {
1224  return constant_val->CopyToRepresentation(Representation::Integer32(),
1225  divisor->block()->zone());
1226  }
1227  }
1228  return NULL;
1229 }
1230 
1231 
1232 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1233  HValue* right = instr->right();
1234  LOperand* dividend = UseRegister(instr->left());
1235  LOperand* divisor = UseRegisterOrConstant(right);
1236  LOperand* remainder = TempRegister();
1237  ASSERT(right->IsConstant() &&
1238  HConstant::cast(right)->HasInteger32Value() &&
1239  HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()));
1240  return AssignEnvironment(DefineAsRegister(
1241  new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
1242 }
1243 
1244 
1245 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1246  if (instr->representation().IsInteger32()) {
1247  ASSERT(instr->left()->representation().IsInteger32());
1248  ASSERT(instr->right()->representation().IsInteger32());
1249 
1250  LModI* mod;
1251  if (instr->HasPowerOf2Divisor()) {
1252  ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1253  LOperand* value = UseRegisterAtStart(instr->left());
1254  mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
1255  } else {
1256  LOperand* dividend = UseRegister(instr->left());
1257  LOperand* divisor = UseRegister(instr->right());
1258  mod = new(zone()) LModI(dividend,
1259  divisor,
1260  TempRegister(),
1261  FixedTemp(d10),
1262  FixedTemp(d11));
1263  }
1264 
1265  if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1266  instr->CheckFlag(HValue::kCanBeDivByZero)) {
1267  return AssignEnvironment(DefineAsRegister(mod));
1268  } else {
1269  return DefineAsRegister(mod);
1270  }
1271  } else if (instr->representation().IsTagged()) {
1272  return DoArithmeticT(Token::MOD, instr);
1273  } else {
1274  ASSERT(instr->representation().IsDouble());
1275  // We call a C function for double modulo. It can't trigger a GC.
1276  // We need to use fixed result register for the call.
1277  // TODO(fschneider): Allow any register as input registers.
1278  LOperand* left = UseFixedDouble(instr->left(), d1);
1279  LOperand* right = UseFixedDouble(instr->right(), d2);
1280  LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
1281  return MarkAsCall(DefineFixedDouble(result, d1), instr);
1282  }
1283 }
1284 
1285 
1286 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1287  if (instr->representation().IsInteger32()) {
1288  ASSERT(instr->left()->representation().IsInteger32());
1289  ASSERT(instr->right()->representation().IsInteger32());
1290  LOperand* left;
1291  LOperand* right = UseOrConstant(instr->MostConstantOperand());
1292  LOperand* temp = NULL;
1293  if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1294  (instr->CheckFlag(HValue::kCanOverflow) ||
1295  !right->IsConstantOperand())) {
1296  left = UseRegister(instr->LeastConstantOperand());
1297  temp = TempRegister();
1298  } else {
1299  left = UseRegisterAtStart(instr->LeastConstantOperand());
1300  }
1301  LMulI* mul = new(zone()) LMulI(left, right, temp);
1302  if (instr->CheckFlag(HValue::kCanOverflow) ||
1303  instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1304  AssignEnvironment(mul);
1305  }
1306  return DefineAsRegister(mul);
1307 
1308  } else if (instr->representation().IsDouble()) {
1309  return DoArithmeticD(Token::MUL, instr);
1310 
1311  } else {
1312  return DoArithmeticT(Token::MUL, instr);
1313  }
1314 }
1315 
1316 
1317 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1318  if (instr->representation().IsInteger32()) {
1319  ASSERT(instr->left()->representation().IsInteger32());
1320  ASSERT(instr->right()->representation().IsInteger32());
1321  LOperand* left = UseRegisterAtStart(instr->left());
1322  LOperand* right = UseOrConstantAtStart(instr->right());
1323  LSubI* sub = new(zone()) LSubI(left, right);
1324  LInstruction* result = DefineAsRegister(sub);
1325  if (instr->CheckFlag(HValue::kCanOverflow)) {
1326  result = AssignEnvironment(result);
1327  }
1328  return result;
1329  } else if (instr->representation().IsDouble()) {
1330  return DoArithmeticD(Token::SUB, instr);
1331  } else {
1332  return DoArithmeticT(Token::SUB, instr);
1333  }
1334 }
1335 
1336 
1337 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1338  if (instr->representation().IsInteger32()) {
1339  ASSERT(instr->left()->representation().IsInteger32());
1340  ASSERT(instr->right()->representation().IsInteger32());
1341  LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1342  LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1343  LAddI* add = new(zone()) LAddI(left, right);
1344  LInstruction* result = DefineAsRegister(add);
1345  if (instr->CheckFlag(HValue::kCanOverflow)) {
1346  result = AssignEnvironment(result);
1347  }
1348  return result;
1349  } else if (instr->representation().IsDouble()) {
1350  return DoArithmeticD(Token::ADD, instr);
1351  } else {
1352  ASSERT(instr->representation().IsTagged());
1353  return DoArithmeticT(Token::ADD, instr);
1354  }
1355 }
1356 
1357 
1358 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1359  LOperand* left = NULL;
1360  LOperand* right = NULL;
1361  if (instr->representation().IsInteger32()) {
1362  ASSERT(instr->left()->representation().IsInteger32());
1363  ASSERT(instr->right()->representation().IsInteger32());
1364  left = UseRegisterAtStart(instr->LeastConstantOperand());
1365  right = UseOrConstantAtStart(instr->MostConstantOperand());
1366  } else {
1367  ASSERT(instr->representation().IsDouble());
1368  ASSERT(instr->left()->representation().IsDouble());
1369  ASSERT(instr->right()->representation().IsDouble());
1370  left = UseRegisterAtStart(instr->left());
1371  right = UseRegisterAtStart(instr->right());
1372  }
1373  return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1374 }
1375 
1376 
1377 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1378  ASSERT(instr->representation().IsDouble());
1379  // We call a C function for double power. It can't trigger a GC.
1380  // We need to use fixed result register for the call.
1381  Representation exponent_type = instr->right()->representation();
1382  ASSERT(instr->left()->representation().IsDouble());
1383  LOperand* left = UseFixedDouble(instr->left(), d1);
1384  LOperand* right = exponent_type.IsDouble() ?
1385  UseFixedDouble(instr->right(), d2) :
1386  UseFixed(instr->right(), r2);
1387  LPower* result = new(zone()) LPower(left, right);
1388  return MarkAsCall(DefineFixedDouble(result, d3),
1389  instr,
1390  CAN_DEOPTIMIZE_EAGERLY);
1391 }
1392 
1393 
1394 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1395  ASSERT(instr->representation().IsDouble());
1396  ASSERT(instr->global_object()->representation().IsTagged());
1397  LOperand* global_object = UseFixed(instr->global_object(), r0);
1398  LRandom* result = new(zone()) LRandom(global_object);
1399  return MarkAsCall(DefineFixedDouble(result, d7), instr);
1400 }
1401 
1402 
1403 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1404  ASSERT(instr->left()->representation().IsTagged());
1405  ASSERT(instr->right()->representation().IsTagged());
1406  LOperand* left = UseFixed(instr->left(), r1);
1407  LOperand* right = UseFixed(instr->right(), r0);
1408  LCmpT* result = new(zone()) LCmpT(left, right);
1409  return MarkAsCall(DefineFixed(result, r0), instr);
1410 }
1411 
1412 
1413 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1414  HCompareIDAndBranch* instr) {
1415  Representation r = instr->GetInputRepresentation();
1416  if (r.IsInteger32()) {
1417  ASSERT(instr->left()->representation().IsInteger32());
1418  ASSERT(instr->right()->representation().IsInteger32());
1419  LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1420  LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1421  return new(zone()) LCmpIDAndBranch(left, right);
1422  } else {
1423  ASSERT(r.IsDouble());
1424  ASSERT(instr->left()->representation().IsDouble());
1425  ASSERT(instr->right()->representation().IsDouble());
1426  LOperand* left = UseRegisterAtStart(instr->left());
1427  LOperand* right = UseRegisterAtStart(instr->right());
1428  return new(zone()) LCmpIDAndBranch(left, right);
1429  }
1430 }
1431 
1432 
1433 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1434  HCompareObjectEqAndBranch* instr) {
1435  LOperand* left = UseRegisterAtStart(instr->left());
1436  LOperand* right = UseRegisterAtStart(instr->right());
1437  return new(zone()) LCmpObjectEqAndBranch(left, right);
1438 }
1439 
1440 
1441 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1442  HCompareConstantEqAndBranch* instr) {
1443  LOperand* value = UseRegisterAtStart(instr->value());
1444  return new(zone()) LCmpConstantEqAndBranch(value);
1445 }
1446 
1447 
1448 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1449  ASSERT(instr->value()->representation().IsTagged());
1450  return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
1451 }
1452 
1453 
1454 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1455  ASSERT(instr->value()->representation().IsTagged());
1456  LOperand* value = UseRegisterAtStart(instr->value());
1457  LOperand* temp = TempRegister();
1458  return new(zone()) LIsObjectAndBranch(value, temp);
1459 }
1460 
1461 
1462 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1463  ASSERT(instr->value()->representation().IsTagged());
1464  LOperand* value = UseRegisterAtStart(instr->value());
1465  LOperand* temp = TempRegister();
1466  return new(zone()) LIsStringAndBranch(value, temp);
1467 }
1468 
1469 
1470 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1471  ASSERT(instr->value()->representation().IsTagged());
1472  return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1473 }
1474 
1475 
1476 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1477  HIsUndetectableAndBranch* instr) {
1478  ASSERT(instr->value()->representation().IsTagged());
1479  LOperand* value = UseRegisterAtStart(instr->value());
1480  return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1481 }
1482 
1483 
1484 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1485  HStringCompareAndBranch* instr) {
1486  ASSERT(instr->left()->representation().IsTagged());
1487  ASSERT(instr->right()->representation().IsTagged());
1488  LOperand* left = UseFixed(instr->left(), r1);
1489  LOperand* right = UseFixed(instr->right(), r0);
1490  LStringCompareAndBranch* result =
1491  new(zone()) LStringCompareAndBranch(left, right);
1492  return MarkAsCall(result, instr);
1493 }
1494 
1495 
1496 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1497  HHasInstanceTypeAndBranch* instr) {
1498  ASSERT(instr->value()->representation().IsTagged());
1499  LOperand* value = UseRegisterAtStart(instr->value());
1500  return new(zone()) LHasInstanceTypeAndBranch(value);
1501 }
1502 
1503 
1504 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1505  HGetCachedArrayIndex* instr) {
1506  ASSERT(instr->value()->representation().IsTagged());
1507  LOperand* value = UseRegisterAtStart(instr->value());
1508 
1509  return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1510 }
1511 
1512 
1513 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1514  HHasCachedArrayIndexAndBranch* instr) {
1515  ASSERT(instr->value()->representation().IsTagged());
1516  return new(zone()) LHasCachedArrayIndexAndBranch(
1517  UseRegisterAtStart(instr->value()));
1518 }
1519 
1520 
1521 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1522  HClassOfTestAndBranch* instr) {
1523  ASSERT(instr->value()->representation().IsTagged());
1524  LOperand* value = UseRegister(instr->value());
1525  return new(zone()) LClassOfTestAndBranch(value, TempRegister());
1526 }
1527 
1528 
1529 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1530  LOperand* array = UseRegisterAtStart(instr->value());
1531  return DefineAsRegister(new(zone()) LJSArrayLength(array));
1532 }
1533 
1534 
1535 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1536  HFixedArrayBaseLength* instr) {
1537  LOperand* array = UseRegisterAtStart(instr->value());
1538  return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
1539 }
1540 
1541 
1542 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1543  LOperand* map = UseRegisterAtStart(instr->value());
1544  return DefineAsRegister(new(zone()) LMapEnumLength(map));
1545 }
1546 
1547 
1548 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1549  LOperand* object = UseRegisterAtStart(instr->value());
1550  return DefineAsRegister(new(zone()) LElementsKind(object));
1551 }
1552 
1553 
1554 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1555  LOperand* object = UseRegister(instr->value());
1556  LValueOf* result = new(zone()) LValueOf(object, TempRegister());
1557  return DefineAsRegister(result);
1558 }
1559 
1560 
1561 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1562  LOperand* object = UseFixed(instr->value(), r0);
1563  LDateField* result =
1564  new(zone()) LDateField(object, FixedTemp(r1), instr->index());
1565  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1566 }
1567 
1568 
1569 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1570  LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1571  LOperand* length = UseRegister(instr->length());
1572  return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
1573 }
1574 
1575 
1576 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1577  // The control instruction marking the end of a block that completed
1578  // abruptly (e.g., threw an exception). There is nothing specific to do.
1579  return NULL;
1580 }
1581 
1582 
1583 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1584  LOperand* value = UseFixed(instr->value(), r0);
1585  return MarkAsCall(new(zone()) LThrow(value), instr);
1586 }
1587 
1588 
1589 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1590  return NULL;
1591 }
1592 
1593 
1594 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1595  // All HForceRepresentation instructions should be eliminated in the
1596  // representation change phase of Hydrogen.
1597  UNREACHABLE();
1598  return NULL;
1599 }
1600 
1601 
1602 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1603  Representation from = instr->from();
1604  Representation to = instr->to();
1605  if (from.IsTagged()) {
1606  if (to.IsDouble()) {
1607  LOperand* value = UseRegister(instr->value());
1608  LNumberUntagD* res = new(zone()) LNumberUntagD(value);
1609  return AssignEnvironment(DefineAsRegister(res));
1610  } else {
1611  ASSERT(to.IsInteger32());
1612  LOperand* value = UseRegisterAtStart(instr->value());
1613  LInstruction* res = NULL;
1614  if (instr->value()->type().IsSmi()) {
1615  res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
1616  } else {
1617  LOperand* temp1 = TempRegister();
1618  LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1619  : NULL;
1620  LOperand* temp3 = FixedTemp(d11);
1621  res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
1622  temp1,
1623  temp2,
1624  temp3));
1625  res = AssignEnvironment(res);
1626  }
1627  return res;
1628  }
1629  } else if (from.IsDouble()) {
1630  if (to.IsTagged()) {
1631  LOperand* value = UseRegister(instr->value());
1632  LOperand* temp1 = TempRegister();
1633  LOperand* temp2 = TempRegister();
1634 
1635  // Make sure that the temp and result_temp registers are
1636  // different.
1637  LUnallocated* result_temp = TempRegister();
1638  LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
1639  Define(result, result_temp);
1640  return AssignPointerMap(result);
1641  } else {
1642  ASSERT(to.IsInteger32());
1643  LOperand* value = UseRegister(instr->value());
1644  LOperand* temp1 = TempRegister();
1645  LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1646  LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
1647  return AssignEnvironment(DefineAsRegister(res));
1648  }
1649  } else if (from.IsInteger32()) {
1650  if (to.IsTagged()) {
1651  HValue* val = instr->value();
1652  LOperand* value = UseRegisterAtStart(val);
1653  if (val->CheckFlag(HInstruction::kUint32)) {
1654  LNumberTagU* result = new(zone()) LNumberTagU(value);
1655  return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1656  } else if (val->HasRange() && val->range()->IsInSmiRange()) {
1657  return DefineAsRegister(new(zone()) LSmiTag(value));
1658  } else {
1659  LNumberTagI* result = new(zone()) LNumberTagI(value);
1660  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1661  }
1662  } else {
1663  ASSERT(to.IsDouble());
1664  if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1665  return DefineAsRegister(
1666  new(zone()) LUint32ToDouble(UseRegister(instr->value())));
1667  } else {
1668  return DefineAsRegister(
1669  new(zone()) LInteger32ToDouble(Use(instr->value())));
1670  }
1671  }
1672  }
1673  UNREACHABLE();
1674  return NULL;
1675 }
1676 
1677 
1678 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1679  LOperand* value = UseRegisterAtStart(instr->value());
1680  return AssignEnvironment(new(zone()) LCheckNonSmi(value));
1681 }
1682 
1683 
1684 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1685  LOperand* value = UseRegisterAtStart(instr->value());
1686  LInstruction* result = new(zone()) LCheckInstanceType(value);
1687  return AssignEnvironment(result);
1688 }
1689 
1690 
1691 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1692  LOperand* temp1 = TempRegister();
1693  LOperand* temp2 = TempRegister();
1694  LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
1695  return AssignEnvironment(result);
1696 }
1697 
1698 
1699 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1700  LOperand* value = UseRegisterAtStart(instr->value());
1701  return AssignEnvironment(new(zone()) LCheckSmi(value));
1702 }
1703 
1704 
1705 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1706  LOperand* value = UseRegisterAtStart(instr->value());
1707  return AssignEnvironment(new(zone()) LCheckFunction(value));
1708 }
1709 
1710 
1711 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1712  LOperand* value = UseRegisterAtStart(instr->value());
1713  LInstruction* result = new(zone()) LCheckMaps(value);
1714  return AssignEnvironment(result);
1715 }
1716 
1717 
1718 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1719  HValue* value = instr->value();
1720  Representation input_rep = value->representation();
1721  LOperand* reg = UseRegister(value);
1722  if (input_rep.IsDouble()) {
1723  return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11)));
1724  } else if (input_rep.IsInteger32()) {
1725  return DefineAsRegister(new(zone()) LClampIToUint8(reg));
1726  } else {
1727  ASSERT(input_rep.IsTagged());
1728  // Register allocator doesn't (yet) support allocation of double
1729  // temps. Reserve d1 explicitly.
1730  LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11));
1731  return AssignEnvironment(DefineAsRegister(result));
1732  }
1733 }
1734 
1735 
1736 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1737  return new(zone()) LReturn(UseFixed(instr->value(), r0));
1738 }
1739 
1740 
1741 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1742  Representation r = instr->representation();
1743  if (r.IsInteger32()) {
1744  return DefineAsRegister(new(zone()) LConstantI);
1745  } else if (r.IsDouble()) {
1746  return DefineAsRegister(new(zone()) LConstantD);
1747  } else if (r.IsTagged()) {
1748  return DefineAsRegister(new(zone()) LConstantT);
1749  } else {
1750  UNREACHABLE();
1751  return NULL;
1752  }
1753 }
1754 
1755 
1756 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1757  LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
1758  return instr->RequiresHoleCheck()
1759  ? AssignEnvironment(DefineAsRegister(result))
1760  : DefineAsRegister(result);
1761 }
1762 
1763 
1764 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1765  LOperand* global_object = UseFixed(instr->global_object(), r0);
1766  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
1767  return MarkAsCall(DefineFixed(result, r0), instr);
1768 }
1769 
1770 
1771 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1772  LOperand* value = UseRegister(instr->value());
1773  // Use a temp to check the value in the cell in the case where we perform
1774  // a hole check.
1775  return instr->RequiresHoleCheck()
1776  ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
1777  : new(zone()) LStoreGlobalCell(value, NULL);
1778 }
1779 
1780 
1781 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1782  LOperand* global_object = UseFixed(instr->global_object(), r1);
1783  LOperand* value = UseFixed(instr->value(), r0);
1784  LStoreGlobalGeneric* result =
1785  new(zone()) LStoreGlobalGeneric(global_object, value);
1786  return MarkAsCall(result, instr);
1787 }
1788 
1789 
1790 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1791  LOperand* context = UseRegisterAtStart(instr->value());
1792  LInstruction* result =
1793  DefineAsRegister(new(zone()) LLoadContextSlot(context));
1794  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1795 }
1796 
1797 
1798 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1799  LOperand* context;
1800  LOperand* value;
1801  if (instr->NeedsWriteBarrier()) {
1802  context = UseTempRegister(instr->context());
1803  value = UseTempRegister(instr->value());
1804  } else {
1805  context = UseRegister(instr->context());
1806  value = UseRegister(instr->value());
1807  }
1808  LInstruction* result = new(zone()) LStoreContextSlot(context, value);
1809  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1810 }
1811 
1812 
1813 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1814  return DefineAsRegister(
1815  new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
1816 }
1817 
1818 
1819 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1820  HLoadNamedFieldPolymorphic* instr) {
1821  ASSERT(instr->representation().IsTagged());
1822  if (instr->need_generic()) {
1823  LOperand* obj = UseFixed(instr->object(), r0);
1824  LLoadNamedFieldPolymorphic* result =
1825  new(zone()) LLoadNamedFieldPolymorphic(obj);
1826  return MarkAsCall(DefineFixed(result, r0), instr);
1827  } else {
1828  LOperand* obj = UseRegisterAtStart(instr->object());
1829  LLoadNamedFieldPolymorphic* result =
1830  new(zone()) LLoadNamedFieldPolymorphic(obj);
1831  return AssignEnvironment(DefineAsRegister(result));
1832  }
1833 }
1834 
1835 
1836 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1837  LOperand* object = UseFixed(instr->object(), r0);
1838  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), r0);
1839  return MarkAsCall(result, instr);
1840 }
1841 
1842 
1843 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1844  HLoadFunctionPrototype* instr) {
1845  return AssignEnvironment(DefineAsRegister(
1846  new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1847 }
1848 
1849 
1850 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1851  LOperand* input = UseRegisterAtStart(instr->value());
1852  return DefineAsRegister(new(zone()) LLoadElements(input));
1853 }
1854 
1855 
1856 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1857  HLoadExternalArrayPointer* instr) {
1858  LOperand* input = UseRegisterAtStart(instr->value());
1859  return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
1860 }
1861 
1862 
1863 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1864  HLoadKeyedFastElement* instr) {
1865  ASSERT(instr->representation().IsTagged());
1866  ASSERT(instr->key()->representation().IsInteger32() ||
1867  instr->key()->representation().IsTagged());
1868  LOperand* obj = UseRegisterAtStart(instr->object());
1869  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1870  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
1871  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1872  return DefineAsRegister(result);
1873 }
1874 
1875 
1876 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1877  HLoadKeyedFastDoubleElement* instr) {
1878  ASSERT(instr->representation().IsDouble());
1879  ASSERT(instr->key()->representation().IsInteger32() ||
1880  instr->key()->representation().IsTagged());
1881  LOperand* elements = UseTempRegister(instr->elements());
1882  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1883  LLoadKeyedFastDoubleElement* result =
1884  new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1885  return AssignEnvironment(DefineAsRegister(result));
1886 }
1887 
1888 
1889 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1890  HLoadKeyedSpecializedArrayElement* instr) {
1891  ElementsKind elements_kind = instr->elements_kind();
1892  ASSERT(
1893  (instr->representation().IsInteger32() &&
1894  (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1895  (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1896  (instr->representation().IsDouble() &&
1897  ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1898  (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1899  ASSERT(instr->key()->representation().IsInteger32() ||
1900  instr->key()->representation().IsTagged());
1901  LOperand* external_pointer = UseRegister(instr->external_pointer());
1902  LOperand* key = UseRegisterOrConstant(instr->key());
1903  LLoadKeyedSpecializedArrayElement* result =
1904  new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1905  LInstruction* load_instr = DefineAsRegister(result);
1906  // An unsigned int array load might overflow and cause a deopt, make sure it
1907  // has an environment.
1908  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
1909  AssignEnvironment(load_instr) : load_instr;
1910 }
1911 
1912 
1913 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1914  LOperand* object = UseFixed(instr->object(), r1);
1915  LOperand* key = UseFixed(instr->key(), r0);
1916 
1917  LInstruction* result =
1918  DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0);
1919  return MarkAsCall(result, instr);
1920 }
1921 
1922 
1923 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1924  HStoreKeyedFastElement* instr) {
1925  bool needs_write_barrier = instr->NeedsWriteBarrier();
1926  ASSERT(instr->value()->representation().IsTagged());
1927  ASSERT(instr->object()->representation().IsTagged());
1928  ASSERT(instr->key()->representation().IsInteger32() ||
1929  instr->key()->representation().IsTagged());
1930 
1931  LOperand* obj = UseTempRegister(instr->object());
1932  LOperand* val = needs_write_barrier
1933  ? UseTempRegister(instr->value())
1934  : UseRegisterAtStart(instr->value());
1935  LOperand* key = needs_write_barrier
1936  ? UseTempRegister(instr->key())
1937  : UseRegisterOrConstantAtStart(instr->key());
1938  return new(zone()) LStoreKeyedFastElement(obj, key, val);
1939 }
1940 
1941 
1942 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1943  HStoreKeyedFastDoubleElement* instr) {
1944  ASSERT(instr->value()->representation().IsDouble());
1945  ASSERT(instr->elements()->representation().IsTagged());
1946  ASSERT(instr->key()->representation().IsInteger32() ||
1947  instr->key()->representation().IsTagged());
1948 
1949  LOperand* elements = UseRegisterAtStart(instr->elements());
1950  LOperand* val = UseTempRegister(instr->value());
1951  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1952 
1953  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1954 }
1955 
1956 
1957 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1958  HStoreKeyedSpecializedArrayElement* instr) {
1959  ElementsKind elements_kind = instr->elements_kind();
1960  ASSERT(
1961  (instr->value()->representation().IsInteger32() &&
1962  (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1963  (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1964  (instr->value()->representation().IsDouble() &&
1965  ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1966  (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1967  ASSERT(instr->external_pointer()->representation().IsExternal());
1968  ASSERT(instr->key()->representation().IsInteger32() ||
1969  instr->key()->representation().IsTagged());
1970 
1971  LOperand* external_pointer = UseRegister(instr->external_pointer());
1972  bool val_is_temp_register =
1973  elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
1974  elements_kind == EXTERNAL_FLOAT_ELEMENTS;
1975  LOperand* val = val_is_temp_register
1976  ? UseTempRegister(instr->value())
1977  : UseRegister(instr->value());
1978  LOperand* key = UseRegisterOrConstant(instr->key());
1979 
1980  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
1981  key,
1982  val);
1983 }
1984 
1985 
1986 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1987  LOperand* obj = UseFixed(instr->object(), r2);
1988  LOperand* key = UseFixed(instr->key(), r1);
1989  LOperand* val = UseFixed(instr->value(), r0);
1990 
1991  ASSERT(instr->object()->representation().IsTagged());
1992  ASSERT(instr->key()->representation().IsTagged());
1993  ASSERT(instr->value()->representation().IsTagged());
1994 
1995  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
1996 }
1997 
1998 
1999 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2000  HTransitionElementsKind* instr) {
2001  ElementsKind from_kind = instr->original_map()->elements_kind();
2002  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
2003  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
2004  LOperand* object = UseRegister(instr->object());
2005  LOperand* new_map_reg = TempRegister();
2006  LTransitionElementsKind* result =
2007  new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
2008  return DefineSameAsFirst(result);
2009  } else {
2010  LOperand* object = UseFixed(instr->object(), r0);
2011  LOperand* fixed_object_reg = FixedTemp(r2);
2012  LOperand* new_map_reg = FixedTemp(r3);
2013  LTransitionElementsKind* result =
2014  new(zone()) LTransitionElementsKind(object,
2015  new_map_reg,
2016  fixed_object_reg);
2017  return MarkAsCall(DefineFixed(result, r0), instr);
2018  }
2019 }
2020 
2021 
2022 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2023  bool needs_write_barrier = instr->NeedsWriteBarrier();
2024  bool needs_write_barrier_for_map = !instr->transition().is_null() &&
2025  instr->NeedsWriteBarrierForMap();
2026 
2027  LOperand* obj;
2028  if (needs_write_barrier) {
2029  obj = instr->is_in_object()
2030  ? UseRegister(instr->object())
2031  : UseTempRegister(instr->object());
2032  } else {
2033  obj = needs_write_barrier_for_map
2034  ? UseRegister(instr->object())
2035  : UseRegisterAtStart(instr->object());
2036  }
2037 
2038  LOperand* val = needs_write_barrier
2039  ? UseTempRegister(instr->value())
2040  : UseRegister(instr->value());
2041 
2042  // We need a temporary register for write barrier of the map field.
2043  LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
2044 
2045  return new(zone()) LStoreNamedField(obj, val, temp);
2046 }
2047 
2048 
2049 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2050  LOperand* obj = UseFixed(instr->object(), r1);
2051  LOperand* val = UseFixed(instr->value(), r0);
2052 
2053  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
2054  return MarkAsCall(result, instr);
2055 }
2056 
2057 
2058 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2059  LOperand* left = UseRegisterAtStart(instr->left());
2060  LOperand* right = UseRegisterAtStart(instr->right());
2061  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), r0),
2062  instr);
2063 }
2064 
2065 
2066 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2067  LOperand* string = UseTempRegister(instr->string());
2068  LOperand* index = UseTempRegister(instr->index());
2069  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2070  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2071 }
2072 
2073 
2074 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2075  LOperand* char_code = UseRegister(instr->value());
2076  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2077  return AssignPointerMap(DefineAsRegister(result));
2078 }
2079 
2080 
2081 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2082  LOperand* string = UseRegisterAtStart(instr->value());
2083  return DefineAsRegister(new(zone()) LStringLength(string));
2084 }
2085 
2086 
2087 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2088  LAllocateObject* result =
2089  new(zone()) LAllocateObject(TempRegister(), TempRegister());
2090  return AssignPointerMap(DefineAsRegister(result));
2091 }
2092 
2093 
2094 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2095  return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, r0), instr);
2096 }
2097 
2098 
2099 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2100  return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, r0), instr);
2101 }
2102 
2103 
2104 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2105  return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, r0), instr);
2106 }
2107 
2108 
2109 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2110  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, r0), instr);
2111 }
2112 
2113 
2114 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2115  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, r0), instr);
2116 }
2117 
2118 
2119 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2120  LOperand* object = UseFixed(instr->object(), r0);
2121  LOperand* key = UseFixed(instr->key(), r1);
2122  LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
2123  return MarkAsCall(DefineFixed(result, r0), instr);
2124 }
2125 
2126 
2127 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2128  ASSERT(argument_count_ == 0);
2129  allocator_->MarkAsOsrEntry();
2130  current_block_->last_environment()->set_ast_id(instr->ast_id());
2131  return AssignEnvironment(new(zone()) LOsrEntry);
2132 }
2133 
2134 
2135 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2136  int spill_index = chunk()->GetParameterStackSlot(instr->index());
2137  return DefineAsSpilled(new(zone()) LParameter, spill_index);
2138 }
2139 
2140 
2141 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2142  int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
2143  if (spill_index > LUnallocated::kMaxFixedIndex) {
2144  Abort("Too many spill slots needed for OSR");
2145  spill_index = 0;
2146  }
2147  return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2148 }
2149 
2150 
2151 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2152  argument_count_ -= instr->argument_count();
2153  return MarkAsCall(DefineFixed(new(zone()) LCallStub, r0), instr);
2154 }
2155 
2156 
2157 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2158  // There are no real uses of the arguments object.
2159  // arguments.length and element access are supported directly on
2160  // stack arguments, and any real arguments object use causes a bailout.
2161  // So this value is never used.
2162  return NULL;
2163 }
2164 
2165 
2166 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2167  LOperand* args = UseRegister(instr->arguments());
2168  LOperand* length = UseTempRegister(instr->length());
2169  LOperand* index = UseRegister(instr->index());
2170  return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2171 }
2172 
2173 
2174 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2175  LOperand* object = UseFixed(instr->value(), r0);
2176  LToFastProperties* result = new(zone()) LToFastProperties(object);
2177  return MarkAsCall(DefineFixed(result, r0), instr);
2178 }
2179 
2180 
2181 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2182  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), r0));
2183  return MarkAsCall(DefineFixed(result, r0), instr);
2184 }
2185 
2186 
2187 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2188  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2189 }
2190 
2191 
2192 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2193  HIsConstructCallAndBranch* instr) {
2194  return new(zone()) LIsConstructCallAndBranch(TempRegister());
2195 }
2196 
2197 
2198 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2199  HEnvironment* env = current_block_->last_environment();
2200  ASSERT(env != NULL);
2201 
2202  env->set_ast_id(instr->ast_id());
2203 
2204  env->Drop(instr->pop_count());
2205  for (int i = 0; i < instr->values()->length(); ++i) {
2206  HValue* value = instr->values()->at(i);
2207  if (instr->HasAssignedIndexAt(i)) {
2208  env->Bind(instr->GetAssignedIndexAt(i), value);
2209  } else {
2210  env->Push(value);
2211  }
2212  }
2213 
2214  // If there is an instruction pending deoptimization environment create a
2215  // lazy bailout instruction to capture the environment.
2216  if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2217  LInstruction* result = new(zone()) LLazyBailout;
2218  result = AssignEnvironment(result);
2219  // Store the lazy deopt environment with the instruction if needed. Right
2220  // now it is only used for LInstanceOfKnownGlobal.
2221  instruction_pending_deoptimization_environment_->
2222  SetDeferredLazyDeoptimizationEnvironment(result->environment());
2223  instruction_pending_deoptimization_environment_ = NULL;
2224  pending_deoptimization_ast_id_ = BailoutId::None();
2225  return result;
2226  }
2227 
2228  return NULL;
2229 }
2230 
2231 
2232 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2233  if (instr->is_function_entry()) {
2234  return MarkAsCall(new(zone()) LStackCheck, instr);
2235  } else {
2236  ASSERT(instr->is_backwards_branch());
2237  return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2238  }
2239 }
2240 
2241 
2242 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2243  HEnvironment* outer = current_block_->last_environment();
2244  HConstant* undefined = graph()->GetConstantUndefined();
2245  HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2246  instr->arguments_count(),
2247  instr->function(),
2248  undefined,
2249  instr->call_kind(),
2250  instr->inlining_kind());
2251  if (instr->arguments_var() != NULL) {
2252  inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2253  }
2254  inner->set_entry(instr);
2255  current_block_->UpdateEnvironment(inner);
2256  chunk_->AddInlinedClosure(instr->closure());
2257  return NULL;
2258 }
2259 
2260 
2261 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2262  LInstruction* pop = NULL;
2263 
2264  HEnvironment* env = current_block_->last_environment();
2265 
2266  if (env->entry()->arguments_pushed()) {
2267  int argument_count = env->arguments_environment()->parameter_count();
2268  pop = new(zone()) LDrop(argument_count);
2269  argument_count_ -= argument_count;
2270  }
2271 
2272  HEnvironment* outer = current_block_->last_environment()->
2273  DiscardInlined(false);
2274  current_block_->UpdateEnvironment(outer);
2275 
2276  return pop;
2277 }
2278 
2279 
2280 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2281  LOperand* key = UseRegisterAtStart(instr->key());
2282  LOperand* object = UseRegisterAtStart(instr->object());
2283  LIn* result = new(zone()) LIn(key, object);
2284  return MarkAsCall(DefineFixed(result, r0), instr);
2285 }
2286 
2287 
2288 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2289  LOperand* object = UseFixed(instr->enumerable(), r0);
2290  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
2291  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
2292 }
2293 
2294 
2295 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2296  LOperand* map = UseRegister(instr->map());
2297  return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
2298 }
2299 
2300 
2301 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2302  LOperand* value = UseRegisterAtStart(instr->value());
2303  LOperand* map = UseRegisterAtStart(instr->map());
2304  return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2305 }
2306 
2307 
2308 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2309  LOperand* object = UseRegister(instr->object());
2310  LOperand* index = UseRegister(instr->index());
2311  return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2312 }
2313 
2314 
2315 } } // namespace v8::internal
#define DEFINE_COMPILE(type)
Definition: lithium-arm.cc:37
const DwVfpRegister d11
static LUnallocated * cast(LOperand *op)
Definition: lithium.h:198
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:305
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:219
Handle< Object > name() const
Definition: lithium-arm.h:1920
const char * ToCString(const v8::String::Utf8Value &value)
const Register r3
const DivMagicNumbers DivMagicNumberFor(int32_t divisor)
Definition: utils.cc:93
static String * cast(Object *obj)
virtual void PrintOutputOperandTo(StringStream *stream)
Definition: lithium-arm.cc:120
Token::Value op() const
Definition: lithium-arm.h:1235
void MarkSpilledDoubleRegister(int allocation_index, LOperand *spill_operand)
Definition: lithium-arm.cc:84
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:279
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:226
static Representation Integer32()
Handle< String > name() const
Definition: lithium-arm.h:1686
int int32_t
Definition: unicode.cc:47
static const int kNumAllocatableRegisters
Handle< Object > name() const
Definition: lithium-arm.h:1898
LOperand * constructor()
Definition: lithium-arm.h:1709
LEnvironment * environment() const
Definition: lithium-arm.h:244
Token::Value op() const
Definition: lithium-arm.h:641
#define ASSERT(condition)
Definition: checks.h:270
virtual const char * Mnemonic() const =0
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:111
const Register r2
void PrintTo(StringStream *stream)
Definition: lithium.cc:220
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
Definition: lithium-arm.h:49
Representation representation() const
EqualityKind kind() const
Definition: lithium-arm.h:709
void Add(Vector< const char > format, Vector< FmtElm > elms)
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:366
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:293
int GetNextSpillIndex(bool is_double)
Definition: lithium-arm.cc:408
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:299
virtual bool HasResult() const =0
#define UNREACHABLE()
Definition: checks.h:50
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:324
DwVfpRegister DoubleRegister
void PrintTo(StringStream *stream)
Definition: lithium.cc:175
LLabel * replacement() const
Definition: lithium-arm.h:419
static HUnaryOperation * cast(HValue *value)
virtual const char * Mnemonic() const
Definition: lithium-arm.cc:156
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:201
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:330
void MarkSpilledRegister(int allocation_index, LOperand *spill_operand)
Definition: lithium-arm.cc:54
static const char * String(Value tok)
Definition: token.h:275
static LDoubleStackSlot * Create(int index, Zone *zone)
Definition: lithium.h:326
const DwVfpRegister d7
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:336
int block_id() const
Definition: lithium-arm.h:416
bool HasEnvironment() const
Definition: lithium-arm.h:245
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:341
virtual LOperand * result()=0
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:233
static int ToAllocationIndex(Register reg)
Definition: assembler-arm.h:77
Zone * zone() const
Definition: lithium.h:683
const DwVfpRegister d3
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:393
const Register r0
bool IsPowerOf2(T x)
Definition: utils.h:50
virtual void PrintTo(StringStream *stream)
Definition: lithium-arm.cc:92
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:125
static BailoutId None()
Definition: utils.h:1014
static LStackSlot * Create(int index, Zone *zone)
Definition: lithium.h:301
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:357
static const int kMaxFixedIndex
Definition: lithium.h:159
LOsrEntry()
Definition: lithium-arm.cc:44
LPointerMap * pointer_map() const
Definition: lithium-arm.h:248
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:312
virtual DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,"string-compare-and-branch") Token void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:247
const Register r1
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:145
int block_id() const
Definition: lithium-arm.h:378
void PrintDataTo(StringStream *stream) const
Definition: lithium.cc:154
virtual const char * Mnemonic() const
Definition: lithium-arm.cc:170
static int ToAllocationIndex(DwVfpRegister reg)
static const int kNumAllocatableRegisters
Definition: assembler-arm.h:74
Token::Value op() const
Definition: lithium-arm.h:1258
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:210
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:190
Handle< String > name() const
Definition: lithium-arm.h:1659
const DwVfpRegister d2
bool HasFixedPolicy() const
Definition: lithium.h:165
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:195
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 use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra 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 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
bool HasPointerMap() const
Definition: lithium-arm.h:249
const DwVfpRegister d1
const DwVfpRegister d10
bool IsRedundant() const
Definition: lithium-arm.cc:134
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:319
const DivMagicNumbers InvalidDivMagicNumber
Definition: utils.h:101
static HValue * cast(HValue *value)
Handle< String > type_literal()
Definition: lithium-arm.h:2307
void PrintTo(StringStream *stream)
Definition: lithium.cc:52
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:288
LOperand * GetNextSpillSlot(bool is_double)
Definition: lithium-arm.cc:415
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:348
const Register r4