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-mips.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 "mips/lithium-mips.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 
92 void LInstruction::PrintTo(StringStream* stream) {
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 
111 void LInstruction::PrintDataTo(StringStream* stream) {
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 
120 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
121  if (HasResult()) result()->PrintTo(stream);
122 }
123 
124 
125 void LLabel::PrintDataTo(StringStream* stream) {
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 
145 void LGap::PrintDataTo(StringStream* stream) {
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 "sll-t";
181  case Token::SAR: return "sra-t";
182  case Token::SHR: return "srl-t";
183  default:
184  UNREACHABLE();
185  return NULL;
186  }
187 }
188 
189 
190 void LGoto::PrintDataTo(StringStream* stream) {
191  stream->Add("B%d", block_id());
192 }
193 
194 
195 void LBranch::PrintDataTo(StringStream* stream) {
196  stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
197  value()->PrintTo(stream);
198 }
199 
200 
201 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
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 
210 void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
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 
219 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
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 
226 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
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 
233 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
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 
240 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
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 
247 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
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 
255 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
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 
279 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
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 
288 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
289  stream->Add("#%d / ", arity());
290 }
291 
292 
293 void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
294  stream->Add("/%s ", hydrogen()->OpName());
295  value()->PrintTo(stream);
296 }
297 
298 
299 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
300  context()->PrintTo(stream);
301  stream->Add("[%d]", slot_index());
302 }
303 
304 
305 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
306  context()->PrintTo(stream);
307  stream->Add("[%d] <- ", slot_index());
308  value()->PrintTo(stream);
309 }
310 
311 
312 void LInvokeFunction::PrintDataTo(StringStream* stream) {
313  stream->Add("= ");
314  function()->PrintTo(stream);
315  stream->Add(" #%d / ", arity());
316 }
317 
318 
319 void LCallKeyed::PrintDataTo(StringStream* stream) {
320  stream->Add("[a2] #%d / ", arity());
321 }
322 
323 
324 void LCallNamed::PrintDataTo(StringStream* stream) {
325  SmartArrayPointer<char> name_string = name()->ToCString();
326  stream->Add("%s #%d / ", *name_string, arity());
327 }
328 
329 
330 void LCallGlobal::PrintDataTo(StringStream* stream) {
331  SmartArrayPointer<char> name_string = name()->ToCString();
332  stream->Add("%s #%d / ", *name_string, arity());
333 }
334 
335 
336 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
337  stream->Add("#%d / ", arity());
338 }
339 
340 
341 void LCallNew::PrintDataTo(StringStream* stream) {
342  stream->Add("= ");
343  constructor()->PrintTo(stream);
344  stream->Add(" #%d / ", arity());
345 }
346 
347 
348 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
349  arguments()->PrintTo(stream);
350  stream->Add(" length ");
351  length()->PrintTo(stream);
352  stream->Add(" index ");
353  index()->PrintTo(stream);
354 }
355 
356 
357 void LStoreNamedField::PrintDataTo(StringStream* stream) {
358  object()->PrintTo(stream);
359  stream->Add(".");
360  stream->Add(*String::cast(*name())->ToCString());
361  stream->Add(" <- ");
362  value()->PrintTo(stream);
363 }
364 
365 
366 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
367  object()->PrintTo(stream);
368  stream->Add(".");
369  stream->Add(*String::cast(*name())->ToCString());
370  stream->Add(" <- ");
371  value()->PrintTo(stream);
372 }
373 
374 
375 void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
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 
393 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
394  object()->PrintTo(stream);
395  stream->Add("[");
396  key()->PrintTo(stream);
397  stream->Add("] <- ");
398  value()->PrintTo(stream);
399 }
400 
401 
402 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
403  object()->PrintTo(stream);
404  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
405 }
406 
407 
408 int LPlatformChunk::GetNextSpillIndex(bool is_double) {
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 
415 LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
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 LCodeGen::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(), a1);
684  LOperand* right = UseFixed(instr->right(), a0);
685  LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
686  return MarkAsCall(DefineFixed(result, v0), 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  bool does_deopt = false;
706 
707  if (FLAG_opt_safe_uint32_operations) {
708  does_deopt = !instr->CheckFlag(HInstruction::kUint32);
709  } else {
710  // Shift operations can only deoptimize if we do a logical shift
711  // by 0 and the result cannot be truncated to int32.
712  bool may_deopt = (op == Token::SHR && constant_value == 0);
713  if (may_deopt) {
714  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
715  if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
716  does_deopt = true;
717  break;
718  }
719  }
720  }
721  }
722 
723  LInstruction* result =
724  DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
725  return does_deopt ? AssignEnvironment(result) : result;
726 }
727 
728 
729 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
730  HArithmeticBinaryOperation* instr) {
731  ASSERT(instr->representation().IsDouble());
732  ASSERT(instr->left()->representation().IsDouble());
733  ASSERT(instr->right()->representation().IsDouble());
734  ASSERT(op != Token::MOD);
735  LOperand* left = UseRegisterAtStart(instr->left());
736  LOperand* right = UseRegisterAtStart(instr->right());
737  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
738  return DefineAsRegister(result);
739 }
740 
741 
742 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
743  HArithmeticBinaryOperation* instr) {
744  ASSERT(op == Token::ADD ||
745  op == Token::DIV ||
746  op == Token::MOD ||
747  op == Token::MUL ||
748  op == Token::SUB);
749  HValue* left = instr->left();
750  HValue* right = instr->right();
751  ASSERT(left->representation().IsTagged());
752  ASSERT(right->representation().IsTagged());
753  LOperand* left_operand = UseFixed(left, a1);
754  LOperand* right_operand = UseFixed(right, a0);
755  LArithmeticT* result =
756  new(zone()) LArithmeticT(op, left_operand, right_operand);
757  return MarkAsCall(DefineFixed(result, v0), instr);
758 }
759 
760 
761 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
762  ASSERT(is_building());
763  current_block_ = block;
764  next_block_ = next_block;
765  if (block->IsStartBlock()) {
766  block->UpdateEnvironment(graph_->start_environment());
767  argument_count_ = 0;
768  } else if (block->predecessors()->length() == 1) {
769  // We have a single predecessor => copy environment and outgoing
770  // argument count from the predecessor.
771  ASSERT(block->phis()->length() == 0);
772  HBasicBlock* pred = block->predecessors()->at(0);
773  HEnvironment* last_environment = pred->last_environment();
774  ASSERT(last_environment != NULL);
775  // Only copy the environment, if it is later used again.
776  if (pred->end()->SecondSuccessor() == NULL) {
777  ASSERT(pred->end()->FirstSuccessor() == block);
778  } else {
779  if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
780  pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
781  last_environment = last_environment->Copy();
782  }
783  }
784  block->UpdateEnvironment(last_environment);
785  ASSERT(pred->argument_count() >= 0);
786  argument_count_ = pred->argument_count();
787  } else {
788  // We are at a state join => process phis.
789  HBasicBlock* pred = block->predecessors()->at(0);
790  // No need to copy the environment, it cannot be used later.
791  HEnvironment* last_environment = pred->last_environment();
792  for (int i = 0; i < block->phis()->length(); ++i) {
793  HPhi* phi = block->phis()->at(i);
794  last_environment->SetValueAt(phi->merged_index(), phi);
795  }
796  for (int i = 0; i < block->deleted_phis()->length(); ++i) {
797  last_environment->SetValueAt(block->deleted_phis()->at(i),
798  graph_->GetConstantUndefined());
799  }
800  block->UpdateEnvironment(last_environment);
801  // Pick up the outgoing argument count of one of the predecessors.
802  argument_count_ = pred->argument_count();
803  }
804  HInstruction* current = block->first();
805  int start = chunk_->instructions()->length();
806  while (current != NULL && !is_aborted()) {
807  // Code for constants in registers is generated lazily.
808  if (!current->EmitAtUses()) {
809  VisitInstruction(current);
810  }
811  current = current->next();
812  }
813  int end = chunk_->instructions()->length() - 1;
814  if (end >= start) {
815  block->set_first_instruction_index(start);
816  block->set_last_instruction_index(end);
817  }
818  block->set_argument_count(argument_count_);
819  next_block_ = NULL;
820  current_block_ = NULL;
821 }
822 
823 
824 void LChunkBuilder::VisitInstruction(HInstruction* current) {
825  HInstruction* old_current = current_instruction_;
826  current_instruction_ = current;
827  if (current->has_position()) position_ = current->position();
828  LInstruction* instr = current->CompileToLithium(this);
829 
830  if (instr != NULL) {
831  if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
832  instr = AssignPointerMap(instr);
833  }
834  if (FLAG_stress_environments && !instr->HasEnvironment()) {
835  instr = AssignEnvironment(instr);
836  }
837  instr->set_hydrogen_value(current);
838  chunk_->AddInstruction(instr, current_block_);
839  }
840  current_instruction_ = old_current;
841 }
842 
843 
844 LEnvironment* LChunkBuilder::CreateEnvironment(
845  HEnvironment* hydrogen_env,
846  int* argument_index_accumulator) {
847  if (hydrogen_env == NULL) return NULL;
848 
849  LEnvironment* outer =
850  CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
851  BailoutId ast_id = hydrogen_env->ast_id();
852  ASSERT(!ast_id.IsNone() ||
853  hydrogen_env->frame_type() != JS_FUNCTION);
854  int value_count = hydrogen_env->length();
855  LEnvironment* result = new(zone()) LEnvironment(
856  hydrogen_env->closure(),
857  hydrogen_env->frame_type(),
858  ast_id,
859  hydrogen_env->parameter_count(),
860  argument_count_,
861  value_count,
862  outer,
863  hydrogen_env->entry(),
864  zone());
865  int argument_index = *argument_index_accumulator;
866  for (int i = 0; i < value_count; ++i) {
867  if (hydrogen_env->is_special_index(i)) continue;
868 
869  HValue* value = hydrogen_env->values()->at(i);
870  LOperand* op = NULL;
871  if (value->IsArgumentsObject()) {
872  op = NULL;
873  } else if (value->IsPushArgument()) {
874  op = new(zone()) LArgument(argument_index++);
875  } else {
876  op = UseAny(value);
877  }
878  result->AddValue(op,
879  value->representation(),
880  value->CheckFlag(HInstruction::kUint32));
881  }
882 
883  if (hydrogen_env->frame_type() == JS_FUNCTION) {
884  *argument_index_accumulator = argument_index;
885  }
886 
887  return result;
888 }
889 
890 
891 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
892  return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
893 }
894 
895 
896 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
897  HValue* value = instr->value();
898  if (value->EmitAtUses()) {
899  HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
900  ? instr->FirstSuccessor()
901  : instr->SecondSuccessor();
902  return new(zone()) LGoto(successor->block_id());
903  }
904 
905  LBranch* result = new(zone()) LBranch(UseRegister(value));
906  // Tagged values that are not known smis or booleans require a
907  // deoptimization environment.
908  Representation rep = value->representation();
909  HType type = value->type();
910  if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
911  return AssignEnvironment(result);
912  }
913  return result;
914 }
915 
916 
917 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
918  ASSERT(instr->value()->representation().IsTagged());
919  LOperand* value = UseRegisterAtStart(instr->value());
920  LOperand* temp = TempRegister();
921  return new(zone()) LCmpMapAndBranch(value, temp);
922 }
923 
924 
925 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
926  return DefineAsRegister(
927  new(zone()) LArgumentsLength(UseRegister(length->value())));
928 }
929 
930 
931 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
932  return DefineAsRegister(new(zone()) LArgumentsElements);
933 }
934 
935 
936 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
937  LInstanceOf* result =
938  new(zone()) LInstanceOf(UseFixed(instr->left(), a0),
939  UseFixed(instr->right(), a1));
940  return MarkAsCall(DefineFixed(result, v0), instr);
941 }
942 
943 
944 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
945  HInstanceOfKnownGlobal* instr) {
946  LInstanceOfKnownGlobal* result =
947  new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0),
948  FixedTemp(t0));
949  return MarkAsCall(DefineFixed(result, v0), instr);
950 }
951 
952 
953 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
954  LOperand* receiver = UseRegisterAtStart(instr->receiver());
955  LOperand* function = UseRegisterAtStart(instr->function());
956  LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
957  return AssignEnvironment(DefineSameAsFirst(result));
958 }
959 
960 
961 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
962  LOperand* function = UseFixed(instr->function(), a1);
963  LOperand* receiver = UseFixed(instr->receiver(), a0);
964  LOperand* length = UseFixed(instr->length(), a2);
965  LOperand* elements = UseFixed(instr->elements(), a3);
966  LApplyArguments* result = new(zone()) LApplyArguments(function,
967  receiver,
968  length,
969  elements);
970  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
971 }
972 
973 
974 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
975  ++argument_count_;
976  LOperand* argument = Use(instr->argument());
977  return new(zone()) LPushArgument(argument);
978 }
979 
980 
981 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
982  return instr->HasNoUses()
983  ? NULL
984  : DefineAsRegister(new(zone()) LThisFunction);
985 }
986 
987 
988 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
989  return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
990 }
991 
992 
993 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
994  LOperand* context = UseRegisterAtStart(instr->value());
995  return DefineAsRegister(new(zone()) LOuterContext(context));
996 }
997 
998 
999 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1000  return MarkAsCall(new(zone()) LDeclareGlobals, instr);
1001 }
1002 
1003 
1004 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1005  LOperand* context = UseRegisterAtStart(instr->value());
1006  return DefineAsRegister(new(zone()) LGlobalObject(context));
1007 }
1008 
1009 
1010 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1011  LOperand* global_object = UseRegisterAtStart(instr->value());
1012  return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1013 }
1014 
1015 
1016 LInstruction* LChunkBuilder::DoCallConstantFunction(
1017  HCallConstantFunction* instr) {
1018  argument_count_ -= instr->argument_count();
1019  return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, v0), instr);
1020 }
1021 
1022 
1023 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1024  LOperand* function = UseFixed(instr->function(), a1);
1025  argument_count_ -= instr->argument_count();
1026  LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1027  return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1028 }
1029 
1030 
1031 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1032  BuiltinFunctionId op = instr->op();
1033  if (op == kMathLog || op == kMathSin || op == kMathCos || op == kMathTan) {
1034  LOperand* input = UseFixedDouble(instr->value(), f4);
1035  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, NULL);
1036  return MarkAsCall(DefineFixedDouble(result, f4), instr);
1037  } else if (op == kMathPowHalf) {
1038  // Input cannot be the same as the result.
1039  // See lithium-codegen-mips.cc::DoMathPowHalf.
1040  LOperand* input = UseFixedDouble(instr->value(), f8);
1041  LOperand* temp = FixedTemp(f6);
1042  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1043  return DefineFixedDouble(result, f4);
1044  } else {
1045  LOperand* input = UseRegisterAtStart(instr->value());
1046  LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1047  LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
1048  switch (op) {
1049  case kMathAbs:
1050  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1051  case kMathFloor:
1052  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1053  case kMathSqrt:
1054  return DefineAsRegister(result);
1055  case kMathRound:
1056  return AssignEnvironment(DefineAsRegister(result));
1057  default:
1058  UNREACHABLE();
1059  return NULL;
1060  }
1061  }
1062 }
1063 
1064 
1065 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1066  ASSERT(instr->key()->representation().IsTagged());
1067  argument_count_ -= instr->argument_count();
1068  LOperand* key = UseFixed(instr->key(), a2);
1069  return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), v0), instr);
1070 }
1071 
1072 
1073 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1074  argument_count_ -= instr->argument_count();
1075  return MarkAsCall(DefineFixed(new(zone()) LCallNamed, v0), instr);
1076 }
1077 
1078 
1079 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1080  argument_count_ -= instr->argument_count();
1081  return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr);
1082 }
1083 
1084 
1085 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1086  argument_count_ -= instr->argument_count();
1087  return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr);
1088 }
1089 
1090 
1091 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1092  LOperand* constructor = UseFixed(instr->constructor(), a1);
1093  argument_count_ -= instr->argument_count();
1094  LCallNew* result = new(zone()) LCallNew(constructor);
1095  return MarkAsCall(DefineFixed(result, v0), instr);
1096 }
1097 
1098 
1099 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1100  LOperand* function = UseFixed(instr->function(), a1);
1101  argument_count_ -= instr->argument_count();
1102  return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), v0),
1103  instr);
1104 }
1105 
1106 
1107 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1108  argument_count_ -= instr->argument_count();
1109  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, v0), instr);
1110 }
1111 
1112 
1113 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1114  return DoShift(Token::SHR, instr);
1115 }
1116 
1117 
1118 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1119  return DoShift(Token::SAR, instr);
1120 }
1121 
1122 
1123 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1124  return DoShift(Token::SHL, instr);
1125 }
1126 
1127 
1128 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1129  if (instr->representation().IsInteger32()) {
1130  ASSERT(instr->left()->representation().IsInteger32());
1131  ASSERT(instr->right()->representation().IsInteger32());
1132 
1133  LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1134  LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1135  return DefineAsRegister(new(zone()) LBitI(left, right));
1136  } else {
1137  ASSERT(instr->representation().IsTagged());
1138  ASSERT(instr->left()->representation().IsTagged());
1139  ASSERT(instr->right()->representation().IsTagged());
1140 
1141  LOperand* left = UseFixed(instr->left(), a1);
1142  LOperand* right = UseFixed(instr->right(), a0);
1143  LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1144  return MarkAsCall(DefineFixed(result, v0), instr);
1145  }
1146 }
1147 
1148 
1149 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1150  ASSERT(instr->value()->representation().IsInteger32());
1151  ASSERT(instr->representation().IsInteger32());
1152  if (instr->HasNoUses()) return NULL;
1153  LOperand* value = UseRegisterAtStart(instr->value());
1154  return DefineAsRegister(new(zone()) LBitNotI(value));
1155 }
1156 
1157 
1158 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1159  if (instr->representation().IsDouble()) {
1160  return DoArithmeticD(Token::DIV, instr);
1161  } else if (instr->representation().IsInteger32()) {
1162  // TODO(1042) The fixed register allocation
1163  // is needed because we call TypeRecordingBinaryOpStub from
1164  // the generated code, which requires registers a0
1165  // and a1 to be used. We should remove that
1166  // when we provide a native implementation.
1167  LOperand* dividend = UseFixed(instr->left(), a0);
1168  LOperand* divisor = UseFixed(instr->right(), a1);
1169  return AssignEnvironment(AssignPointerMap(
1170  DefineFixed(new(zone()) LDivI(dividend, divisor), v0)));
1171  } else {
1172  return DoArithmeticT(Token::DIV, instr);
1173  }
1174 }
1175 
1176 
1177 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1178  UNIMPLEMENTED();
1179  return NULL;
1180 }
1181 
1182 
1183 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1184  if (instr->representation().IsInteger32()) {
1185  ASSERT(instr->left()->representation().IsInteger32());
1186  ASSERT(instr->right()->representation().IsInteger32());
1187 
1188  LModI* mod;
1189  if (instr->HasPowerOf2Divisor()) {
1190  ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1191  LOperand* value = UseRegisterAtStart(instr->left());
1192  mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
1193  } else {
1194  LOperand* dividend = UseRegister(instr->left());
1195  LOperand* divisor = UseRegister(instr->right());
1196  mod = new(zone()) LModI(dividend,
1197  divisor,
1198  TempRegister(),
1199  FixedTemp(f20),
1200  FixedTemp(f22));
1201  }
1202 
1203  if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1204  instr->CheckFlag(HValue::kCanBeDivByZero)) {
1205  return AssignEnvironment(DefineAsRegister(mod));
1206  } else {
1207  return DefineAsRegister(mod);
1208  }
1209  } else if (instr->representation().IsTagged()) {
1210  return DoArithmeticT(Token::MOD, instr);
1211  } else {
1212  ASSERT(instr->representation().IsDouble());
1213  // We call a C function for double modulo. It can't trigger a GC.
1214  // We need to use fixed result register for the call.
1215  // TODO(fschneider): Allow any register as input registers.
1216  LOperand* left = UseFixedDouble(instr->left(), f2);
1217  LOperand* right = UseFixedDouble(instr->right(), f4);
1218  LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
1219  return MarkAsCall(DefineFixedDouble(result, f2), instr);
1220  }
1221 }
1222 
1223 
1224 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1225  if (instr->representation().IsInteger32()) {
1226  ASSERT(instr->left()->representation().IsInteger32());
1227  ASSERT(instr->right()->representation().IsInteger32());
1228  LOperand* left;
1229  LOperand* right = UseOrConstant(instr->MostConstantOperand());
1230  LOperand* temp = NULL;
1231  if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1232  (instr->CheckFlag(HValue::kCanOverflow) ||
1233  !right->IsConstantOperand())) {
1234  left = UseRegister(instr->LeastConstantOperand());
1235  temp = TempRegister();
1236  } else {
1237  left = UseRegisterAtStart(instr->LeastConstantOperand());
1238  }
1239  LMulI* mul = new(zone()) LMulI(left, right, temp);
1240  if (instr->CheckFlag(HValue::kCanOverflow) ||
1241  instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1242  AssignEnvironment(mul);
1243  }
1244  return DefineAsRegister(mul);
1245 
1246  } else if (instr->representation().IsDouble()) {
1247  return DoArithmeticD(Token::MUL, instr);
1248 
1249  } else {
1250  return DoArithmeticT(Token::MUL, instr);
1251  }
1252 }
1253 
1254 
1255 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1256  if (instr->representation().IsInteger32()) {
1257  ASSERT(instr->left()->representation().IsInteger32());
1258  ASSERT(instr->right()->representation().IsInteger32());
1259  LOperand* left = UseRegisterAtStart(instr->left());
1260  LOperand* right = UseOrConstantAtStart(instr->right());
1261  LSubI* sub = new(zone()) LSubI(left, right);
1262  LInstruction* result = DefineAsRegister(sub);
1263  if (instr->CheckFlag(HValue::kCanOverflow)) {
1264  result = AssignEnvironment(result);
1265  }
1266  return result;
1267  } else if (instr->representation().IsDouble()) {
1268  return DoArithmeticD(Token::SUB, instr);
1269  } else {
1270  return DoArithmeticT(Token::SUB, instr);
1271  }
1272 }
1273 
1274 
1275 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1276  if (instr->representation().IsInteger32()) {
1277  ASSERT(instr->left()->representation().IsInteger32());
1278  ASSERT(instr->right()->representation().IsInteger32());
1279  LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1280  LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1281  LAddI* add = new(zone()) LAddI(left, right);
1282  LInstruction* result = DefineAsRegister(add);
1283  if (instr->CheckFlag(HValue::kCanOverflow)) {
1284  result = AssignEnvironment(result);
1285  }
1286  return result;
1287  } else if (instr->representation().IsDouble()) {
1288  return DoArithmeticD(Token::ADD, instr);
1289  } else {
1290  ASSERT(instr->representation().IsTagged());
1291  return DoArithmeticT(Token::ADD, instr);
1292  }
1293 }
1294 
1295 
1296 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1297  LOperand* left = NULL;
1298  LOperand* right = NULL;
1299  if (instr->representation().IsInteger32()) {
1300  ASSERT(instr->left()->representation().IsInteger32());
1301  ASSERT(instr->right()->representation().IsInteger32());
1302  left = UseRegisterAtStart(instr->LeastConstantOperand());
1303  right = UseOrConstantAtStart(instr->MostConstantOperand());
1304  } else {
1305  ASSERT(instr->representation().IsDouble());
1306  ASSERT(instr->left()->representation().IsDouble());
1307  ASSERT(instr->right()->representation().IsDouble());
1308  left = UseRegisterAtStart(instr->left());
1309  right = UseRegisterAtStart(instr->right());
1310  }
1311  return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1312 }
1313 
1314 
1315 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1316  ASSERT(instr->representation().IsDouble());
1317  // We call a C function for double power. It can't trigger a GC.
1318  // We need to use fixed result register for the call.
1319  Representation exponent_type = instr->right()->representation();
1320  ASSERT(instr->left()->representation().IsDouble());
1321  LOperand* left = UseFixedDouble(instr->left(), f2);
1322  LOperand* right = exponent_type.IsDouble() ?
1323  UseFixedDouble(instr->right(), f4) :
1324  UseFixed(instr->right(), a2);
1325  LPower* result = new(zone()) LPower(left, right);
1326  return MarkAsCall(DefineFixedDouble(result, f0),
1327  instr,
1328  CAN_DEOPTIMIZE_EAGERLY);
1329 }
1330 
1331 
1332 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1333  ASSERT(instr->representation().IsDouble());
1334  ASSERT(instr->global_object()->representation().IsTagged());
1335  LOperand* global_object = UseFixed(instr->global_object(), a0);
1336  LRandom* result = new(zone()) LRandom(global_object);
1337  return MarkAsCall(DefineFixedDouble(result, f0), instr);
1338 }
1339 
1340 
1341 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1342  ASSERT(instr->left()->representation().IsTagged());
1343  ASSERT(instr->right()->representation().IsTagged());
1344  LOperand* left = UseFixed(instr->left(), a1);
1345  LOperand* right = UseFixed(instr->right(), a0);
1346  LCmpT* result = new(zone()) LCmpT(left, right);
1347  return MarkAsCall(DefineFixed(result, v0), instr);
1348 }
1349 
1350 
1351 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1352  HCompareIDAndBranch* instr) {
1353  Representation r = instr->GetInputRepresentation();
1354  if (r.IsInteger32()) {
1355  ASSERT(instr->left()->representation().IsInteger32());
1356  ASSERT(instr->right()->representation().IsInteger32());
1357  LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1358  LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1359  return new(zone()) LCmpIDAndBranch(left, right);
1360  } else {
1361  ASSERT(r.IsDouble());
1362  ASSERT(instr->left()->representation().IsDouble());
1363  ASSERT(instr->right()->representation().IsDouble());
1364  LOperand* left = UseRegisterAtStart(instr->left());
1365  LOperand* right = UseRegisterAtStart(instr->right());
1366  return new(zone()) LCmpIDAndBranch(left, right);
1367  }
1368 }
1369 
1370 
1371 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1372  HCompareObjectEqAndBranch* instr) {
1373  LOperand* left = UseRegisterAtStart(instr->left());
1374  LOperand* right = UseRegisterAtStart(instr->right());
1375  return new(zone()) LCmpObjectEqAndBranch(left, right);
1376 }
1377 
1378 
1379 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1380  HCompareConstantEqAndBranch* instr) {
1381  return new(zone()) LCmpConstantEqAndBranch(
1382  UseRegisterAtStart(instr->value()));
1383 }
1384 
1385 
1386 LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
1387  ASSERT(instr->value()->representation().IsTagged());
1388  return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()));
1389 }
1390 
1391 
1392 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1393  ASSERT(instr->value()->representation().IsTagged());
1394  LOperand* temp = TempRegister();
1395  return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
1396  temp);
1397 }
1398 
1399 
1400 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1401  ASSERT(instr->value()->representation().IsTagged());
1402  LOperand* temp = TempRegister();
1403  return new(zone()) LIsStringAndBranch(UseRegisterAtStart(instr->value()),
1404  temp);
1405 }
1406 
1407 
1408 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1409  ASSERT(instr->value()->representation().IsTagged());
1410  return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1411 }
1412 
1413 
1414 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1415  HIsUndetectableAndBranch* instr) {
1416  ASSERT(instr->value()->representation().IsTagged());
1417  return new(zone()) LIsUndetectableAndBranch(
1418  UseRegisterAtStart(instr->value()), TempRegister());
1419 }
1420 
1421 
1422 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1423  HStringCompareAndBranch* instr) {
1424  ASSERT(instr->left()->representation().IsTagged());
1425  ASSERT(instr->right()->representation().IsTagged());
1426  LOperand* left = UseFixed(instr->left(), a1);
1427  LOperand* right = UseFixed(instr->right(), a0);
1428  LStringCompareAndBranch* result =
1429  new(zone()) LStringCompareAndBranch(left, right);
1430  return MarkAsCall(result, instr);
1431 }
1432 
1433 
1434 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1435  HHasInstanceTypeAndBranch* instr) {
1436  ASSERT(instr->value()->representation().IsTagged());
1437  LOperand* value = UseRegisterAtStart(instr->value());
1438  return new(zone()) LHasInstanceTypeAndBranch(value);
1439 }
1440 
1441 
1442 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1443  HGetCachedArrayIndex* instr) {
1444  ASSERT(instr->value()->representation().IsTagged());
1445  LOperand* value = UseRegisterAtStart(instr->value());
1446 
1447  return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1448 }
1449 
1450 
1451 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1452  HHasCachedArrayIndexAndBranch* instr) {
1453  ASSERT(instr->value()->representation().IsTagged());
1454  return new(zone()) LHasCachedArrayIndexAndBranch(
1455  UseRegisterAtStart(instr->value()));
1456 }
1457 
1458 
1459 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1460  HClassOfTestAndBranch* instr) {
1461  ASSERT(instr->value()->representation().IsTagged());
1462  return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1463  TempRegister());
1464 }
1465 
1466 
1467 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1468  LOperand* array = UseRegisterAtStart(instr->value());
1469  return DefineAsRegister(new(zone()) LJSArrayLength(array));
1470 }
1471 
1472 
1473 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1474  HFixedArrayBaseLength* instr) {
1475  LOperand* array = UseRegisterAtStart(instr->value());
1476  return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
1477 }
1478 
1479 
1480 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1481  LOperand* map = UseRegisterAtStart(instr->value());
1482  return DefineAsRegister(new(zone()) LMapEnumLength(map));
1483 }
1484 
1485 
1486 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1487  LOperand* object = UseRegisterAtStart(instr->value());
1488  return DefineAsRegister(new(zone()) LElementsKind(object));
1489 }
1490 
1491 
1492 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1493  LOperand* object = UseRegister(instr->value());
1494  LValueOf* result = new(zone()) LValueOf(object, TempRegister());
1495  return DefineAsRegister(result);
1496 }
1497 
1498 
1499 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1500  LOperand* object = UseFixed(instr->value(), a0);
1501  LDateField* result =
1502  new(zone()) LDateField(object, FixedTemp(a1), instr->index());
1503  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
1504 }
1505 
1506 
1507 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1508  LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1509  LOperand* length = UseRegister(instr->length());
1510  return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
1511 }
1512 
1513 
1514 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1515  // The control instruction marking the end of a block that completed
1516  // abruptly (e.g., threw an exception). There is nothing specific to do.
1517  return NULL;
1518 }
1519 
1520 
1521 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1522  LOperand* value = UseFixed(instr->value(), a0);
1523  return MarkAsCall(new(zone()) LThrow(value), instr);
1524 }
1525 
1526 
1527 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1528  return NULL;
1529 }
1530 
1531 
1532 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1533  // All HForceRepresentation instructions should be eliminated in the
1534  // representation change phase of Hydrogen.
1535  UNREACHABLE();
1536  return NULL;
1537 }
1538 
1539 
1540 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1541  Representation from = instr->from();
1542  Representation to = instr->to();
1543  if (from.IsTagged()) {
1544  if (to.IsDouble()) {
1545  LOperand* value = UseRegister(instr->value());
1546  LNumberUntagD* res = new(zone()) LNumberUntagD(value);
1547  return AssignEnvironment(DefineAsRegister(res));
1548  } else {
1549  ASSERT(to.IsInteger32());
1550  LOperand* value = UseRegisterAtStart(instr->value());
1551  LInstruction* res = NULL;
1552  if (instr->value()->type().IsSmi()) {
1553  res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
1554  } else {
1555  LOperand* temp1 = TempRegister();
1556  LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1557  : NULL;
1558  LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(f22)
1559  : NULL;
1560  res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
1561  temp1,
1562  temp2,
1563  temp3));
1564  res = AssignEnvironment(res);
1565  }
1566  return res;
1567  }
1568  } else if (from.IsDouble()) {
1569  if (to.IsTagged()) {
1570  LOperand* value = UseRegister(instr->value());
1571  LOperand* temp1 = TempRegister();
1572  LOperand* temp2 = TempRegister();
1573 
1574  // Make sure that the temp and result_temp registers are
1575  // different.
1576  LUnallocated* result_temp = TempRegister();
1577  LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
1578  Define(result, result_temp);
1579  return AssignPointerMap(result);
1580  } else {
1581  ASSERT(to.IsInteger32());
1582  LOperand* value = UseRegister(instr->value());
1583  LOperand* temp1 = TempRegister();
1584  LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1585  LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
1586  return AssignEnvironment(DefineAsRegister(res));
1587  }
1588  } else if (from.IsInteger32()) {
1589  if (to.IsTagged()) {
1590  HValue* val = instr->value();
1591  LOperand* value = UseRegisterAtStart(val);
1592  if (val->CheckFlag(HInstruction::kUint32)) {
1593  LNumberTagU* result = new(zone()) LNumberTagU(value);
1594  return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1595  } else if (val->HasRange() && val->range()->IsInSmiRange()) {
1596  return DefineAsRegister(new(zone()) LSmiTag(value));
1597  } else {
1598  LNumberTagI* result = new(zone()) LNumberTagI(value);
1599  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1600  }
1601  } else {
1602  ASSERT(to.IsDouble());
1603  if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1604  return DefineAsRegister(
1605  new(zone()) LUint32ToDouble(UseRegister(instr->value())));
1606  } else {
1607  return DefineAsRegister(
1608  new(zone()) LInteger32ToDouble(Use(instr->value())));
1609  }
1610  }
1611  }
1612  UNREACHABLE();
1613  return NULL;
1614 }
1615 
1616 
1617 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1618  LOperand* value = UseRegisterAtStart(instr->value());
1619  return AssignEnvironment(new(zone()) LCheckNonSmi(value));
1620 }
1621 
1622 
1623 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1624  LOperand* value = UseRegisterAtStart(instr->value());
1625  LInstruction* result = new(zone()) LCheckInstanceType(value);
1626  return AssignEnvironment(result);
1627 }
1628 
1629 
1630 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1631  LOperand* temp1 = TempRegister();
1632  LOperand* temp2 = TempRegister();
1633  LInstruction* result = new(zone()) LCheckPrototypeMaps(temp1, temp2);
1634  return AssignEnvironment(result);
1635 }
1636 
1637 
1638 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1639  LOperand* value = UseRegisterAtStart(instr->value());
1640  return AssignEnvironment(new(zone()) LCheckSmi(value));
1641 }
1642 
1643 
1644 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1645  LOperand* value = UseRegisterAtStart(instr->value());
1646  return AssignEnvironment(new(zone()) LCheckFunction(value));
1647 }
1648 
1649 
1650 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1651  LOperand* value = UseRegisterAtStart(instr->value());
1652  LInstruction* result = new(zone()) LCheckMaps(value);
1653  return AssignEnvironment(result);
1654 }
1655 
1656 
1657 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1658  HValue* value = instr->value();
1659  Representation input_rep = value->representation();
1660  LOperand* reg = UseRegister(value);
1661  if (input_rep.IsDouble()) {
1662  // Revisit this decision, here and 8 lines below.
1663  return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(f22)));
1664  } else if (input_rep.IsInteger32()) {
1665  return DefineAsRegister(new(zone()) LClampIToUint8(reg));
1666  } else {
1667  ASSERT(input_rep.IsTagged());
1668  // Register allocator doesn't (yet) support allocation of double
1669  // temps. Reserve f22 explicitly.
1670  LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22));
1671  return AssignEnvironment(DefineAsRegister(result));
1672  }
1673 }
1674 
1675 
1676 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1677  return new(zone()) LReturn(UseFixed(instr->value(), v0));
1678 }
1679 
1680 
1681 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1682  Representation r = instr->representation();
1683  if (r.IsInteger32()) {
1684  return DefineAsRegister(new(zone()) LConstantI);
1685  } else if (r.IsDouble()) {
1686  return DefineAsRegister(new(zone()) LConstantD);
1687  } else if (r.IsTagged()) {
1688  return DefineAsRegister(new(zone()) LConstantT);
1689  } else {
1690  UNREACHABLE();
1691  return NULL;
1692  }
1693 }
1694 
1695 
1696 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1697  LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
1698  return instr->RequiresHoleCheck()
1699  ? AssignEnvironment(DefineAsRegister(result))
1700  : DefineAsRegister(result);
1701 }
1702 
1703 
1704 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1705  LOperand* global_object = UseFixed(instr->global_object(), a0);
1706  LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
1707  return MarkAsCall(DefineFixed(result, v0), instr);
1708 }
1709 
1710 
1711 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1712  LOperand* value = UseRegister(instr->value());
1713  // Use a temp to check the value in the cell in the case where we perform
1714  // a hole check.
1715  return instr->RequiresHoleCheck()
1716  ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
1717  : new(zone()) LStoreGlobalCell(value, NULL);
1718 }
1719 
1720 
1721 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1722  LOperand* global_object = UseFixed(instr->global_object(), a1);
1723  LOperand* value = UseFixed(instr->value(), a0);
1724  LStoreGlobalGeneric* result =
1725  new(zone()) LStoreGlobalGeneric(global_object, value);
1726  return MarkAsCall(result, instr);
1727 }
1728 
1729 
1730 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1731  LOperand* context = UseRegisterAtStart(instr->value());
1732  LInstruction* result =
1733  DefineAsRegister(new(zone()) LLoadContextSlot(context));
1734  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1735 }
1736 
1737 
1738 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1739  LOperand* context;
1740  LOperand* value;
1741  if (instr->NeedsWriteBarrier()) {
1742  context = UseTempRegister(instr->context());
1743  value = UseTempRegister(instr->value());
1744  } else {
1745  context = UseRegister(instr->context());
1746  value = UseRegister(instr->value());
1747  }
1748  LInstruction* result = new(zone()) LStoreContextSlot(context, value);
1749  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1750 }
1751 
1752 
1753 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1754  return DefineAsRegister(
1755  new(zone()) LLoadNamedField(UseRegisterAtStart(instr->object())));
1756 }
1757 
1758 
1759 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1760  HLoadNamedFieldPolymorphic* instr) {
1761  ASSERT(instr->representation().IsTagged());
1762  if (instr->need_generic()) {
1763  LOperand* obj = UseFixed(instr->object(), a0);
1764  LLoadNamedFieldPolymorphic* result =
1765  new(zone()) LLoadNamedFieldPolymorphic(obj);
1766  return MarkAsCall(DefineFixed(result, v0), instr);
1767  } else {
1768  LOperand* obj = UseRegisterAtStart(instr->object());
1769  LLoadNamedFieldPolymorphic* result =
1770  new(zone()) LLoadNamedFieldPolymorphic(obj);
1771  return AssignEnvironment(DefineAsRegister(result));
1772  }
1773 }
1774 
1775 
1776 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1777  LOperand* object = UseFixed(instr->object(), a0);
1778  LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0);
1779  return MarkAsCall(result, instr);
1780 }
1781 
1782 
1783 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1784  HLoadFunctionPrototype* instr) {
1785  return AssignEnvironment(DefineAsRegister(
1786  new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1787 }
1788 
1789 
1790 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1791  LOperand* input = UseRegisterAtStart(instr->value());
1792  return DefineAsRegister(new(zone()) LLoadElements(input));
1793 }
1794 
1795 
1796 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1797  HLoadExternalArrayPointer* instr) {
1798  LOperand* input = UseRegisterAtStart(instr->value());
1799  return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
1800 }
1801 
1802 
1803 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1804  HLoadKeyedFastElement* instr) {
1805  ASSERT(instr->representation().IsTagged());
1806  ASSERT(instr->key()->representation().IsInteger32() ||
1807  instr->key()->representation().IsTagged());
1808  LOperand* obj = UseRegisterAtStart(instr->object());
1809  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1810  LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
1811  if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1812  return DefineAsRegister(result);
1813 }
1814 
1815 
1816 LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1817  HLoadKeyedFastDoubleElement* instr) {
1818  ASSERT(instr->representation().IsDouble());
1819  ASSERT(instr->key()->representation().IsInteger32() ||
1820  instr->key()->representation().IsTagged());
1821  LOperand* elements = UseTempRegister(instr->elements());
1822  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1823  LLoadKeyedFastDoubleElement* result =
1824  new(zone()) LLoadKeyedFastDoubleElement(elements, key);
1825  return AssignEnvironment(DefineAsRegister(result));
1826 }
1827 
1828 
1829 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1830  HLoadKeyedSpecializedArrayElement* instr) {
1831  ElementsKind elements_kind = instr->elements_kind();
1832  ASSERT(
1833  (instr->representation().IsInteger32() &&
1834  (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1835  (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1836  (instr->representation().IsDouble() &&
1837  ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1838  (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1839  ASSERT(instr->key()->representation().IsInteger32() ||
1840  instr->key()->representation().IsTagged());
1841  LOperand* external_pointer = UseRegister(instr->external_pointer());
1842  LOperand* key = UseRegisterOrConstant(instr->key());
1843  LLoadKeyedSpecializedArrayElement* result =
1844  new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer, key);
1845  LInstruction* load_instr = DefineAsRegister(result);
1846  // An unsigned int array load might overflow and cause a deopt, make sure it
1847  // has an environment.
1848  return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
1849  AssignEnvironment(load_instr) : load_instr;
1850 }
1851 
1852 
1853 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1854  LOperand* object = UseFixed(instr->object(), a1);
1855  LOperand* key = UseFixed(instr->key(), a0);
1856 
1857  LInstruction* result =
1858  DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0);
1859  return MarkAsCall(result, instr);
1860 }
1861 
1862 
1863 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1864  HStoreKeyedFastElement* instr) {
1865  bool needs_write_barrier = instr->NeedsWriteBarrier();
1866  ASSERT(instr->value()->representation().IsTagged());
1867  ASSERT(instr->object()->representation().IsTagged());
1868  ASSERT(instr->key()->representation().IsInteger32() ||
1869  instr->key()->representation().IsTagged());
1870 
1871  LOperand* obj = UseTempRegister(instr->object());
1872  LOperand* val = needs_write_barrier
1873  ? UseTempRegister(instr->value())
1874  : UseRegisterAtStart(instr->value());
1875  LOperand* key = needs_write_barrier
1876  ? UseTempRegister(instr->key())
1877  : UseRegisterOrConstantAtStart(instr->key());
1878  return new(zone()) LStoreKeyedFastElement(obj, key, val);
1879 }
1880 
1881 
1882 LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1883  HStoreKeyedFastDoubleElement* instr) {
1884  ASSERT(instr->value()->representation().IsDouble());
1885  ASSERT(instr->elements()->representation().IsTagged());
1886  ASSERT(instr->key()->representation().IsInteger32() ||
1887  instr->key()->representation().IsTagged());
1888 
1889  LOperand* elements = UseRegisterAtStart(instr->elements());
1890  LOperand* val = UseTempRegister(instr->value());
1891  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1892 
1893  return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
1894 }
1895 
1896 
1897 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1898  HStoreKeyedSpecializedArrayElement* instr) {
1899  ElementsKind elements_kind = instr->elements_kind();
1900  ASSERT(
1901  (instr->value()->representation().IsInteger32() &&
1902  (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1903  (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1904  (instr->value()->representation().IsDouble() &&
1905  ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1906  (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1907  ASSERT(instr->external_pointer()->representation().IsExternal());
1908  ASSERT(instr->key()->representation().IsInteger32() ||
1909  instr->key()->representation().IsTagged());
1910 
1911  LOperand* external_pointer = UseRegister(instr->external_pointer());
1912  bool val_is_temp_register =
1913  elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
1914  elements_kind == EXTERNAL_FLOAT_ELEMENTS;
1915  LOperand* val = val_is_temp_register
1916  ? UseTempRegister(instr->value())
1917  : UseRegister(instr->value());
1918  LOperand* key = UseRegisterOrConstant(instr->key());
1919 
1920  return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
1921  key,
1922  val);
1923 }
1924 
1925 
1926 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1927  LOperand* obj = UseFixed(instr->object(), a2);
1928  LOperand* key = UseFixed(instr->key(), a1);
1929  LOperand* val = UseFixed(instr->value(), a0);
1930 
1931  ASSERT(instr->object()->representation().IsTagged());
1932  ASSERT(instr->key()->representation().IsTagged());
1933  ASSERT(instr->value()->representation().IsTagged());
1934 
1935  return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr);
1936 }
1937 
1938 
1939 LInstruction* LChunkBuilder::DoTransitionElementsKind(
1940  HTransitionElementsKind* instr) {
1941  ElementsKind from_kind = instr->original_map()->elements_kind();
1942  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
1943  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
1944  LOperand* object = UseRegister(instr->object());
1945  LOperand* new_map_reg = TempRegister();
1946  LTransitionElementsKind* result =
1947  new(zone()) LTransitionElementsKind(object, new_map_reg, NULL);
1948  return DefineSameAsFirst(result);
1949  } else {
1950  LOperand* object = UseFixed(instr->object(), a0);
1951  LOperand* fixed_object_reg = FixedTemp(a2);
1952  LOperand* new_map_reg = FixedTemp(a3);
1953  LTransitionElementsKind* result =
1954  new(zone()) LTransitionElementsKind(object,
1955  new_map_reg,
1956  fixed_object_reg);
1957  return MarkAsCall(DefineFixed(result, v0), instr);
1958  }
1959 }
1960 
1961 
1962 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1963  bool needs_write_barrier = instr->NeedsWriteBarrier();
1964  bool needs_write_barrier_for_map = !instr->transition().is_null() &&
1965  instr->NeedsWriteBarrierForMap();
1966 
1967  LOperand* obj;
1968  if (needs_write_barrier) {
1969  obj = instr->is_in_object()
1970  ? UseRegister(instr->object())
1971  : UseTempRegister(instr->object());
1972  } else {
1973  obj = needs_write_barrier_for_map
1974  ? UseRegister(instr->object())
1975  : UseRegisterAtStart(instr->object());
1976  }
1977 
1978  LOperand* val = needs_write_barrier
1979  ? UseTempRegister(instr->value())
1980  : UseRegister(instr->value());
1981 
1982  // We need a temporary register for write barrier of the map field.
1983  LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
1984 
1985  return new(zone()) LStoreNamedField(obj, val, temp);
1986 }
1987 
1988 
1989 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1990  LOperand* obj = UseFixed(instr->object(), a1);
1991  LOperand* val = UseFixed(instr->value(), a0);
1992 
1993  LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
1994  return MarkAsCall(result, instr);
1995 }
1996 
1997 
1998 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1999  LOperand* left = UseRegisterAtStart(instr->left());
2000  LOperand* right = UseRegisterAtStart(instr->right());
2001  return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), v0),
2002  instr);
2003 }
2004 
2005 
2006 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2007  LOperand* string = UseTempRegister(instr->string());
2008  LOperand* index = UseTempRegister(instr->index());
2009  LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2010  return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2011 }
2012 
2013 
2014 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2015  LOperand* char_code = UseRegister(instr->value());
2016  LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2017  return AssignPointerMap(DefineAsRegister(result));
2018 }
2019 
2020 
2021 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2022  LOperand* string = UseRegisterAtStart(instr->value());
2023  return DefineAsRegister(new(zone()) LStringLength(string));
2024 }
2025 
2026 
2027 LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2028  LAllocateObject* result =
2029  new(zone()) LAllocateObject(TempRegister(), TempRegister());
2030  return AssignPointerMap(DefineAsRegister(result));
2031 }
2032 
2033 
2034 LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2035  return MarkAsCall(DefineFixed(new(zone()) LFastLiteral, v0), instr);
2036 }
2037 
2038 
2039 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2040  return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, v0), instr);
2041 }
2042 
2043 
2044 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2045  return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, v0), instr);
2046 }
2047 
2048 
2049 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2050  return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, v0), instr);
2051 }
2052 
2053 
2054 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2055  return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, v0), instr);
2056 }
2057 
2058 
2059 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
2060  LOperand* object = UseFixed(instr->object(), a0);
2061  LOperand* key = UseFixed(instr->key(), a1);
2062  LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
2063  return MarkAsCall(DefineFixed(result, v0), instr);
2064 }
2065 
2066 
2067 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2068  ASSERT(argument_count_ == 0);
2069  allocator_->MarkAsOsrEntry();
2070  current_block_->last_environment()->set_ast_id(instr->ast_id());
2071  return AssignEnvironment(new(zone()) LOsrEntry);
2072 }
2073 
2074 
2075 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2076  int spill_index = chunk()->GetParameterStackSlot(instr->index());
2077  return DefineAsSpilled(new(zone()) LParameter, spill_index);
2078 }
2079 
2080 
2081 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2082  int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
2083  if (spill_index > LUnallocated::kMaxFixedIndex) {
2084  Abort("Too many spill slots needed for OSR");
2085  spill_index = 0;
2086  }
2087  return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2088 }
2089 
2090 
2091 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2092  argument_count_ -= instr->argument_count();
2093  return MarkAsCall(DefineFixed(new(zone()) LCallStub, v0), instr);
2094 }
2095 
2096 
2097 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2098  // There are no real uses of the arguments object.
2099  // arguments.length and element access are supported directly on
2100  // stack arguments, and any real arguments object use causes a bailout.
2101  // So this value is never used.
2102  return NULL;
2103 }
2104 
2105 
2106 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2107  LOperand* args = UseRegister(instr->arguments());
2108  LOperand* length = UseTempRegister(instr->length());
2109  LOperand* index = UseRegister(instr->index());
2110  return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2111 }
2112 
2113 
2114 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2115  LOperand* object = UseFixed(instr->value(), a0);
2116  LToFastProperties* result = new(zone()) LToFastProperties(object);
2117  return MarkAsCall(DefineFixed(result, v0), instr);
2118 }
2119 
2120 
2121 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2122  LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), a0));
2123  return MarkAsCall(DefineFixed(result, v0), instr);
2124 }
2125 
2126 
2127 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2128  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2129 }
2130 
2131 
2132 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2133  HIsConstructCallAndBranch* instr) {
2134  return new(zone()) LIsConstructCallAndBranch(TempRegister());
2135 }
2136 
2137 
2138 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2139  HEnvironment* env = current_block_->last_environment();
2140  ASSERT(env != NULL);
2141 
2142  env->set_ast_id(instr->ast_id());
2143 
2144  env->Drop(instr->pop_count());
2145  for (int i = 0; i < instr->values()->length(); ++i) {
2146  HValue* value = instr->values()->at(i);
2147  if (instr->HasAssignedIndexAt(i)) {
2148  env->Bind(instr->GetAssignedIndexAt(i), value);
2149  } else {
2150  env->Push(value);
2151  }
2152  }
2153 
2154  // If there is an instruction pending deoptimization environment create a
2155  // lazy bailout instruction to capture the environment.
2156  if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2157  LInstruction* result = new(zone()) LLazyBailout;
2158  result = AssignEnvironment(result);
2159  // Store the lazy deopt environment with the instruction if needed. Right
2160  // now it is only used for LInstanceOfKnownGlobal.
2161  instruction_pending_deoptimization_environment_->
2162  SetDeferredLazyDeoptimizationEnvironment(result->environment());
2163  instruction_pending_deoptimization_environment_ = NULL;
2164  pending_deoptimization_ast_id_ = BailoutId::None();
2165  return result;
2166  }
2167 
2168  return NULL;
2169 }
2170 
2171 
2172 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2173  if (instr->is_function_entry()) {
2174  return MarkAsCall(new(zone()) LStackCheck, instr);
2175  } else {
2176  ASSERT(instr->is_backwards_branch());
2177  return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2178  }
2179 }
2180 
2181 
2182 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2183  HEnvironment* outer = current_block_->last_environment();
2184  HConstant* undefined = graph()->GetConstantUndefined();
2185  HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2186  instr->arguments_count(),
2187  instr->function(),
2188  undefined,
2189  instr->call_kind(),
2190  instr->inlining_kind());
2191  if (instr->arguments_var() != NULL) {
2192  inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2193  }
2194  inner->set_entry(instr);
2195  current_block_->UpdateEnvironment(inner);
2196  chunk_->AddInlinedClosure(instr->closure());
2197  return NULL;
2198 }
2199 
2200 
2201 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2202  LInstruction* pop = NULL;
2203 
2204  HEnvironment* env = current_block_->last_environment();
2205 
2206  if (env->entry()->arguments_pushed()) {
2207  int argument_count = env->arguments_environment()->parameter_count();
2208  pop = new(zone()) LDrop(argument_count);
2209  argument_count_ -= argument_count;
2210  }
2211 
2212  HEnvironment* outer = current_block_->last_environment()->
2213  DiscardInlined(false);
2214  current_block_->UpdateEnvironment(outer);
2215 
2216  return pop;
2217 }
2218 
2219 
2220 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2221  LOperand* key = UseRegisterAtStart(instr->key());
2222  LOperand* object = UseRegisterAtStart(instr->object());
2223  LIn* result = new(zone()) LIn(key, object);
2224  return MarkAsCall(DefineFixed(result, v0), instr);
2225 }
2226 
2227 
2228 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2229  LOperand* object = UseFixed(instr->enumerable(), a0);
2230  LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
2231  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
2232 }
2233 
2234 
2235 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2236  LOperand* map = UseRegister(instr->map());
2237  return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
2238 }
2239 
2240 
2241 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2242  LOperand* value = UseRegisterAtStart(instr->value());
2243  LOperand* map = UseRegisterAtStart(instr->map());
2244  return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2245 }
2246 
2247 
2248 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2249  LOperand* object = UseRegister(instr->object());
2250  LOperand* index = UseRegister(instr->index());
2251  return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2252 }
2253 
2254 
2255 } } // namespace v8::internal
const FPURegister f4
const FPURegister f20
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)
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
const FPURegister f0
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:279
const FPURegister f22
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:226
LLabel(HBasicBlock *block)
Definition: lithium-arm.h:409
Handle< String > name() const
Definition: lithium-arm.h:1686
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
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
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
#define DEFINE_COMPILE(type)
Definition: lithium-mips.cc:37
LLabel * replacement() const
Definition: lithium-arm.h:419
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
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:336
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
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:393
const FPURegister f2
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
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)
#define UNIMPLEMENTED()
Definition: checks.h:48
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
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:195
const FPURegister f6
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
bool IsRedundant() const
Definition: lithium-arm.cc:134
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:319
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 FPURegister f8