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