V8 Project
lithium-x87.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #if V8_TARGET_ARCH_X87
8 
9 #include "src/hydrogen-osr.h"
10 #include "src/lithium-inl.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 #define DEFINE_COMPILE(type) \
17  void L##type::CompileToNative(LCodeGen* generator) { \
18  generator->Do##type(this); \
19  }
21 #undef DEFINE_COMPILE
22 
23 
24 #ifdef DEBUG
25 void LInstruction::VerifyCall() {
26  // Call instructions can use only fixed registers as temporaries and
27  // outputs because all registers are blocked by the calling convention.
28  // Inputs operands must use a fixed register or use-at-start policy or
29  // a non-register policy.
30  DCHECK(Output() == NULL ||
31  LUnallocated::cast(Output())->HasFixedPolicy() ||
32  !LUnallocated::cast(Output())->HasRegisterPolicy());
33  for (UseIterator it(this); !it.Done(); it.Advance()) {
34  LUnallocated* operand = LUnallocated::cast(it.Current());
35  DCHECK(operand->HasFixedPolicy() ||
36  operand->IsUsedAtStart());
37  }
38  for (TempIterator it(this); !it.Done(); it.Advance()) {
39  LUnallocated* operand = LUnallocated::cast(it.Current());
40  DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
41  }
42 }
43 #endif
44 
45 
47  return HasResult() && result()->IsDoubleRegister();
48 }
49 
50 
52  for (int i = 0; i < InputCount(); i++) {
53  LOperand* op = InputAt(i);
54  if (op != NULL && op->IsDoubleRegister()) {
55  return true;
56  }
57  }
58  return false;
59 }
60 
61 
62 bool LInstruction::IsDoubleInput(X87Register reg, LCodeGen* cgen) {
63  for (int i = 0; i < InputCount(); i++) {
64  LOperand* op = InputAt(i);
65  if (op != NULL && op->IsDoubleRegister()) {
66  if (cgen->ToX87Register(op).is(reg)) return true;
67  }
68  }
69  return false;
70 }
71 
72 
73 void LInstruction::PrintTo(StringStream* stream) {
74  stream->Add("%s ", this->Mnemonic());
75 
76  PrintOutputOperandTo(stream);
77 
78  PrintDataTo(stream);
79 
80  if (HasEnvironment()) {
81  stream->Add(" ");
82  environment()->PrintTo(stream);
83  }
84 
85  if (HasPointerMap()) {
86  stream->Add(" ");
87  pointer_map()->PrintTo(stream);
88  }
89 }
90 
91 
92 void LInstruction::PrintDataTo(StringStream* stream) {
93  stream->Add("= ");
94  for (int i = 0; i < InputCount(); i++) {
95  if (i > 0) stream->Add(" ");
96  if (InputAt(i) == NULL) {
97  stream->Add("NULL");
98  } else {
99  InputAt(i)->PrintTo(stream);
100  }
101  }
102 }
103 
104 
105 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
106  if (HasResult()) result()->PrintTo(stream);
107 }
108 
109 
110 void LLabel::PrintDataTo(StringStream* stream) {
111  LGap::PrintDataTo(stream);
112  LLabel* rep = replacement();
113  if (rep != NULL) {
114  stream->Add(" Dead block replaced with B%d", rep->block_id());
115  }
116 }
117 
118 
119 bool LGap::IsRedundant() const {
120  for (int i = 0; i < 4; i++) {
122  return false;
123  }
124  }
125 
126  return true;
127 }
128 
129 
130 void LGap::PrintDataTo(StringStream* stream) {
131  for (int i = 0; i < 4; i++) {
132  stream->Add("(");
133  if (parallel_moves_[i] != NULL) {
134  parallel_moves_[i]->PrintDataTo(stream);
135  }
136  stream->Add(") ");
137  }
138 }
139 
140 
141 const char* LArithmeticD::Mnemonic() const {
142  switch (op()) {
143  case Token::ADD: return "add-d";
144  case Token::SUB: return "sub-d";
145  case Token::MUL: return "mul-d";
146  case Token::DIV: return "div-d";
147  case Token::MOD: return "mod-d";
148  default:
149  UNREACHABLE();
150  return NULL;
151  }
152 }
153 
154 
155 const char* LArithmeticT::Mnemonic() const {
156  switch (op()) {
157  case Token::ADD: return "add-t";
158  case Token::SUB: return "sub-t";
159  case Token::MUL: return "mul-t";
160  case Token::MOD: return "mod-t";
161  case Token::DIV: return "div-t";
162  case Token::BIT_AND: return "bit-and-t";
163  case Token::BIT_OR: return "bit-or-t";
164  case Token::BIT_XOR: return "bit-xor-t";
165  case Token::ROR: return "ror-t";
166  case Token::SHL: return "sal-t";
167  case Token::SAR: return "sar-t";
168  case Token::SHR: return "shr-t";
169  default:
170  UNREACHABLE();
171  return NULL;
172  }
173 }
174 
175 
176 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
177  return !gen->IsNextEmittedBlock(block_id());
178 }
179 
180 
181 void LGoto::PrintDataTo(StringStream* stream) {
182  stream->Add("B%d", block_id());
183 }
184 
185 
186 void LBranch::PrintDataTo(StringStream* stream) {
187  stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
188  value()->PrintTo(stream);
189 }
190 
191 
192 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
193  stream->Add("if ");
194  left()->PrintTo(stream);
195  stream->Add(" %s ", Token::String(op()));
196  right()->PrintTo(stream);
197  stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
198 }
199 
200 
201 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
202  stream->Add("if is_object(");
203  value()->PrintTo(stream);
204  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
205 }
206 
207 
208 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
209  stream->Add("if is_string(");
210  value()->PrintTo(stream);
211  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
212 }
213 
214 
215 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
216  stream->Add("if is_smi(");
217  value()->PrintTo(stream);
218  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
219 }
220 
221 
222 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
223  stream->Add("if is_undetectable(");
224  value()->PrintTo(stream);
225  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
226 }
227 
228 
229 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
230  stream->Add("if string_compare(");
231  left()->PrintTo(stream);
232  right()->PrintTo(stream);
233  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
234 }
235 
236 
237 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
238  stream->Add("if has_instance_type(");
239  value()->PrintTo(stream);
240  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
241 }
242 
243 
244 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
245  stream->Add("if has_cached_array_index(");
246  value()->PrintTo(stream);
247  stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
248 }
249 
250 
251 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
252  stream->Add("if class_of_test(");
253  value()->PrintTo(stream);
254  stream->Add(", \"%o\") then B%d else B%d",
255  *hydrogen()->class_name(),
256  true_block_id(),
257  false_block_id());
258 }
259 
260 
261 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
262  stream->Add("if typeof ");
263  value()->PrintTo(stream);
264  stream->Add(" == \"%s\" then B%d else B%d",
265  hydrogen()->type_literal()->ToCString().get(),
266  true_block_id(), false_block_id());
267 }
268 
269 
270 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
271  stream->Add(" = ");
272  function()->PrintTo(stream);
273  stream->Add(".code_entry = ");
274  code_object()->PrintTo(stream);
275 }
276 
277 
278 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
279  stream->Add(" = ");
280  base_object()->PrintTo(stream);
281  stream->Add(" + ");
282  offset()->PrintTo(stream);
283 }
284 
285 
286 void LCallJSFunction::PrintDataTo(StringStream* stream) {
287  stream->Add("= ");
288  function()->PrintTo(stream);
289  stream->Add("#%d / ", arity());
290 }
291 
292 
293 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
294  for (int i = 0; i < InputCount(); i++) {
295  InputAt(i)->PrintTo(stream);
296  stream->Add(" ");
297  }
298  stream->Add("#%d / ", arity());
299 }
300 
301 
302 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
303  context()->PrintTo(stream);
304  stream->Add("[%d]", slot_index());
305 }
306 
307 
308 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
309  context()->PrintTo(stream);
310  stream->Add("[%d] <- ", slot_index());
311  value()->PrintTo(stream);
312 }
313 
314 
315 void LInvokeFunction::PrintDataTo(StringStream* stream) {
316  stream->Add("= ");
317  context()->PrintTo(stream);
318  stream->Add(" ");
319  function()->PrintTo(stream);
320  stream->Add(" #%d / ", arity());
321 }
322 
323 
324 void LCallNew::PrintDataTo(StringStream* stream) {
325  stream->Add("= ");
326  context()->PrintTo(stream);
327  stream->Add(" ");
328  constructor()->PrintTo(stream);
329  stream->Add(" #%d / ", arity());
330 }
331 
332 
333 void LCallNewArray::PrintDataTo(StringStream* stream) {
334  stream->Add("= ");
335  context()->PrintTo(stream);
336  stream->Add(" ");
337  constructor()->PrintTo(stream);
338  stream->Add(" #%d / ", arity());
339  ElementsKind kind = hydrogen()->elements_kind();
340  stream->Add(" (%s) ", ElementsKindToString(kind));
341 }
342 
343 
344 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
345  arguments()->PrintTo(stream);
346 
347  stream->Add(" length ");
348  length()->PrintTo(stream);
349 
350  stream->Add(" index ");
351  index()->PrintTo(stream);
352 }
353 
354 
355 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
356  // Skip a slot if for a double-width slot.
357  if (kind == DOUBLE_REGISTERS) {
358  spill_slot_count_++;
359  spill_slot_count_ |= 1;
360  num_double_slots_++;
361  }
362  return spill_slot_count_++;
363 }
364 
365 
366 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
367  int index = GetNextSpillIndex(kind);
368  if (kind == DOUBLE_REGISTERS) {
369  return LDoubleStackSlot::Create(index, zone());
370  } else {
371  DCHECK(kind == GENERAL_REGISTERS);
372  return LStackSlot::Create(index, zone());
373  }
374 }
375 
376 
377 void LStoreNamedField::PrintDataTo(StringStream* stream) {
378  object()->PrintTo(stream);
379  OStringStream os;
380  os << hydrogen()->access() << " <- ";
381  stream->Add(os.c_str());
382  value()->PrintTo(stream);
383 }
384 
385 
386 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
387  object()->PrintTo(stream);
388  stream->Add(".");
389  stream->Add(String::cast(*name())->ToCString().get());
390  stream->Add(" <- ");
391  value()->PrintTo(stream);
392 }
393 
394 
395 void LLoadKeyed::PrintDataTo(StringStream* stream) {
396  elements()->PrintTo(stream);
397  stream->Add("[");
398  key()->PrintTo(stream);
399  if (hydrogen()->IsDehoisted()) {
400  stream->Add(" + %d]", base_offset());
401  } else {
402  stream->Add("]");
403  }
404 }
405 
406 
407 void LStoreKeyed::PrintDataTo(StringStream* stream) {
408  elements()->PrintTo(stream);
409  stream->Add("[");
410  key()->PrintTo(stream);
411  if (hydrogen()->IsDehoisted()) {
412  stream->Add(" + %d] <-", base_offset());
413  } else {
414  stream->Add("] <- ");
415  }
416 
417  if (value() == NULL) {
418  DCHECK(hydrogen()->IsConstantHoleStore() &&
419  hydrogen()->value()->representation().IsDouble());
420  stream->Add("<the hole(nan)>");
421  } else {
422  value()->PrintTo(stream);
423  }
424 }
425 
426 
427 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
428  object()->PrintTo(stream);
429  stream->Add("[");
430  key()->PrintTo(stream);
431  stream->Add("] <- ");
432  value()->PrintTo(stream);
433 }
434 
435 
436 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
437  object()->PrintTo(stream);
438  stream->Add(" %p -> %p", *original_map(), *transitioned_map());
439 }
440 
441 
442 LPlatformChunk* LChunkBuilder::Build() {
443  DCHECK(is_unused());
444  chunk_ = new(zone()) LPlatformChunk(info(), graph());
445  LPhase phase("L_Building chunk", chunk_);
446  status_ = BUILDING;
447 
448  // Reserve the first spill slot for the state of dynamic alignment.
449  if (info()->IsOptimizing()) {
450  int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
451  DCHECK_EQ(alignment_state_index, 0);
452  USE(alignment_state_index);
453  }
454 
455  // If compiling for OSR, reserve space for the unoptimized frame,
456  // which will be subsumed into this frame.
457  if (graph()->has_osr()) {
458  for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
459  chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
460  }
461  }
462 
463  const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
464  for (int i = 0; i < blocks->length(); i++) {
465  HBasicBlock* next = NULL;
466  if (i < blocks->length() - 1) next = blocks->at(i + 1);
467  DoBasicBlock(blocks->at(i), next);
468  if (is_aborted()) return NULL;
469  }
470  status_ = DONE;
471  return chunk_;
472 }
473 
474 
475 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
476  return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
478 }
479 
480 
481 LUnallocated* LChunkBuilder::ToUnallocated(X87Register reg) {
482  return new (zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
484 }
485 
486 
487 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
488  return Use(value, ToUnallocated(fixed_register));
489 }
490 
491 
492 LOperand* LChunkBuilder::UseRegister(HValue* value) {
493  return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
494 }
495 
496 
497 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
498  return Use(value,
499  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
501 }
502 
503 
504 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
505  return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
506 }
507 
508 
509 LOperand* LChunkBuilder::Use(HValue* value) {
510  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
511 }
512 
513 
514 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
515  return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
517 }
518 
519 
520 static inline bool CanBeImmediateConstant(HValue* value) {
521  return value->IsConstant() && HConstant::cast(value)->NotInNewSpace();
522 }
523 
524 
525 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
526  return CanBeImmediateConstant(value)
527  ? chunk_->DefineConstantOperand(HConstant::cast(value))
528  : Use(value);
529 }
530 
531 
532 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
533  return CanBeImmediateConstant(value)
534  ? chunk_->DefineConstantOperand(HConstant::cast(value))
535  : UseAtStart(value);
536 }
537 
538 
539 LOperand* LChunkBuilder::UseFixedOrConstant(HValue* value,
540  Register fixed_register) {
541  return CanBeImmediateConstant(value)
542  ? chunk_->DefineConstantOperand(HConstant::cast(value))
543  : UseFixed(value, fixed_register);
544 }
545 
546 
547 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
548  return CanBeImmediateConstant(value)
549  ? chunk_->DefineConstantOperand(HConstant::cast(value))
550  : UseRegister(value);
551 }
552 
553 
554 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
555  return CanBeImmediateConstant(value)
556  ? chunk_->DefineConstantOperand(HConstant::cast(value))
557  : UseRegisterAtStart(value);
558 }
559 
560 
561 LOperand* LChunkBuilder::UseConstant(HValue* value) {
562  return chunk_->DefineConstantOperand(HConstant::cast(value));
563 }
564 
565 
566 LOperand* LChunkBuilder::UseAny(HValue* value) {
567  return value->IsConstant()
568  ? chunk_->DefineConstantOperand(HConstant::cast(value))
569  : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
570 }
571 
572 
573 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
574  if (value->EmitAtUses()) {
575  HInstruction* instr = HInstruction::cast(value);
576  VisitInstruction(instr);
577  }
578  operand->set_virtual_register(value->id());
579  return operand;
580 }
581 
582 
583 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
584  LUnallocated* result) {
585  result->set_virtual_register(current_instruction_->id());
586  instr->set_result(result);
587  return instr;
588 }
589 
590 
591 LInstruction* LChunkBuilder::DefineAsRegister(
592  LTemplateResultInstruction<1>* instr) {
593  return Define(instr,
594  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
595 }
596 
597 
598 LInstruction* LChunkBuilder::DefineAsSpilled(
599  LTemplateResultInstruction<1>* instr,
600  int index) {
601  return Define(instr,
602  new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
603 }
604 
605 
606 LInstruction* LChunkBuilder::DefineSameAsFirst(
607  LTemplateResultInstruction<1>* instr) {
608  return Define(instr,
609  new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
610 }
611 
612 
613 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
614  Register reg) {
615  return Define(instr, ToUnallocated(reg));
616 }
617 
618 
619 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
620  X87Register reg) {
621  return Define(instr, ToUnallocated(reg));
622 }
623 
624 
625 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
626  HEnvironment* hydrogen_env = current_block_->last_environment();
627  int argument_index_accumulator = 0;
628  ZoneList<HValue*> objects_to_materialize(0, zone());
629  instr->set_environment(CreateEnvironment(hydrogen_env,
630  &argument_index_accumulator,
631  &objects_to_materialize));
632  return instr;
633 }
634 
635 
636 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
637  HInstruction* hinstr,
638  CanDeoptimize can_deoptimize) {
639  info()->MarkAsNonDeferredCalling();
640 
641 #ifdef DEBUG
642  instr->VerifyCall();
643 #endif
644  instr->MarkAsCall();
645  instr = AssignPointerMap(instr);
646 
647  // If instruction does not have side-effects lazy deoptimization
648  // after the call will try to deoptimize to the point before the call.
649  // Thus we still need to attach environment to this call even if
650  // call sequence can not deoptimize eagerly.
651  bool needs_environment =
652  (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
653  !hinstr->HasObservableSideEffects();
654  if (needs_environment && !instr->HasEnvironment()) {
655  instr = AssignEnvironment(instr);
656  // We can't really figure out if the environment is needed or not.
657  instr->environment()->set_has_been_used();
658  }
659 
660  return instr;
661 }
662 
663 
664 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
665  DCHECK(!instr->HasPointerMap());
666  instr->set_pointer_map(new(zone()) LPointerMap(zone()));
667  return instr;
668 }
669 
670 
671 LUnallocated* LChunkBuilder::TempRegister() {
672  LUnallocated* operand =
673  new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
674  int vreg = allocator_->GetVirtualRegister();
675  if (!allocator_->AllocationOk()) {
676  Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
677  vreg = 0;
678  }
679  operand->set_virtual_register(vreg);
680  return operand;
681 }
682 
683 
684 LOperand* LChunkBuilder::FixedTemp(Register reg) {
685  LUnallocated* operand = ToUnallocated(reg);
686  DCHECK(operand->HasFixedPolicy());
687  return operand;
688 }
689 
690 
691 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
692  return new(zone()) LLabel(instr->block());
693 }
694 
695 
696 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
697  return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
698 }
699 
700 
701 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
702  UNREACHABLE();
703  return NULL;
704 }
705 
706 
707 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
708  return AssignEnvironment(new(zone()) LDeoptimize);
709 }
710 
711 
712 LInstruction* LChunkBuilder::DoShift(Token::Value op,
713  HBitwiseBinaryOperation* instr) {
714  if (instr->representation().IsSmiOrInteger32()) {
715  DCHECK(instr->left()->representation().Equals(instr->representation()));
716  DCHECK(instr->right()->representation().Equals(instr->representation()));
717  LOperand* left = UseRegisterAtStart(instr->left());
718 
719  HValue* right_value = instr->right();
720  LOperand* right = NULL;
721  int constant_value = 0;
722  bool does_deopt = false;
723  if (right_value->IsConstant()) {
724  HConstant* constant = HConstant::cast(right_value);
725  right = chunk_->DefineConstantOperand(constant);
726  constant_value = constant->Integer32Value() & 0x1f;
727  // Left shifts can deoptimize if we shift by > 0 and the result cannot be
728  // truncated to smi.
729  if (instr->representation().IsSmi() && constant_value > 0) {
730  does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
731  }
732  } else {
733  right = UseFixed(right_value, ecx);
734  }
735 
736  // Shift operations can only deoptimize if we do a logical shift by 0 and
737  // the result cannot be truncated to int32.
738  if (op == Token::SHR && constant_value == 0) {
739  if (FLAG_opt_safe_uint32_operations) {
740  does_deopt = !instr->CheckFlag(HInstruction::kUint32);
741  } else {
742  does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
743  }
744  }
745 
746  LInstruction* result =
747  DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
748  return does_deopt ? AssignEnvironment(result) : result;
749  } else {
750  return DoArithmeticT(op, instr);
751  }
752 }
753 
754 
755 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
756  HArithmeticBinaryOperation* instr) {
757  DCHECK(instr->representation().IsDouble());
758  DCHECK(instr->left()->representation().IsDouble());
759  DCHECK(instr->right()->representation().IsDouble());
760  if (op == Token::MOD) {
761  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
762  LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
763  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
764  return MarkAsCall(DefineSameAsFirst(result), instr);
765  } else {
766  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
767  LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
768  LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
769  return DefineSameAsFirst(result);
770  }
771 }
772 
773 
774 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
775  HBinaryOperation* instr) {
776  HValue* left = instr->left();
777  HValue* right = instr->right();
778  DCHECK(left->representation().IsTagged());
779  DCHECK(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  DCHECK(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  DCHECK(block->phis()->length() == 0);
800  HBasicBlock* pred = block->predecessors()->at(0);
801  HEnvironment* last_environment = pred->last_environment();
802  DCHECK(last_environment != NULL);
803  // Only copy the environment, if it is later used again.
804  if (pred->end()->SecondSuccessor() == NULL) {
805  DCHECK(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  DCHECK(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  if (phi->HasMergedIndex()) {
823  last_environment->SetValueAt(phi->merged_index(), phi);
824  }
825  }
826  for (int i = 0; i < block->deleted_phis()->length(); ++i) {
827  if (block->deleted_phis()->at(i) < last_environment->length()) {
828  last_environment->SetValueAt(block->deleted_phis()->at(i),
829  graph_->GetConstantUndefined());
830  }
831  }
832  block->UpdateEnvironment(last_environment);
833  // Pick up the outgoing argument count of one of the predecessors.
834  argument_count_ = pred->argument_count();
835  }
836  HInstruction* current = block->first();
837  int start = chunk_->instructions()->length();
838  while (current != NULL && !is_aborted()) {
839  // Code for constants in registers is generated lazily.
840  if (!current->EmitAtUses()) {
841  VisitInstruction(current);
842  }
843  current = current->next();
844  }
845  int end = chunk_->instructions()->length() - 1;
846  if (end >= start) {
847  block->set_first_instruction_index(start);
848  block->set_last_instruction_index(end);
849  }
850  block->set_argument_count(argument_count_);
851  next_block_ = NULL;
852  current_block_ = NULL;
853 }
854 
855 
856 void LChunkBuilder::VisitInstruction(HInstruction* current) {
857  HInstruction* old_current = current_instruction_;
858  current_instruction_ = current;
859 
860  LInstruction* instr = NULL;
861  if (current->CanReplaceWithDummyUses()) {
862  if (current->OperandCount() == 0) {
863  instr = DefineAsRegister(new(zone()) LDummy());
864  } else {
865  DCHECK(!current->OperandAt(0)->IsControlInstruction());
866  instr = DefineAsRegister(new(zone())
867  LDummyUse(UseAny(current->OperandAt(0))));
868  }
869  for (int i = 1; i < current->OperandCount(); ++i) {
870  if (current->OperandAt(i)->IsControlInstruction()) continue;
871  LInstruction* dummy =
872  new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
873  dummy->set_hydrogen_value(current);
874  chunk_->AddInstruction(dummy, current_block_);
875  }
876  } else {
877  HBasicBlock* successor;
878  if (current->IsControlInstruction() &&
879  HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
880  successor != NULL) {
881  // Always insert a fpu register barrier here when branch is optimized to
882  // be a direct goto.
883  // TODO(weiliang): require a better solution.
884  if (!current->IsGoto()) {
885  LClobberDoubles* clobber = new (zone()) LClobberDoubles(isolate());
886  clobber->set_hydrogen_value(current);
887  chunk_->AddInstruction(clobber, current_block_);
888  }
889  instr = new(zone()) LGoto(successor);
890  } else {
891  instr = current->CompileToLithium(this);
892  }
893  }
894 
895  argument_count_ += current->argument_delta();
896  DCHECK(argument_count_ >= 0);
897 
898  if (instr != NULL) {
899  AddInstruction(instr, current);
900  }
901 
902  current_instruction_ = old_current;
903 }
904 
905 
906 void LChunkBuilder::AddInstruction(LInstruction* instr,
907  HInstruction* hydrogen_val) {
908  // Associate the hydrogen instruction first, since we may need it for
909  // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
910  instr->set_hydrogen_value(hydrogen_val);
911 
912 #if DEBUG
913  // Make sure that the lithium instruction has either no fixed register
914  // constraints in temps or the result OR no uses that are only used at
915  // start. If this invariant doesn't hold, the register allocator can decide
916  // to insert a split of a range immediately before the instruction due to an
917  // already allocated register needing to be used for the instruction's fixed
918  // register constraint. In this case, The register allocator won't see an
919  // interference between the split child and the use-at-start (it would if
920  // the it was just a plain use), so it is free to move the split child into
921  // the same register that is used for the use-at-start.
922  // See https://code.google.com/p/chromium/issues/detail?id=201590
923  if (!(instr->ClobbersRegisters() &&
924  instr->ClobbersDoubleRegisters(isolate()))) {
925  int fixed = 0;
926  int used_at_start = 0;
927  for (UseIterator it(instr); !it.Done(); it.Advance()) {
928  LUnallocated* operand = LUnallocated::cast(it.Current());
929  if (operand->IsUsedAtStart()) ++used_at_start;
930  }
931  if (instr->Output() != NULL) {
932  if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
933  }
934  for (TempIterator it(instr); !it.Done(); it.Advance()) {
935  LUnallocated* operand = LUnallocated::cast(it.Current());
936  if (operand->HasFixedPolicy()) ++fixed;
937  }
938  DCHECK(fixed == 0 || used_at_start == 0);
939  }
940 #endif
941 
942  if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
943  instr = AssignPointerMap(instr);
944  }
945  if (FLAG_stress_environments && !instr->HasEnvironment()) {
946  instr = AssignEnvironment(instr);
947  }
948  if (instr->IsGoto() &&
949  (LGoto::cast(instr)->jumps_to_join() || next_block_->is_osr_entry())) {
950  // TODO(olivf) Since phis of spilled values are joined as registers
951  // (not in the stack slot), we need to allow the goto gaps to keep one
952  // x87 register alive. To ensure all other values are still spilled, we
953  // insert a fpu register barrier right before.
954  LClobberDoubles* clobber = new(zone()) LClobberDoubles(isolate());
955  clobber->set_hydrogen_value(hydrogen_val);
956  chunk_->AddInstruction(clobber, current_block_);
957  }
958  chunk_->AddInstruction(instr, current_block_);
959 
960  if (instr->IsCall()) {
961  HValue* hydrogen_value_for_lazy_bailout = hydrogen_val;
962  LInstruction* instruction_needing_environment = NULL;
963  if (hydrogen_val->HasObservableSideEffects()) {
964  HSimulate* sim = HSimulate::cast(hydrogen_val->next());
965  instruction_needing_environment = instr;
966  sim->ReplayEnvironment(current_block_->last_environment());
967  hydrogen_value_for_lazy_bailout = sim;
968  }
969  LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
970  bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
971  chunk_->AddInstruction(bailout, current_block_);
972  if (instruction_needing_environment != NULL) {
973  // Store the lazy deopt environment with the instruction if needed.
974  // Right now it is only used for LInstanceOfKnownGlobal.
975  instruction_needing_environment->
976  SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
977  }
978  }
979 }
980 
981 
982 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
983  return new(zone()) LGoto(instr->FirstSuccessor());
984 }
985 
986 
987 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
988  HValue* value = instr->value();
989  Representation r = value->representation();
990  HType type = value->type();
991  ToBooleanStub::Types expected = instr->expected_input_types();
992  if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
993 
994  bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
995  type.IsJSArray() || type.IsHeapNumber() || type.IsString();
996  LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL;
997  LInstruction* branch =
998  temp != NULL ? new (zone()) LBranch(UseRegister(value), temp)
999  : new (zone()) LBranch(UseRegisterAtStart(value), temp);
1000  if (!easy_case &&
1001  ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) ||
1002  !expected.IsGeneric())) {
1003  branch = AssignEnvironment(branch);
1004  }
1005  return branch;
1006 }
1007 
1008 
1009 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1010  return new(zone()) LDebugBreak();
1011 }
1012 
1013 
1014 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1015  DCHECK(instr->value()->representation().IsTagged());
1016  LOperand* value = UseRegisterAtStart(instr->value());
1017  return new(zone()) LCmpMapAndBranch(value);
1018 }
1019 
1020 
1021 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1022  info()->MarkAsRequiresFrame();
1023  return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
1024 }
1025 
1026 
1027 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1028  info()->MarkAsRequiresFrame();
1029  return DefineAsRegister(new(zone()) LArgumentsElements);
1030 }
1031 
1032 
1033 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1034  LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
1035  LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
1036  LOperand* context = UseFixed(instr->context(), esi);
1037  LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
1038  return MarkAsCall(DefineFixed(result, eax), instr);
1039 }
1040 
1041 
1042 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1043  HInstanceOfKnownGlobal* instr) {
1044  LInstanceOfKnownGlobal* result =
1045  new(zone()) LInstanceOfKnownGlobal(
1046  UseFixed(instr->context(), esi),
1047  UseFixed(instr->left(), InstanceofStub::left()),
1048  FixedTemp(edi));
1049  return MarkAsCall(DefineFixed(result, eax), instr);
1050 }
1051 
1052 
1053 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1054  LOperand* receiver = UseRegister(instr->receiver());
1055  LOperand* function = UseRegister(instr->function());
1056  LOperand* temp = TempRegister();
1057  LWrapReceiver* result =
1058  new(zone()) LWrapReceiver(receiver, function, temp);
1059  return AssignEnvironment(DefineSameAsFirst(result));
1060 }
1061 
1062 
1063 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1064  LOperand* function = UseFixed(instr->function(), edi);
1065  LOperand* receiver = UseFixed(instr->receiver(), eax);
1066  LOperand* length = UseFixed(instr->length(), ebx);
1067  LOperand* elements = UseFixed(instr->elements(), ecx);
1068  LApplyArguments* result = new(zone()) LApplyArguments(function,
1069  receiver,
1070  length,
1071  elements);
1072  return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1073 }
1074 
1075 
1076 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
1077  int argc = instr->OperandCount();
1078  for (int i = 0; i < argc; ++i) {
1079  LOperand* argument = UseAny(instr->argument(i));
1080  AddInstruction(new(zone()) LPushArgument(argument), instr);
1081  }
1082  return NULL;
1083 }
1084 
1085 
1086 LInstruction* LChunkBuilder::DoStoreCodeEntry(
1087  HStoreCodeEntry* store_code_entry) {
1088  LOperand* function = UseRegister(store_code_entry->function());
1089  LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1090  return new(zone()) LStoreCodeEntry(function, code_object);
1091 }
1092 
1093 
1094 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1095  HInnerAllocatedObject* instr) {
1096  LOperand* base_object = UseRegisterAtStart(instr->base_object());
1097  LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
1098  return DefineAsRegister(
1099  new(zone()) LInnerAllocatedObject(base_object, offset));
1100 }
1101 
1102 
1103 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1104  return instr->HasNoUses()
1105  ? NULL
1106  : DefineAsRegister(new(zone()) LThisFunction);
1107 }
1108 
1109 
1110 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1111  if (instr->HasNoUses()) return NULL;
1112 
1113  if (info()->IsStub()) {
1114  return DefineFixed(new(zone()) LContext, esi);
1115  }
1116 
1117  return DefineAsRegister(new(zone()) LContext);
1118 }
1119 
1120 
1121 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1122  LOperand* context = UseFixed(instr->context(), esi);
1123  return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1124 }
1125 
1126 
1127 LInstruction* LChunkBuilder::DoCallJSFunction(
1128  HCallJSFunction* instr) {
1129  LOperand* function = UseFixed(instr->function(), edi);
1130 
1131  LCallJSFunction* result = new(zone()) LCallJSFunction(function);
1132 
1133  return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1134 }
1135 
1136 
1137 LInstruction* LChunkBuilder::DoCallWithDescriptor(
1138  HCallWithDescriptor* instr) {
1139  CallInterfaceDescriptor descriptor = instr->descriptor();
1140  LOperand* target = UseRegisterOrConstantAtStart(instr->target());
1141  ZoneList<LOperand*> ops(instr->OperandCount(), zone());
1142  ops.Add(target, zone());
1143  for (int i = 1; i < instr->OperandCount(); i++) {
1144  LOperand* op =
1145  UseFixed(instr->OperandAt(i), descriptor.GetParameterRegister(i - 1));
1146  ops.Add(op, zone());
1147  }
1148 
1149  LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(
1150  descriptor, ops, zone());
1151  return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1152 }
1153 
1154 
1155 LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
1156  HTailCallThroughMegamorphicCache* instr) {
1157  LOperand* context = UseFixed(instr->context(), esi);
1158  LOperand* receiver_register =
1159  UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
1160  LOperand* name_register =
1161  UseFixed(instr->name(), LoadDescriptor::NameRegister());
1162  // Not marked as call. It can't deoptimize, and it never returns.
1163  return new (zone()) LTailCallThroughMegamorphicCache(
1164  context, receiver_register, name_register);
1165 }
1166 
1167 
1168 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1169  LOperand* context = UseFixed(instr->context(), esi);
1170  LOperand* function = UseFixed(instr->function(), edi);
1171  LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
1172  return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1173 }
1174 
1175 
1176 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1177  switch (instr->op()) {
1178  case kMathFloor: return DoMathFloor(instr);
1179  case kMathRound: return DoMathRound(instr);
1180  case kMathFround: return DoMathFround(instr);
1181  case kMathAbs: return DoMathAbs(instr);
1182  case kMathLog: return DoMathLog(instr);
1183  case kMathExp: return DoMathExp(instr);
1184  case kMathSqrt: return DoMathSqrt(instr);
1185  case kMathPowHalf: return DoMathPowHalf(instr);
1186  case kMathClz32: return DoMathClz32(instr);
1187  default:
1188  UNREACHABLE();
1189  return NULL;
1190  }
1191 }
1192 
1193 
1194 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1195  LOperand* input = UseRegisterAtStart(instr->value());
1196  LMathFloor* result = new(zone()) LMathFloor(input);
1197  return AssignEnvironment(DefineAsRegister(result));
1198 }
1199 
1200 
1201 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1202  LOperand* input = UseRegisterAtStart(instr->value());
1203  LInstruction* result = DefineAsRegister(new (zone()) LMathRound(input));
1204  return AssignEnvironment(result);
1205 }
1206 
1207 
1208 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1209  LOperand* input = UseRegister(instr->value());
1210  LMathFround* result = new (zone()) LMathFround(input);
1211  return DefineSameAsFirst(result);
1212 }
1213 
1214 
1215 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1216  LOperand* context = UseAny(instr->context()); // Deferred use.
1217  LOperand* input = UseRegisterAtStart(instr->value());
1218  LInstruction* result =
1219  DefineSameAsFirst(new(zone()) LMathAbs(context, input));
1220  Representation r = instr->value()->representation();
1221  if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1222  if (!r.IsDouble()) result = AssignEnvironment(result);
1223  return result;
1224 }
1225 
1226 
1227 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1228  DCHECK(instr->representation().IsDouble());
1229  DCHECK(instr->value()->representation().IsDouble());
1230  LOperand* input = UseRegisterAtStart(instr->value());
1231  return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr);
1232 }
1233 
1234 
1235 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1236  LOperand* input = UseRegisterAtStart(instr->value());
1237  LMathClz32* result = new(zone()) LMathClz32(input);
1238  return DefineAsRegister(result);
1239 }
1240 
1241 
1242 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1243  DCHECK(instr->representation().IsDouble());
1244  DCHECK(instr->value()->representation().IsDouble());
1245  LOperand* value = UseRegisterAtStart(instr->value());
1246  LOperand* temp1 = FixedTemp(ecx);
1247  LOperand* temp2 = FixedTemp(edx);
1248  LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1249  return MarkAsCall(DefineSameAsFirst(result), instr);
1250 }
1251 
1252 
1253 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1254  LOperand* input = UseRegisterAtStart(instr->value());
1255  LOperand* temp1 = FixedTemp(ecx);
1256  LOperand* temp2 = FixedTemp(edx);
1257  LMathSqrt* result = new(zone()) LMathSqrt(input, temp1, temp2);
1258  return MarkAsCall(DefineSameAsFirst(result), instr);
1259 }
1260 
1261 
1262 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1263  LOperand* input = UseRegisterAtStart(instr->value());
1264  LMathPowHalf* result = new (zone()) LMathPowHalf(input);
1265  return DefineSameAsFirst(result);
1266 }
1267 
1268 
1269 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1270  LOperand* context = UseFixed(instr->context(), esi);
1271  LOperand* constructor = UseFixed(instr->constructor(), edi);
1272  LCallNew* result = new(zone()) LCallNew(context, constructor);
1273  return MarkAsCall(DefineFixed(result, eax), instr);
1274 }
1275 
1276 
1277 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1278  LOperand* context = UseFixed(instr->context(), esi);
1279  LOperand* constructor = UseFixed(instr->constructor(), edi);
1280  LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1281  return MarkAsCall(DefineFixed(result, eax), instr);
1282 }
1283 
1284 
1285 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1286  LOperand* context = UseFixed(instr->context(), esi);
1287  LOperand* function = UseFixed(instr->function(), edi);
1288  LCallFunction* call = new(zone()) LCallFunction(context, function);
1289  return MarkAsCall(DefineFixed(call, eax), instr);
1290 }
1291 
1292 
1293 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1294  LOperand* context = UseFixed(instr->context(), esi);
1295  return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr);
1296 }
1297 
1298 
1299 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1300  return DoShift(Token::ROR, instr);
1301 }
1302 
1303 
1304 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1305  return DoShift(Token::SHR, instr);
1306 }
1307 
1308 
1309 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1310  return DoShift(Token::SAR, instr);
1311 }
1312 
1313 
1314 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1315  return DoShift(Token::SHL, instr);
1316 }
1317 
1318 
1319 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1320  if (instr->representation().IsSmiOrInteger32()) {
1321  DCHECK(instr->left()->representation().Equals(instr->representation()));
1322  DCHECK(instr->right()->representation().Equals(instr->representation()));
1323  DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32));
1324 
1325  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1326  LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1327  return DefineSameAsFirst(new(zone()) LBitI(left, right));
1328  } else {
1329  return DoArithmeticT(instr->op(), instr);
1330  }
1331 }
1332 
1333 
1334 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1335  DCHECK(instr->representation().IsSmiOrInteger32());
1336  DCHECK(instr->left()->representation().Equals(instr->representation()));
1337  DCHECK(instr->right()->representation().Equals(instr->representation()));
1338  LOperand* dividend = UseRegister(instr->left());
1339  int32_t divisor = instr->right()->GetInteger32Constant();
1340  LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
1341  dividend, divisor));
1342  if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1343  (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1344  (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1345  divisor != 1 && divisor != -1)) {
1346  result = AssignEnvironment(result);
1347  }
1348  return result;
1349 }
1350 
1351 
1352 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1353  DCHECK(instr->representation().IsInteger32());
1354  DCHECK(instr->left()->representation().Equals(instr->representation()));
1355  DCHECK(instr->right()->representation().Equals(instr->representation()));
1356  LOperand* dividend = UseRegister(instr->left());
1357  int32_t divisor = instr->right()->GetInteger32Constant();
1358  LOperand* temp1 = FixedTemp(eax);
1359  LOperand* temp2 = FixedTemp(edx);
1360  LInstruction* result = DefineFixed(new(zone()) LDivByConstI(
1361  dividend, divisor, temp1, temp2), edx);
1362  if (divisor == 0 ||
1363  (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1364  !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1365  result = AssignEnvironment(result);
1366  }
1367  return result;
1368 }
1369 
1370 
1371 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1372  DCHECK(instr->representation().IsSmiOrInteger32());
1373  DCHECK(instr->left()->representation().Equals(instr->representation()));
1374  DCHECK(instr->right()->representation().Equals(instr->representation()));
1375  LOperand* dividend = UseFixed(instr->left(), eax);
1376  LOperand* divisor = UseRegister(instr->right());
1377  LOperand* temp = FixedTemp(edx);
1378  LInstruction* result = DefineFixed(new(zone()) LDivI(
1379  dividend, divisor, temp), eax);
1380  if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1381  instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1382  instr->CheckFlag(HValue::kCanOverflow) ||
1383  !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1384  result = AssignEnvironment(result);
1385  }
1386  return result;
1387 }
1388 
1389 
1390 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1391  if (instr->representation().IsSmiOrInteger32()) {
1392  if (instr->RightIsPowerOf2()) {
1393  return DoDivByPowerOf2I(instr);
1394  } else if (instr->right()->IsConstant()) {
1395  return DoDivByConstI(instr);
1396  } else {
1397  return DoDivI(instr);
1398  }
1399  } else if (instr->representation().IsDouble()) {
1400  return DoArithmeticD(Token::DIV, instr);
1401  } else {
1402  return DoArithmeticT(Token::DIV, instr);
1403  }
1404 }
1405 
1406 
1407 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1408  LOperand* dividend = UseRegisterAtStart(instr->left());
1409  int32_t divisor = instr->right()->GetInteger32Constant();
1410  LInstruction* result = DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(
1411  dividend, divisor));
1412  if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1413  (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1414  result = AssignEnvironment(result);
1415  }
1416  return result;
1417 }
1418 
1419 
1420 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1421  DCHECK(instr->representation().IsInteger32());
1422  DCHECK(instr->left()->representation().Equals(instr->representation()));
1423  DCHECK(instr->right()->representation().Equals(instr->representation()));
1424  LOperand* dividend = UseRegister(instr->left());
1425  int32_t divisor = instr->right()->GetInteger32Constant();
1426  LOperand* temp1 = FixedTemp(eax);
1427  LOperand* temp2 = FixedTemp(edx);
1428  LOperand* temp3 =
1429  ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
1430  (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
1431  NULL : TempRegister();
1432  LInstruction* result =
1433  DefineFixed(new(zone()) LFlooringDivByConstI(dividend,
1434  divisor,
1435  temp1,
1436  temp2,
1437  temp3),
1438  edx);
1439  if (divisor == 0 ||
1440  (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
1441  result = AssignEnvironment(result);
1442  }
1443  return result;
1444 }
1445 
1446 
1447 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1448  DCHECK(instr->representation().IsSmiOrInteger32());
1449  DCHECK(instr->left()->representation().Equals(instr->representation()));
1450  DCHECK(instr->right()->representation().Equals(instr->representation()));
1451  LOperand* dividend = UseFixed(instr->left(), eax);
1452  LOperand* divisor = UseRegister(instr->right());
1453  LOperand* temp = FixedTemp(edx);
1454  LInstruction* result = DefineFixed(new(zone()) LFlooringDivI(
1455  dividend, divisor, temp), eax);
1456  if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1457  instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1458  instr->CheckFlag(HValue::kCanOverflow)) {
1459  result = AssignEnvironment(result);
1460  }
1461  return result;
1462 }
1463 
1464 
1465 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1466  if (instr->RightIsPowerOf2()) {
1467  return DoFlooringDivByPowerOf2I(instr);
1468  } else if (instr->right()->IsConstant()) {
1469  return DoFlooringDivByConstI(instr);
1470  } else {
1471  return DoFlooringDivI(instr);
1472  }
1473 }
1474 
1475 
1476 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1477  DCHECK(instr->representation().IsSmiOrInteger32());
1478  DCHECK(instr->left()->representation().Equals(instr->representation()));
1479  DCHECK(instr->right()->representation().Equals(instr->representation()));
1480  LOperand* dividend = UseRegisterAtStart(instr->left());
1481  int32_t divisor = instr->right()->GetInteger32Constant();
1482  LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
1483  dividend, divisor));
1484  if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
1485  instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1486  result = AssignEnvironment(result);
1487  }
1488  return result;
1489 }
1490 
1491 
1492 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1493  DCHECK(instr->representation().IsSmiOrInteger32());
1494  DCHECK(instr->left()->representation().Equals(instr->representation()));
1495  DCHECK(instr->right()->representation().Equals(instr->representation()));
1496  LOperand* dividend = UseRegister(instr->left());
1497  int32_t divisor = instr->right()->GetInteger32Constant();
1498  LOperand* temp1 = FixedTemp(eax);
1499  LOperand* temp2 = FixedTemp(edx);
1500  LInstruction* result = DefineFixed(new(zone()) LModByConstI(
1501  dividend, divisor, temp1, temp2), eax);
1502  if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1503  result = AssignEnvironment(result);
1504  }
1505  return result;
1506 }
1507 
1508 
1509 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1510  DCHECK(instr->representation().IsSmiOrInteger32());
1511  DCHECK(instr->left()->representation().Equals(instr->representation()));
1512  DCHECK(instr->right()->representation().Equals(instr->representation()));
1513  LOperand* dividend = UseFixed(instr->left(), eax);
1514  LOperand* divisor = UseRegister(instr->right());
1515  LOperand* temp = FixedTemp(edx);
1516  LInstruction* result = DefineFixed(new(zone()) LModI(
1517  dividend, divisor, temp), edx);
1518  if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1519  instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1520  result = AssignEnvironment(result);
1521  }
1522  return result;
1523 }
1524 
1525 
1526 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1527  if (instr->representation().IsSmiOrInteger32()) {
1528  if (instr->RightIsPowerOf2()) {
1529  return DoModByPowerOf2I(instr);
1530  } else if (instr->right()->IsConstant()) {
1531  return DoModByConstI(instr);
1532  } else {
1533  return DoModI(instr);
1534  }
1535  } else if (instr->representation().IsDouble()) {
1536  return DoArithmeticD(Token::MOD, instr);
1537  } else {
1538  return DoArithmeticT(Token::MOD, instr);
1539  }
1540 }
1541 
1542 
1543 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1544  if (instr->representation().IsSmiOrInteger32()) {
1545  DCHECK(instr->left()->representation().Equals(instr->representation()));
1546  DCHECK(instr->right()->representation().Equals(instr->representation()));
1547  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1548  LOperand* right = UseOrConstant(instr->BetterRightOperand());
1549  LOperand* temp = NULL;
1550  if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1551  temp = TempRegister();
1552  }
1553  LMulI* mul = new(zone()) LMulI(left, right, temp);
1554  if (instr->CheckFlag(HValue::kCanOverflow) ||
1555  instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1556  AssignEnvironment(mul);
1557  }
1558  return DefineSameAsFirst(mul);
1559  } else if (instr->representation().IsDouble()) {
1560  return DoArithmeticD(Token::MUL, instr);
1561  } else {
1562  return DoArithmeticT(Token::MUL, instr);
1563  }
1564 }
1565 
1566 
1567 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1568  if (instr->representation().IsSmiOrInteger32()) {
1569  DCHECK(instr->left()->representation().Equals(instr->representation()));
1570  DCHECK(instr->right()->representation().Equals(instr->representation()));
1571  LOperand* left = UseRegisterAtStart(instr->left());
1572  LOperand* right = UseOrConstantAtStart(instr->right());
1573  LSubI* sub = new(zone()) LSubI(left, right);
1574  LInstruction* result = DefineSameAsFirst(sub);
1575  if (instr->CheckFlag(HValue::kCanOverflow)) {
1576  result = AssignEnvironment(result);
1577  }
1578  return result;
1579  } else if (instr->representation().IsDouble()) {
1580  return DoArithmeticD(Token::SUB, instr);
1581  } else {
1582  return DoArithmeticT(Token::SUB, instr);
1583  }
1584 }
1585 
1586 
1587 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1588  if (instr->representation().IsSmiOrInteger32()) {
1589  DCHECK(instr->left()->representation().Equals(instr->representation()));
1590  DCHECK(instr->right()->representation().Equals(instr->representation()));
1591  // Check to see if it would be advantageous to use an lea instruction rather
1592  // than an add. This is the case when no overflow check is needed and there
1593  // are multiple uses of the add's inputs, so using a 3-register add will
1594  // preserve all input values for later uses.
1595  bool use_lea = LAddI::UseLea(instr);
1596  LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1597  HValue* right_candidate = instr->BetterRightOperand();
1598  LOperand* right = use_lea
1599  ? UseRegisterOrConstantAtStart(right_candidate)
1600  : UseOrConstantAtStart(right_candidate);
1601  LAddI* add = new(zone()) LAddI(left, right);
1602  bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1603  LInstruction* result = use_lea
1604  ? DefineAsRegister(add)
1605  : DefineSameAsFirst(add);
1606  if (can_overflow) {
1607  result = AssignEnvironment(result);
1608  }
1609  return result;
1610  } else if (instr->representation().IsDouble()) {
1611  return DoArithmeticD(Token::ADD, instr);
1612  } else if (instr->representation().IsExternal()) {
1613  DCHECK(instr->left()->representation().IsExternal());
1614  DCHECK(instr->right()->representation().IsInteger32());
1615  DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
1616  bool use_lea = LAddI::UseLea(instr);
1617  LOperand* left = UseRegisterAtStart(instr->left());
1618  HValue* right_candidate = instr->right();
1619  LOperand* right = use_lea
1620  ? UseRegisterOrConstantAtStart(right_candidate)
1621  : UseOrConstantAtStart(right_candidate);
1622  LAddI* add = new(zone()) LAddI(left, right);
1623  LInstruction* result = use_lea
1624  ? DefineAsRegister(add)
1625  : DefineSameAsFirst(add);
1626  return result;
1627  } else {
1628  return DoArithmeticT(Token::ADD, instr);
1629  }
1630 }
1631 
1632 
1633 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1634  LOperand* left = NULL;
1635  LOperand* right = NULL;
1636  LOperand* scratch = TempRegister();
1637 
1638  if (instr->representation().IsSmiOrInteger32()) {
1639  DCHECK(instr->left()->representation().Equals(instr->representation()));
1640  DCHECK(instr->right()->representation().Equals(instr->representation()));
1641  left = UseRegisterAtStart(instr->BetterLeftOperand());
1642  right = UseOrConstantAtStart(instr->BetterRightOperand());
1643  } else {
1644  DCHECK(instr->representation().IsDouble());
1645  DCHECK(instr->left()->representation().IsDouble());
1646  DCHECK(instr->right()->representation().IsDouble());
1647  left = UseRegisterAtStart(instr->left());
1648  right = UseRegisterAtStart(instr->right());
1649  }
1650  LMathMinMax* minmax = new (zone()) LMathMinMax(left, right, scratch);
1651  return DefineSameAsFirst(minmax);
1652 }
1653 
1654 
1655 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1656  // Unlike ia32, we don't have a MathPowStub and directly call c function.
1657  DCHECK(instr->representation().IsDouble());
1658  DCHECK(instr->left()->representation().IsDouble());
1659  LOperand* left = UseRegisterAtStart(instr->left());
1660  LOperand* right = UseRegisterAtStart(instr->right());
1661  LPower* result = new (zone()) LPower(left, right);
1662  return MarkAsCall(DefineSameAsFirst(result), instr);
1663 }
1664 
1665 
1666 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1667  DCHECK(instr->left()->representation().IsSmiOrTagged());
1668  DCHECK(instr->right()->representation().IsSmiOrTagged());
1669  LOperand* context = UseFixed(instr->context(), esi);
1670  LOperand* left = UseFixed(instr->left(), edx);
1671  LOperand* right = UseFixed(instr->right(), eax);
1672  LCmpT* result = new(zone()) LCmpT(context, left, right);
1673  return MarkAsCall(DefineFixed(result, eax), instr);
1674 }
1675 
1676 
1677 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1678  HCompareNumericAndBranch* instr) {
1679  Representation r = instr->representation();
1680  if (r.IsSmiOrInteger32()) {
1681  DCHECK(instr->left()->representation().Equals(r));
1682  DCHECK(instr->right()->representation().Equals(r));
1683  LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1684  LOperand* right = UseOrConstantAtStart(instr->right());
1685  return new(zone()) LCompareNumericAndBranch(left, right);
1686  } else {
1687  DCHECK(r.IsDouble());
1688  DCHECK(instr->left()->representation().IsDouble());
1689  DCHECK(instr->right()->representation().IsDouble());
1690  LOperand* left;
1691  LOperand* right;
1692  if (CanBeImmediateConstant(instr->left()) &&
1693  CanBeImmediateConstant(instr->right())) {
1694  // The code generator requires either both inputs to be constant
1695  // operands, or neither.
1696  left = UseConstant(instr->left());
1697  right = UseConstant(instr->right());
1698  } else {
1699  left = UseRegisterAtStart(instr->left());
1700  right = UseRegisterAtStart(instr->right());
1701  }
1702  return new(zone()) LCompareNumericAndBranch(left, right);
1703  }
1704 }
1705 
1706 
1707 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1708  HCompareObjectEqAndBranch* instr) {
1709  LOperand* left = UseRegisterAtStart(instr->left());
1710  LOperand* right = UseOrConstantAtStart(instr->right());
1711  return new(zone()) LCmpObjectEqAndBranch(left, right);
1712 }
1713 
1714 
1715 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1716  HCompareHoleAndBranch* instr) {
1717  LOperand* value = UseRegisterAtStart(instr->value());
1718  return new(zone()) LCmpHoleAndBranch(value);
1719 }
1720 
1721 
1722 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1723  HCompareMinusZeroAndBranch* instr) {
1724  LOperand* value = UseRegisterAtStart(instr->value());
1725  return new (zone()) LCompareMinusZeroAndBranch(value);
1726 }
1727 
1728 
1729 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1730  DCHECK(instr->value()->representation().IsSmiOrTagged());
1731  LOperand* temp = TempRegister();
1732  return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
1733 }
1734 
1735 
1736 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1737  DCHECK(instr->value()->representation().IsTagged());
1738  LOperand* temp = TempRegister();
1739  return new(zone()) LIsStringAndBranch(UseRegister(instr->value()), temp);
1740 }
1741 
1742 
1743 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1744  DCHECK(instr->value()->representation().IsTagged());
1745  return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1746 }
1747 
1748 
1749 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1750  HIsUndetectableAndBranch* instr) {
1751  DCHECK(instr->value()->representation().IsTagged());
1752  return new(zone()) LIsUndetectableAndBranch(
1753  UseRegisterAtStart(instr->value()), TempRegister());
1754 }
1755 
1756 
1757 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1758  HStringCompareAndBranch* instr) {
1759  DCHECK(instr->left()->representation().IsTagged());
1760  DCHECK(instr->right()->representation().IsTagged());
1761  LOperand* context = UseFixed(instr->context(), esi);
1762  LOperand* left = UseFixed(instr->left(), edx);
1763  LOperand* right = UseFixed(instr->right(), eax);
1764 
1765  LStringCompareAndBranch* result = new(zone())
1766  LStringCompareAndBranch(context, left, right);
1767 
1768  return MarkAsCall(result, instr);
1769 }
1770 
1771 
1772 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1773  HHasInstanceTypeAndBranch* instr) {
1774  DCHECK(instr->value()->representation().IsTagged());
1775  return new(zone()) LHasInstanceTypeAndBranch(
1776  UseRegisterAtStart(instr->value()),
1777  TempRegister());
1778 }
1779 
1780 
1781 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1782  HGetCachedArrayIndex* instr) {
1783  DCHECK(instr->value()->representation().IsTagged());
1784  LOperand* value = UseRegisterAtStart(instr->value());
1785 
1786  return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1787 }
1788 
1789 
1790 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1791  HHasCachedArrayIndexAndBranch* instr) {
1792  DCHECK(instr->value()->representation().IsTagged());
1793  return new(zone()) LHasCachedArrayIndexAndBranch(
1794  UseRegisterAtStart(instr->value()));
1795 }
1796 
1797 
1798 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1799  HClassOfTestAndBranch* instr) {
1800  DCHECK(instr->value()->representation().IsTagged());
1801  return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1802  TempRegister(),
1803  TempRegister());
1804 }
1805 
1806 
1807 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1808  LOperand* map = UseRegisterAtStart(instr->value());
1809  return DefineAsRegister(new(zone()) LMapEnumLength(map));
1810 }
1811 
1812 
1813 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1814  LOperand* date = UseFixed(instr->value(), eax);
1815  LDateField* result =
1816  new(zone()) LDateField(date, FixedTemp(ecx), instr->index());
1817  return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1818 }
1819 
1820 
1821 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1822  LOperand* string = UseRegisterAtStart(instr->string());
1823  LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1824  return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
1825 }
1826 
1827 
1828 LOperand* LChunkBuilder::GetSeqStringSetCharOperand(HSeqStringSetChar* instr) {
1829  if (instr->encoding() == String::ONE_BYTE_ENCODING) {
1830  if (FLAG_debug_code) {
1831  return UseFixed(instr->value(), eax);
1832  } else {
1833  return UseFixedOrConstant(instr->value(), eax);
1834  }
1835  } else {
1836  if (FLAG_debug_code) {
1837  return UseRegisterAtStart(instr->value());
1838  } else {
1839  return UseRegisterOrConstantAtStart(instr->value());
1840  }
1841  }
1842 }
1843 
1844 
1845 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1846  LOperand* string = UseRegisterAtStart(instr->string());
1847  LOperand* index = FLAG_debug_code
1848  ? UseRegisterAtStart(instr->index())
1849  : UseRegisterOrConstantAtStart(instr->index());
1850  LOperand* value = GetSeqStringSetCharOperand(instr);
1851  LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), esi) : NULL;
1852  LInstruction* result = new(zone()) LSeqStringSetChar(context, string,
1853  index, value);
1854  if (FLAG_debug_code) {
1855  result = MarkAsCall(result, instr);
1856  }
1857  return result;
1858 }
1859 
1860 
1861 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1862  if (!FLAG_debug_code && instr->skip_check()) return NULL;
1863  LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1864  LOperand* length = !index->IsConstantOperand()
1865  ? UseOrConstantAtStart(instr->length())
1866  : UseAtStart(instr->length());
1867  LInstruction* result = new(zone()) LBoundsCheck(index, length);
1868  if (!FLAG_debug_code || !instr->skip_check()) {
1869  result = AssignEnvironment(result);
1870  }
1871  return result;
1872 }
1873 
1874 
1875 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1876  HBoundsCheckBaseIndexInformation* instr) {
1877  UNREACHABLE();
1878  return NULL;
1879 }
1880 
1881 
1882 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1883  // The control instruction marking the end of a block that completed
1884  // abruptly (e.g., threw an exception). There is nothing specific to do.
1885  return NULL;
1886 }
1887 
1888 
1889 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1890  return NULL;
1891 }
1892 
1893 
1894 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1895  // All HForceRepresentation instructions should be eliminated in the
1896  // representation change phase of Hydrogen.
1897  UNREACHABLE();
1898  return NULL;
1899 }
1900 
1901 
1902 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1903  Representation from = instr->from();
1904  Representation to = instr->to();
1905  HValue* val = instr->value();
1906  if (from.IsSmi()) {
1907  if (to.IsTagged()) {
1908  LOperand* value = UseRegister(val);
1909  return DefineSameAsFirst(new(zone()) LDummyUse(value));
1910  }
1911  from = Representation::Tagged();
1912  }
1913  if (from.IsTagged()) {
1914  if (to.IsDouble()) {
1915  LOperand* value = UseRegister(val);
1916  LOperand* temp = TempRegister();
1917  LInstruction* result =
1918  DefineAsRegister(new(zone()) LNumberUntagD(value, temp));
1919  if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1920  return result;
1921  } else if (to.IsSmi()) {
1922  LOperand* value = UseRegister(val);
1923  if (val->type().IsSmi()) {
1924  return DefineSameAsFirst(new(zone()) LDummyUse(value));
1925  }
1926  return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
1927  } else {
1928  DCHECK(to.IsInteger32());
1929  if (val->type().IsSmi() || val->representation().IsSmi()) {
1930  LOperand* value = UseRegister(val);
1931  return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
1932  } else {
1933  LOperand* value = UseRegister(val);
1934  LInstruction* result = DefineSameAsFirst(new(zone()) LTaggedToI(value));
1935  if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1936  return result;
1937  }
1938  }
1939  } else if (from.IsDouble()) {
1940  if (to.IsTagged()) {
1941  info()->MarkAsDeferredCalling();
1942  LOperand* value = UseRegisterAtStart(val);
1943  LOperand* temp = FLAG_inline_new ? TempRegister() : NULL;
1944  LUnallocated* result_temp = TempRegister();
1945  LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
1946  return AssignPointerMap(Define(result, result_temp));
1947  } else if (to.IsSmi()) {
1948  LOperand* value = UseRegister(val);
1949  return AssignEnvironment(
1950  DefineAsRegister(new(zone()) LDoubleToSmi(value)));
1951  } else {
1952  DCHECK(to.IsInteger32());
1953  bool truncating = instr->CanTruncateToInt32();
1954  LOperand* value = UseRegister(val);
1955  LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value));
1956  if (!truncating) result = AssignEnvironment(result);
1957  return result;
1958  }
1959  } else if (from.IsInteger32()) {
1960  info()->MarkAsDeferredCalling();
1961  if (to.IsTagged()) {
1962  if (!instr->CheckFlag(HValue::kCanOverflow)) {
1963  LOperand* value = UseRegister(val);
1964  return DefineSameAsFirst(new(zone()) LSmiTag(value));
1965  } else if (val->CheckFlag(HInstruction::kUint32)) {
1966  LOperand* value = UseRegister(val);
1967  LOperand* temp = TempRegister();
1968  LNumberTagU* result = new(zone()) LNumberTagU(value, temp);
1969  return AssignPointerMap(DefineSameAsFirst(result));
1970  } else {
1971  LOperand* value = UseRegister(val);
1972  LOperand* temp = TempRegister();
1973  LNumberTagI* result = new(zone()) LNumberTagI(value, temp);
1974  return AssignPointerMap(DefineSameAsFirst(result));
1975  }
1976  } else if (to.IsSmi()) {
1977  LOperand* value = UseRegister(val);
1978  LInstruction* result = DefineSameAsFirst(new(zone()) LSmiTag(value));
1979  if (instr->CheckFlag(HValue::kCanOverflow)) {
1980  result = AssignEnvironment(result);
1981  }
1982  return result;
1983  } else {
1984  DCHECK(to.IsDouble());
1985  if (val->CheckFlag(HInstruction::kUint32)) {
1986  return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val)));
1987  } else {
1988  return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val)));
1989  }
1990  }
1991  }
1992  UNREACHABLE();
1993  return NULL;
1994 }
1995 
1996 
1997 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1998  LOperand* value = UseAtStart(instr->value());
1999  LInstruction* result = new(zone()) LCheckNonSmi(value);
2000  if (!instr->value()->type().IsHeapObject()) {
2001  result = AssignEnvironment(result);
2002  }
2003  return result;
2004 }
2005 
2006 
2007 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2008  LOperand* value = UseRegisterAtStart(instr->value());
2009  return AssignEnvironment(new(zone()) LCheckSmi(value));
2010 }
2011 
2012 
2013 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2014  LOperand* value = UseRegisterAtStart(instr->value());
2015  LOperand* temp = TempRegister();
2016  LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp);
2017  return AssignEnvironment(result);
2018 }
2019 
2020 
2021 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2022  // If the object is in new space, we'll emit a global cell compare and so
2023  // want the value in a register. If the object gets promoted before we
2024  // emit code, we will still get the register but will do an immediate
2025  // compare instead of the cell compare. This is safe.
2026  LOperand* value = instr->object_in_new_space()
2027  ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value());
2028  return AssignEnvironment(new(zone()) LCheckValue(value));
2029 }
2030 
2031 
2032 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
2033  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
2034  LOperand* value = UseRegisterAtStart(instr->value());
2035  LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
2036  if (instr->HasMigrationTarget()) {
2037  info()->MarkAsDeferredCalling();
2038  result = AssignPointerMap(result);
2039  }
2040  return result;
2041 }
2042 
2043 
2044 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2045  HValue* value = instr->value();
2046  Representation input_rep = value->representation();
2047  if (input_rep.IsDouble()) {
2048  LOperand* reg = UseRegister(value);
2049  return DefineFixed(new (zone()) LClampDToUint8(reg), eax);
2050  } else if (input_rep.IsInteger32()) {
2051  LOperand* reg = UseFixed(value, eax);
2052  return DefineFixed(new(zone()) LClampIToUint8(reg), eax);
2053  } else {
2054  DCHECK(input_rep.IsSmiOrTagged());
2055  LOperand* value = UseRegister(instr->value());
2056  LClampTToUint8NoSSE2* res =
2057  new(zone()) LClampTToUint8NoSSE2(value, TempRegister(),
2058  TempRegister(), TempRegister());
2059  return AssignEnvironment(DefineFixed(res, ecx));
2060  }
2061 }
2062 
2063 
2064 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
2065  HValue* value = instr->value();
2066  DCHECK(value->representation().IsDouble());
2067  return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
2068 }
2069 
2070 
2071 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
2072  LOperand* lo = UseRegister(instr->lo());
2073  LOperand* hi = UseRegister(instr->hi());
2074  return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
2075 }
2076 
2077 
2078 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
2079  LOperand* context = info()->IsStub() ? UseFixed(instr->context(), esi) : NULL;
2080  LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
2081  return new(zone()) LReturn(
2082  UseFixed(instr->value(), eax), context, parameter_count);
2083 }
2084 
2085 
2086 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2087  Representation r = instr->representation();
2088  if (r.IsSmi()) {
2089  return DefineAsRegister(new(zone()) LConstantS);
2090  } else if (r.IsInteger32()) {
2091  return DefineAsRegister(new(zone()) LConstantI);
2092  } else if (r.IsDouble()) {
2093  return DefineAsRegister(new (zone()) LConstantD);
2094  } else if (r.IsExternal()) {
2095  return DefineAsRegister(new(zone()) LConstantE);
2096  } else if (r.IsTagged()) {
2097  return DefineAsRegister(new(zone()) LConstantT);
2098  } else {
2099  UNREACHABLE();
2100  return NULL;
2101  }
2102 }
2103 
2104 
2105 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
2106  LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
2107  return instr->RequiresHoleCheck()
2108  ? AssignEnvironment(DefineAsRegister(result))
2109  : DefineAsRegister(result);
2110 }
2111 
2112 
2113 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2114  LOperand* context = UseFixed(instr->context(), esi);
2115  LOperand* global_object =
2116  UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
2117  LOperand* vector = NULL;
2118  if (FLAG_vector_ics) {
2119  vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2120  }
2121 
2122  LLoadGlobalGeneric* result =
2123  new(zone()) LLoadGlobalGeneric(context, global_object, vector);
2124  return MarkAsCall(DefineFixed(result, eax), instr);
2125 }
2126 
2127 
2128 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2129  LStoreGlobalCell* result =
2130  new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
2131  return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
2132 }
2133 
2134 
2135 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
2136  LOperand* context = UseRegisterAtStart(instr->value());
2137  LInstruction* result =
2138  DefineAsRegister(new(zone()) LLoadContextSlot(context));
2139  if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2140  result = AssignEnvironment(result);
2141  }
2142  return result;
2143 }
2144 
2145 
2146 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
2147  LOperand* value;
2148  LOperand* temp;
2149  LOperand* context = UseRegister(instr->context());
2150  if (instr->NeedsWriteBarrier()) {
2151  value = UseTempRegister(instr->value());
2152  temp = TempRegister();
2153  } else {
2154  value = UseRegister(instr->value());
2155  temp = NULL;
2156  }
2157  LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
2158  if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
2159  result = AssignEnvironment(result);
2160  }
2161  return result;
2162 }
2163 
2164 
2165 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2166  LOperand* obj = (instr->access().IsExternalMemory() &&
2167  instr->access().offset() == 0)
2168  ? UseRegisterOrConstantAtStart(instr->object())
2169  : UseRegisterAtStart(instr->object());
2170  return DefineAsRegister(new(zone()) LLoadNamedField(obj));
2171 }
2172 
2173 
2174 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2175  LOperand* context = UseFixed(instr->context(), esi);
2176  LOperand* object =
2177  UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
2178  LOperand* vector = NULL;
2179  if (FLAG_vector_ics) {
2180  vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2181  }
2182  LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
2183  context, object, vector);
2184  return MarkAsCall(DefineFixed(result, eax), instr);
2185 }
2186 
2187 
2188 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2189  HLoadFunctionPrototype* instr) {
2190  return AssignEnvironment(DefineAsRegister(
2191  new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
2192  TempRegister())));
2193 }
2194 
2195 
2196 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2197  return DefineAsRegister(new(zone()) LLoadRoot);
2198 }
2199 
2200 
2201 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
2202  DCHECK(instr->key()->representation().IsSmiOrInteger32());
2203  ElementsKind elements_kind = instr->elements_kind();
2204  bool clobbers_key = ExternalArrayOpRequiresTemp(
2205  instr->key()->representation(), elements_kind);
2206  LOperand* key = clobbers_key
2207  ? UseTempRegister(instr->key())
2208  : UseRegisterOrConstantAtStart(instr->key());
2209  LInstruction* result = NULL;
2210 
2211  if (!instr->is_typed_elements()) {
2212  LOperand* obj = UseRegisterAtStart(instr->elements());
2213  result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
2214  } else {
2215  DCHECK(
2216  (instr->representation().IsInteger32() &&
2217  !(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
2218  (instr->representation().IsDouble() &&
2219  (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
2220  LOperand* backing_store = UseRegister(instr->elements());
2221  result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
2222  }
2223 
2224  if ((instr->is_external() || instr->is_fixed_typed_array()) ?
2225  // see LCodeGen::DoLoadKeyedExternalArray
2226  ((instr->elements_kind() == EXTERNAL_UINT32_ELEMENTS ||
2227  instr->elements_kind() == UINT32_ELEMENTS) &&
2228  !instr->CheckFlag(HInstruction::kUint32)) :
2229  // see LCodeGen::DoLoadKeyedFixedDoubleArray and
2230  // LCodeGen::DoLoadKeyedFixedArray
2231  instr->RequiresHoleCheck()) {
2232  result = AssignEnvironment(result);
2233  }
2234  return result;
2235 }
2236 
2237 
2238 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2239  LOperand* context = UseFixed(instr->context(), esi);
2240  LOperand* object =
2241  UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
2242  LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
2243  LOperand* vector = NULL;
2244  if (FLAG_vector_ics) {
2245  vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
2246  }
2247  LLoadKeyedGeneric* result =
2248  new(zone()) LLoadKeyedGeneric(context, object, key, vector);
2249  return MarkAsCall(DefineFixed(result, eax), instr);
2250 }
2251 
2252 
2253 LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
2254  ElementsKind elements_kind = instr->elements_kind();
2255 
2256  // Determine if we need a byte register in this case for the value.
2257  bool val_is_fixed_register =
2258  elements_kind == EXTERNAL_INT8_ELEMENTS ||
2259  elements_kind == EXTERNAL_UINT8_ELEMENTS ||
2260  elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2261  elements_kind == UINT8_ELEMENTS ||
2262  elements_kind == INT8_ELEMENTS ||
2263  elements_kind == UINT8_CLAMPED_ELEMENTS;
2264  if (val_is_fixed_register) {
2265  return UseFixed(instr->value(), eax);
2266  }
2267 
2268  if (IsDoubleOrFloatElementsKind(elements_kind)) {
2269  return UseRegisterAtStart(instr->value());
2270  }
2271 
2272  return UseRegister(instr->value());
2273 }
2274 
2275 
2276 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2277  if (!instr->is_typed_elements()) {
2278  DCHECK(instr->elements()->representation().IsTagged());
2279  DCHECK(instr->key()->representation().IsInteger32() ||
2280  instr->key()->representation().IsSmi());
2281 
2282  if (instr->value()->representation().IsDouble()) {
2283  LOperand* object = UseRegisterAtStart(instr->elements());
2284  // For storing double hole, no fp register required.
2285  LOperand* val = instr->IsConstantHoleStore()
2286  ? NULL
2287  : UseRegisterAtStart(instr->value());
2288  LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2289  return new(zone()) LStoreKeyed(object, key, val);
2290  } else {
2291  DCHECK(instr->value()->representation().IsSmiOrTagged());
2292  bool needs_write_barrier = instr->NeedsWriteBarrier();
2293 
2294  LOperand* obj = UseRegister(instr->elements());
2295  LOperand* val;
2296  LOperand* key;
2297  if (needs_write_barrier) {
2298  val = UseTempRegister(instr->value());
2299  key = UseTempRegister(instr->key());
2300  } else {
2301  val = UseRegisterOrConstantAtStart(instr->value());
2302  key = UseRegisterOrConstantAtStart(instr->key());
2303  }
2304  return new(zone()) LStoreKeyed(obj, key, val);
2305  }
2306  }
2307 
2308  ElementsKind elements_kind = instr->elements_kind();
2309  DCHECK(
2310  (instr->value()->representation().IsInteger32() &&
2311  !IsDoubleOrFloatElementsKind(elements_kind)) ||
2312  (instr->value()->representation().IsDouble() &&
2313  IsDoubleOrFloatElementsKind(elements_kind)));
2314  DCHECK((instr->is_fixed_typed_array() &&
2315  instr->elements()->representation().IsTagged()) ||
2316  (instr->is_external() &&
2317  instr->elements()->representation().IsExternal()));
2318 
2319  LOperand* backing_store = UseRegister(instr->elements());
2320  LOperand* val = GetStoreKeyedValueOperand(instr);
2321  bool clobbers_key = ExternalArrayOpRequiresTemp(
2322  instr->key()->representation(), elements_kind);
2323  LOperand* key = clobbers_key
2324  ? UseTempRegister(instr->key())
2325  : UseRegisterOrConstantAtStart(instr->key());
2326  return new(zone()) LStoreKeyed(backing_store, key, val);
2327 }
2328 
2329 
2330 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2331  LOperand* context = UseFixed(instr->context(), esi);
2332  LOperand* object =
2333  UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
2334  LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister());
2335  LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
2336 
2337  DCHECK(instr->object()->representation().IsTagged());
2338  DCHECK(instr->key()->representation().IsTagged());
2339  DCHECK(instr->value()->representation().IsTagged());
2340 
2341  LStoreKeyedGeneric* result =
2342  new(zone()) LStoreKeyedGeneric(context, object, key, value);
2343  return MarkAsCall(result, instr);
2344 }
2345 
2346 
2347 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2348  HTransitionElementsKind* instr) {
2349  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2350  LOperand* object = UseRegister(instr->object());
2351  LOperand* new_map_reg = TempRegister();
2352  LOperand* temp_reg = TempRegister();
2353  LTransitionElementsKind* result =
2354  new(zone()) LTransitionElementsKind(object, NULL,
2355  new_map_reg, temp_reg);
2356  return result;
2357  } else {
2358  LOperand* object = UseFixed(instr->object(), eax);
2359  LOperand* context = UseFixed(instr->context(), esi);
2360  LTransitionElementsKind* result =
2361  new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
2362  return MarkAsCall(result, instr);
2363  }
2364 }
2365 
2366 
2367 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2368  HTrapAllocationMemento* instr) {
2369  LOperand* object = UseRegister(instr->object());
2370  LOperand* temp = TempRegister();
2371  LTrapAllocationMemento* result =
2372  new(zone()) LTrapAllocationMemento(object, temp);
2373  return AssignEnvironment(result);
2374 }
2375 
2376 
2377 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2378  bool is_in_object = instr->access().IsInobject();
2379  bool is_external_location = instr->access().IsExternalMemory() &&
2380  instr->access().offset() == 0;
2381  bool needs_write_barrier = instr->NeedsWriteBarrier();
2382  bool needs_write_barrier_for_map = instr->has_transition() &&
2383  instr->NeedsWriteBarrierForMap();
2384 
2385  LOperand* obj;
2386  if (needs_write_barrier) {
2387  obj = is_in_object
2388  ? UseRegister(instr->object())
2389  : UseTempRegister(instr->object());
2390  } else if (is_external_location) {
2391  DCHECK(!is_in_object);
2392  DCHECK(!needs_write_barrier);
2393  DCHECK(!needs_write_barrier_for_map);
2394  obj = UseRegisterOrConstant(instr->object());
2395  } else {
2396  obj = needs_write_barrier_for_map
2397  ? UseRegister(instr->object())
2398  : UseRegisterAtStart(instr->object());
2399  }
2400 
2401  bool can_be_constant = instr->value()->IsConstant() &&
2402  HConstant::cast(instr->value())->NotInNewSpace() &&
2403  !instr->field_representation().IsDouble();
2404 
2405  LOperand* val;
2406  if (instr->field_representation().IsInteger8() ||
2407  instr->field_representation().IsUInteger8()) {
2408  // mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx).
2409  // Just force the value to be in eax and we're safe here.
2410  val = UseFixed(instr->value(), eax);
2411  } else if (needs_write_barrier) {
2412  val = UseTempRegister(instr->value());
2413  } else if (can_be_constant) {
2414  val = UseRegisterOrConstant(instr->value());
2415  } else if (instr->field_representation().IsDouble()) {
2416  val = UseRegisterAtStart(instr->value());
2417  } else {
2418  val = UseRegister(instr->value());
2419  }
2420 
2421  // We only need a scratch register if we have a write barrier or we
2422  // have a store into the properties array (not in-object-property).
2423  LOperand* temp = (!is_in_object || needs_write_barrier ||
2424  needs_write_barrier_for_map) ? TempRegister() : NULL;
2425 
2426  // We need a temporary register for write barrier of the map field.
2427  LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
2428 
2429  return new(zone()) LStoreNamedField(obj, val, temp, temp_map);
2430 }
2431 
2432 
2433 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2434  LOperand* context = UseFixed(instr->context(), esi);
2435  LOperand* object =
2436  UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
2437  LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
2438 
2439  LStoreNamedGeneric* result =
2440  new(zone()) LStoreNamedGeneric(context, object, value);
2441  return MarkAsCall(result, instr);
2442 }
2443 
2444 
2445 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2446  LOperand* context = UseFixed(instr->context(), esi);
2447  LOperand* left = UseFixed(instr->left(), edx);
2448  LOperand* right = UseFixed(instr->right(), eax);
2449  LStringAdd* string_add = new(zone()) LStringAdd(context, left, right);
2450  return MarkAsCall(DefineFixed(string_add, eax), instr);
2451 }
2452 
2453 
2454 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2455  LOperand* string = UseTempRegister(instr->string());
2456  LOperand* index = UseTempRegister(instr->index());
2457  LOperand* context = UseAny(instr->context());
2458  LStringCharCodeAt* result =
2459  new(zone()) LStringCharCodeAt(context, string, index);
2460  return AssignPointerMap(DefineAsRegister(result));
2461 }
2462 
2463 
2464 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2465  LOperand* char_code = UseRegister(instr->value());
2466  LOperand* context = UseAny(instr->context());
2467  LStringCharFromCode* result =
2468  new(zone()) LStringCharFromCode(context, char_code);
2469  return AssignPointerMap(DefineAsRegister(result));
2470 }
2471 
2472 
2473 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2474  info()->MarkAsDeferredCalling();
2475  LOperand* context = UseAny(instr->context());
2476  LOperand* size = instr->size()->IsConstant()
2477  ? UseConstant(instr->size())
2478  : UseTempRegister(instr->size());
2479  LOperand* temp = TempRegister();
2480  LAllocate* result = new(zone()) LAllocate(context, size, temp);
2481  return AssignPointerMap(DefineAsRegister(result));
2482 }
2483 
2484 
2485 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2486  LOperand* context = UseFixed(instr->context(), esi);
2487  return MarkAsCall(
2488  DefineFixed(new(zone()) LRegExpLiteral(context), eax), instr);
2489 }
2490 
2491 
2492 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2493  LOperand* context = UseFixed(instr->context(), esi);
2494  return MarkAsCall(
2495  DefineFixed(new(zone()) LFunctionLiteral(context), eax), instr);
2496 }
2497 
2498 
2499 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2500  DCHECK(argument_count_ == 0);
2501  allocator_->MarkAsOsrEntry();
2502  current_block_->last_environment()->set_ast_id(instr->ast_id());
2503  return AssignEnvironment(new(zone()) LOsrEntry);
2504 }
2505 
2506 
2507 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2508  LParameter* result = new(zone()) LParameter;
2509  if (instr->kind() == HParameter::STACK_PARAMETER) {
2510  int spill_index = chunk()->GetParameterStackSlot(instr->index());
2511  return DefineAsSpilled(result, spill_index);
2512  } else {
2513  DCHECK(info()->IsStub());
2514  CallInterfaceDescriptor descriptor =
2515  info()->code_stub()->GetCallInterfaceDescriptor();
2516  int index = static_cast<int>(instr->index());
2517  Register reg = descriptor.GetEnvironmentParameterRegister(index);
2518  return DefineFixed(result, reg);
2519  }
2520 }
2521 
2522 
2523 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2524  // Use an index that corresponds to the location in the unoptimized frame,
2525  // which the optimized frame will subsume.
2526  int env_index = instr->index();
2527  int spill_index = 0;
2528  if (instr->environment()->is_parameter_index(env_index)) {
2529  spill_index = chunk()->GetParameterStackSlot(env_index);
2530  } else {
2531  spill_index = env_index - instr->environment()->first_local_index();
2532  if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2533  Retry(kNotEnoughSpillSlotsForOsr);
2534  spill_index = 0;
2535  }
2536  if (spill_index == 0) {
2537  // The dynamic frame alignment state overwrites the first local.
2538  // The first local is saved at the end of the unoptimized frame.
2539  spill_index = graph()->osr()->UnoptimizedFrameSlots();
2540  }
2541  }
2542  return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2543 }
2544 
2545 
2546 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2547  LOperand* context = UseFixed(instr->context(), esi);
2548  LCallStub* result = new(zone()) LCallStub(context);
2549  return MarkAsCall(DefineFixed(result, eax), instr);
2550 }
2551 
2552 
2553 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2554  // There are no real uses of the arguments object.
2555  // arguments.length and element access are supported directly on
2556  // stack arguments, and any real arguments object use causes a bailout.
2557  // So this value is never used.
2558  return NULL;
2559 }
2560 
2561 
2562 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2563  instr->ReplayEnvironment(current_block_->last_environment());
2564 
2565  // There are no real uses of a captured object.
2566  return NULL;
2567 }
2568 
2569 
2570 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2571  info()->MarkAsRequiresFrame();
2572  LOperand* args = UseRegister(instr->arguments());
2573  LOperand* length;
2574  LOperand* index;
2575  if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2576  length = UseRegisterOrConstant(instr->length());
2577  index = UseOrConstant(instr->index());
2578  } else {
2579  length = UseTempRegister(instr->length());
2580  index = Use(instr->index());
2581  }
2582  return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2583 }
2584 
2585 
2586 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2587  LOperand* object = UseFixed(instr->value(), eax);
2588  LToFastProperties* result = new(zone()) LToFastProperties(object);
2589  return MarkAsCall(DefineFixed(result, eax), instr);
2590 }
2591 
2592 
2593 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2594  LOperand* context = UseFixed(instr->context(), esi);
2595  LOperand* value = UseAtStart(instr->value());
2596  LTypeof* result = new(zone()) LTypeof(context, value);
2597  return MarkAsCall(DefineFixed(result, eax), instr);
2598 }
2599 
2600 
2601 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2602  return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2603 }
2604 
2605 
2606 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2607  HIsConstructCallAndBranch* instr) {
2608  return new(zone()) LIsConstructCallAndBranch(TempRegister());
2609 }
2610 
2611 
2612 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2613  instr->ReplayEnvironment(current_block_->last_environment());
2614  return NULL;
2615 }
2616 
2617 
2618 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2619  info()->MarkAsDeferredCalling();
2620  if (instr->is_function_entry()) {
2621  LOperand* context = UseFixed(instr->context(), esi);
2622  return MarkAsCall(new(zone()) LStackCheck(context), instr);
2623  } else {
2624  DCHECK(instr->is_backwards_branch());
2625  LOperand* context = UseAny(instr->context());
2626  return AssignEnvironment(
2627  AssignPointerMap(new(zone()) LStackCheck(context)));
2628  }
2629 }
2630 
2631 
2632 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2633  HEnvironment* outer = current_block_->last_environment();
2634  outer->set_ast_id(instr->ReturnId());
2635  HConstant* undefined = graph()->GetConstantUndefined();
2636  HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2637  instr->arguments_count(),
2638  instr->function(),
2639  undefined,
2640  instr->inlining_kind());
2641  // Only replay binding of arguments object if it wasn't removed from graph.
2642  if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2643  inner->Bind(instr->arguments_var(), instr->arguments_object());
2644  }
2645  inner->BindContext(instr->closure_context());
2646  inner->set_entry(instr);
2647  current_block_->UpdateEnvironment(inner);
2648  chunk_->AddInlinedClosure(instr->closure());
2649  return NULL;
2650 }
2651 
2652 
2653 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2654  LInstruction* pop = NULL;
2655 
2656  HEnvironment* env = current_block_->last_environment();
2657 
2658  if (env->entry()->arguments_pushed()) {
2659  int argument_count = env->arguments_environment()->parameter_count();
2660  pop = new(zone()) LDrop(argument_count);
2661  DCHECK(instr->argument_delta() == -argument_count);
2662  }
2663 
2664  HEnvironment* outer = current_block_->last_environment()->
2665  DiscardInlined(false);
2666  current_block_->UpdateEnvironment(outer);
2667  return pop;
2668 }
2669 
2670 
2671 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2672  LOperand* context = UseFixed(instr->context(), esi);
2673  LOperand* object = UseFixed(instr->enumerable(), eax);
2674  LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2675  return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2676 }
2677 
2678 
2679 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2680  LOperand* map = UseRegister(instr->map());
2681  return AssignEnvironment(DefineAsRegister(
2682  new(zone()) LForInCacheArray(map)));
2683 }
2684 
2685 
2686 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2687  LOperand* value = UseRegisterAtStart(instr->value());
2688  LOperand* map = UseRegisterAtStart(instr->map());
2689  return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2690 }
2691 
2692 
2693 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2694  LOperand* object = UseRegister(instr->object());
2695  LOperand* index = UseTempRegister(instr->index());
2696  LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index);
2697  LInstruction* result = DefineSameAsFirst(load);
2698  return AssignPointerMap(result);
2699 }
2700 
2701 
2702 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) {
2703  LOperand* context = UseRegisterAtStart(instr->context());
2704  return new(zone()) LStoreFrameContext(context);
2705 }
2706 
2707 
2708 LInstruction* LChunkBuilder::DoAllocateBlockContext(
2709  HAllocateBlockContext* instr) {
2710  LOperand* context = UseFixed(instr->context(), esi);
2711  LOperand* function = UseRegisterAtStart(instr->function());
2712  LAllocateBlockContext* result =
2713  new(zone()) LAllocateBlockContext(context, function);
2714  return MarkAsCall(DefineFixed(result, esi), instr);
2715 }
2716 
2717 
2718 } } // namespace v8::internal
2719 
2720 #endif // V8_TARGET_ARCH_X87
static HValue * cast(HValue *value)
static Register right()
Definition: code-stubs.h:686
static Register left()
Definition: code-stubs.h:685
bool IsRedundant() const
Definition: lithium-arm.cc:89
virtual void PrintDataTo(StringStream *stream) OVERRIDE
Definition: lithium-arm.cc:100
LParallelMove * parallel_moves_[LAST_INNER_POSITION+1]
Definition: lithium-arm.h:367
virtual int InputCount()=0
virtual bool HasResult() const =0
virtual const char * Mnemonic() const =0
virtual void PrintTo(StringStream *stream)
Definition: lithium-arm.cc:43
LEnvironment * environment() const
Definition: lithium-arm.h:231
virtual LOperand * InputAt(int i)=0
virtual void PrintDataTo(StringStream *stream)
Definition: lithium-arm.cc:62
virtual LOperand * result() const =0
virtual void PrintOutputOperandTo(StringStream *stream)
Definition: lithium-arm.cc:75
bool IsDoubleInput(X87Register reg, LCodeGen *cgen)
LPointerMap * pointer_map() const
Definition: lithium-arm.h:235
void PrintDataTo(StringStream *stream) OVERRIDE
uint32_t base_offset() const
void PrintTo(StringStream *stream)
Definition: lithium.cc:41
void PrintDataTo(StringStream *stream) OVERRIDE
uint32_t base_offset() const
static LUnallocated * cast(LOperand *op)
Definition: lithium.h:138
static const int kMaxFixedSlotIndex
Definition: lithium.h:177
bool HasFixedPolicy() const
Definition: lithium.h:185
static const Register ReceiverRegister()
static const Register NameRegister()
static Representation Tagged()
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register ValueRegister()
static const char * String(Value tok)
Definition: token.h:276
static const Register VectorRegister()
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DEFINE_COMPILE(type)
Definition: lithium-arm.cc:14
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
Definition: lithium-arm.h:20
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
void USE(T)
Definition: macros.h:322
int int32_t
Definition: unicode.cc:24
bool IsDoubleOrFloatElementsKind(ElementsKind kind)
const Register edx
const Register edi
static bool ExternalArrayOpRequiresTemp(Representation key_representation, ElementsKind elements_kind)
@ UINT8_CLAMPED_ELEMENTS
Definition: elements-kind.h:52
@ EXTERNAL_UINT8_ELEMENTS
Definition: elements-kind.h:34
@ EXTERNAL_INT8_ELEMENTS
Definition: elements-kind.h:33
@ EXTERNAL_UINT32_ELEMENTS
Definition: elements-kind.h:38
@ EXTERNAL_UINT8_CLAMPED_ELEMENTS
Definition: elements-kind.h:41
bool IsSimpleMapChangeTransition(ElementsKind from_kind, ElementsKind to_kind)
const char * ElementsKindToString(ElementsKind kind)
const Register esi
const Register eax
const Register ebx
@ GENERAL_REGISTERS
Definition: lithium.h:780
@ DOUBLE_REGISTERS
Definition: lithium.h:781
const Register ecx
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static i::Handle< i::Context > CreateEnvironment(i::Isolate *isolate, v8::ExtensionConfiguration *extensions, v8::Handle< ObjectTemplate > global_template, v8::Handle< Value > maybe_global_proxy)
Definition: api.cc:5151
static int ToAllocationIndex(Register reg)
static int ToAllocationIndex(X87Register reg)