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