1 // Copyright 2014 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/crankshaft/s390/lithium-s390.h"
6
7 #include <sstream>
8
9 #include "src/crankshaft/hydrogen-osr.h"
10 #include "src/crankshaft/lithium-inl.h"
11 #include "src/crankshaft/s390/lithium-codegen-s390.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 }
LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
21 #undef DEFINE_COMPILE
22
23 #ifdef DEBUG
24 void LInstruction::VerifyCall() {
25 // Call instructions can use only fixed registers as temporaries and
26 // outputs because all registers are blocked by the calling convention.
27 // Inputs operands must use a fixed register or use-at-start policy or
28 // a non-register policy.
29 DCHECK(Output() == NULL || LUnallocated::cast(Output())->HasFixedPolicy() ||
30 !LUnallocated::cast(Output())->HasRegisterPolicy());
31 for (UseIterator it(this); !it.Done(); it.Advance()) {
32 LUnallocated* operand = LUnallocated::cast(it.Current());
33 DCHECK(operand->HasFixedPolicy() || operand->IsUsedAtStart());
34 }
35 for (TempIterator it(this); !it.Done(); it.Advance()) {
36 LUnallocated* operand = LUnallocated::cast(it.Current());
37 DCHECK(operand->HasFixedPolicy() || !operand->HasRegisterPolicy());
38 }
39 }
40 #endif
41
PrintTo(StringStream * stream)42 void LInstruction::PrintTo(StringStream* stream) {
43 stream->Add("%s ", this->Mnemonic());
44
45 PrintOutputOperandTo(stream);
46
47 PrintDataTo(stream);
48
49 if (HasEnvironment()) {
50 stream->Add(" ");
51 environment()->PrintTo(stream);
52 }
53
54 if (HasPointerMap()) {
55 stream->Add(" ");
56 pointer_map()->PrintTo(stream);
57 }
58 }
59
PrintDataTo(StringStream * stream)60 void LInstruction::PrintDataTo(StringStream* stream) {
61 stream->Add("= ");
62 for (int i = 0; i < InputCount(); i++) {
63 if (i > 0) stream->Add(" ");
64 if (InputAt(i) == NULL) {
65 stream->Add("NULL");
66 } else {
67 InputAt(i)->PrintTo(stream);
68 }
69 }
70 }
71
PrintOutputOperandTo(StringStream * stream)72 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
73 if (HasResult()) result()->PrintTo(stream);
74 }
75
PrintDataTo(StringStream * stream)76 void LLabel::PrintDataTo(StringStream* stream) {
77 LGap::PrintDataTo(stream);
78 LLabel* rep = replacement();
79 if (rep != NULL) {
80 stream->Add(" Dead block replaced with B%d", rep->block_id());
81 }
82 }
83
IsRedundant() const84 bool LGap::IsRedundant() const {
85 for (int i = 0; i < 4; i++) {
86 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
87 return false;
88 }
89 }
90
91 return true;
92 }
93
PrintDataTo(StringStream * stream)94 void LGap::PrintDataTo(StringStream* stream) {
95 for (int i = 0; i < 4; i++) {
96 stream->Add("(");
97 if (parallel_moves_[i] != NULL) {
98 parallel_moves_[i]->PrintDataTo(stream);
99 }
100 stream->Add(") ");
101 }
102 }
103
Mnemonic() const104 const char* LArithmeticD::Mnemonic() const {
105 switch (op()) {
106 case Token::ADD:
107 return "add-d";
108 case Token::SUB:
109 return "sub-d";
110 case Token::MUL:
111 return "mul-d";
112 case Token::DIV:
113 return "div-d";
114 case Token::MOD:
115 return "mod-d";
116 default:
117 UNREACHABLE();
118 return NULL;
119 }
120 }
121
Mnemonic() const122 const char* LArithmeticT::Mnemonic() const {
123 switch (op()) {
124 case Token::ADD:
125 return "add-t";
126 case Token::SUB:
127 return "sub-t";
128 case Token::MUL:
129 return "mul-t";
130 case Token::MOD:
131 return "mod-t";
132 case Token::DIV:
133 return "div-t";
134 case Token::BIT_AND:
135 return "bit-and-t";
136 case Token::BIT_OR:
137 return "bit-or-t";
138 case Token::BIT_XOR:
139 return "bit-xor-t";
140 case Token::ROR:
141 return "ror-t";
142 case Token::SHL:
143 return "shl-t";
144 case Token::SAR:
145 return "sar-t";
146 case Token::SHR:
147 return "shr-t";
148 default:
149 UNREACHABLE();
150 return NULL;
151 }
152 }
153
HasInterestingComment(LCodeGen * gen) const154 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
155 return !gen->IsNextEmittedBlock(block_id());
156 }
157
PrintDataTo(StringStream * stream)158 void LGoto::PrintDataTo(StringStream* stream) {
159 stream->Add("B%d", block_id());
160 }
161
PrintDataTo(StringStream * stream)162 void LBranch::PrintDataTo(StringStream* stream) {
163 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
164 value()->PrintTo(stream);
165 }
166
PrintDataTo(StringStream * stream)167 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
168 stream->Add("if ");
169 left()->PrintTo(stream);
170 stream->Add(" %s ", Token::String(op()));
171 right()->PrintTo(stream);
172 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
173 }
174
PrintDataTo(StringStream * stream)175 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
176 stream->Add("if is_string(");
177 value()->PrintTo(stream);
178 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
179 }
180
PrintDataTo(StringStream * stream)181 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
182 stream->Add("if is_smi(");
183 value()->PrintTo(stream);
184 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
185 }
186
PrintDataTo(StringStream * stream)187 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
188 stream->Add("if is_undetectable(");
189 value()->PrintTo(stream);
190 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
191 }
192
PrintDataTo(StringStream * stream)193 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
194 stream->Add("if string_compare(");
195 left()->PrintTo(stream);
196 right()->PrintTo(stream);
197 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
198 }
199
PrintDataTo(StringStream * stream)200 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
201 stream->Add("if has_instance_type(");
202 value()->PrintTo(stream);
203 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
204 }
205
PrintDataTo(StringStream * stream)206 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
207 stream->Add("if class_of_test(");
208 value()->PrintTo(stream);
209 stream->Add(", \"%o\") then B%d else B%d", *hydrogen()->class_name(),
210 true_block_id(), false_block_id());
211 }
212
PrintDataTo(StringStream * stream)213 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
214 stream->Add("if typeof ");
215 value()->PrintTo(stream);
216 stream->Add(" == \"%s\" then B%d else B%d",
217 hydrogen()->type_literal()->ToCString().get(), true_block_id(),
218 false_block_id());
219 }
220
PrintDataTo(StringStream * stream)221 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
222 stream->Add(" = ");
223 function()->PrintTo(stream);
224 stream->Add(".code_entry = ");
225 code_object()->PrintTo(stream);
226 }
227
PrintDataTo(StringStream * stream)228 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
229 stream->Add(" = ");
230 base_object()->PrintTo(stream);
231 stream->Add(" + ");
232 offset()->PrintTo(stream);
233 }
234
PrintDataTo(StringStream * stream)235 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
236 for (int i = 0; i < InputCount(); i++) {
237 InputAt(i)->PrintTo(stream);
238 stream->Add(" ");
239 }
240 stream->Add("#%d / ", arity());
241 }
242
PrintDataTo(StringStream * stream)243 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
244 context()->PrintTo(stream);
245 stream->Add("[%d]", slot_index());
246 }
247
PrintDataTo(StringStream * stream)248 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
249 context()->PrintTo(stream);
250 stream->Add("[%d] <- ", slot_index());
251 value()->PrintTo(stream);
252 }
253
PrintDataTo(StringStream * stream)254 void LInvokeFunction::PrintDataTo(StringStream* stream) {
255 stream->Add("= ");
256 function()->PrintTo(stream);
257 stream->Add(" #%d / ", arity());
258 }
259
PrintDataTo(StringStream * stream)260 void LCallNewArray::PrintDataTo(StringStream* stream) {
261 stream->Add("= ");
262 constructor()->PrintTo(stream);
263 stream->Add(" #%d / ", arity());
264 ElementsKind kind = hydrogen()->elements_kind();
265 stream->Add(" (%s) ", ElementsKindToString(kind));
266 }
267
PrintDataTo(StringStream * stream)268 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
269 arguments()->PrintTo(stream);
270 stream->Add(" length ");
271 length()->PrintTo(stream);
272 stream->Add(" index ");
273 index()->PrintTo(stream);
274 }
275
PrintDataTo(StringStream * stream)276 void LStoreNamedField::PrintDataTo(StringStream* stream) {
277 object()->PrintTo(stream);
278 std::ostringstream os;
279 os << hydrogen()->access() << " <- ";
280 stream->Add(os.str().c_str());
281 value()->PrintTo(stream);
282 }
283
PrintDataTo(StringStream * stream)284 void LLoadKeyed::PrintDataTo(StringStream* stream) {
285 elements()->PrintTo(stream);
286 stream->Add("[");
287 key()->PrintTo(stream);
288 if (hydrogen()->IsDehoisted()) {
289 stream->Add(" + %d]", base_offset());
290 } else {
291 stream->Add("]");
292 }
293 }
294
PrintDataTo(StringStream * stream)295 void LStoreKeyed::PrintDataTo(StringStream* stream) {
296 elements()->PrintTo(stream);
297 stream->Add("[");
298 key()->PrintTo(stream);
299 if (hydrogen()->IsDehoisted()) {
300 stream->Add(" + %d] <-", base_offset());
301 } else {
302 stream->Add("] <- ");
303 }
304
305 if (value() == NULL) {
306 DCHECK(hydrogen()->IsConstantHoleStore() &&
307 hydrogen()->value()->representation().IsDouble());
308 stream->Add("<the hole(nan)>");
309 } else {
310 value()->PrintTo(stream);
311 }
312 }
313
PrintDataTo(StringStream * stream)314 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
315 object()->PrintTo(stream);
316 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
317 }
318
GetNextSpillIndex(RegisterKind kind)319 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
320 // Skip a slot if for a double-width slot.
321 if (kind == DOUBLE_REGISTERS) current_frame_slots_++;
322 return current_frame_slots_++;
323 }
324
GetNextSpillSlot(RegisterKind kind)325 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
326 int index = GetNextSpillIndex(kind);
327 if (kind == DOUBLE_REGISTERS) {
328 return LDoubleStackSlot::Create(index, zone());
329 } else {
330 DCHECK(kind == GENERAL_REGISTERS);
331 return LStackSlot::Create(index, zone());
332 }
333 }
334
Build()335 LPlatformChunk* LChunkBuilder::Build() {
336 DCHECK(is_unused());
337 chunk_ = new (zone()) LPlatformChunk(info(), graph());
338 LPhase phase("L_Building chunk", chunk_);
339 status_ = BUILDING;
340
341 // If compiling for OSR, reserve space for the unoptimized frame,
342 // which will be subsumed into this frame.
343 if (graph()->has_osr()) {
344 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
345 chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
346 }
347 }
348
349 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
350 for (int i = 0; i < blocks->length(); i++) {
351 HBasicBlock* next = NULL;
352 if (i < blocks->length() - 1) next = blocks->at(i + 1);
353 DoBasicBlock(blocks->at(i), next);
354 if (is_aborted()) return NULL;
355 }
356 status_ = DONE;
357 return chunk_;
358 }
359
ToUnallocated(Register reg)360 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
361 return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
362 }
363
ToUnallocated(DoubleRegister reg)364 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
365 return new (zone())
366 LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
367 }
368
UseFixed(HValue * value,Register fixed_register)369 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
370 return Use(value, ToUnallocated(fixed_register));
371 }
372
UseFixedDouble(HValue * value,DoubleRegister reg)373 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
374 return Use(value, ToUnallocated(reg));
375 }
376
UseRegister(HValue * value)377 LOperand* LChunkBuilder::UseRegister(HValue* value) {
378 return Use(value,
379 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
380 }
381
UseRegisterAtStart(HValue * value)382 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
383 return Use(value, new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
384 LUnallocated::USED_AT_START));
385 }
386
UseTempRegister(HValue * value)387 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
388 return Use(value, new (zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
389 }
390
Use(HValue * value)391 LOperand* LChunkBuilder::Use(HValue* value) {
392 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE));
393 }
394
UseAtStart(HValue * value)395 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
396 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE,
397 LUnallocated::USED_AT_START));
398 }
399
UseOrConstant(HValue * value)400 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
401 return value->IsConstant()
402 ? chunk_->DefineConstantOperand(HConstant::cast(value))
403 : Use(value);
404 }
405
UseOrConstantAtStart(HValue * value)406 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
407 return value->IsConstant()
408 ? chunk_->DefineConstantOperand(HConstant::cast(value))
409 : UseAtStart(value);
410 }
411
UseRegisterOrConstant(HValue * value)412 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
413 return value->IsConstant()
414 ? chunk_->DefineConstantOperand(HConstant::cast(value))
415 : UseRegister(value);
416 }
417
UseRegisterOrConstantAtStart(HValue * value)418 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
419 return value->IsConstant()
420 ? chunk_->DefineConstantOperand(HConstant::cast(value))
421 : UseRegisterAtStart(value);
422 }
423
UseConstant(HValue * value)424 LOperand* LChunkBuilder::UseConstant(HValue* value) {
425 return chunk_->DefineConstantOperand(HConstant::cast(value));
426 }
427
UseAny(HValue * value)428 LOperand* LChunkBuilder::UseAny(HValue* value) {
429 return value->IsConstant()
430 ? chunk_->DefineConstantOperand(HConstant::cast(value))
431 : Use(value, new (zone()) LUnallocated(LUnallocated::ANY));
432 }
433
Use(HValue * value,LUnallocated * operand)434 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
435 if (value->EmitAtUses()) {
436 HInstruction* instr = HInstruction::cast(value);
437 VisitInstruction(instr);
438 }
439 operand->set_virtual_register(value->id());
440 return operand;
441 }
442
Define(LTemplateResultInstruction<1> * instr,LUnallocated * result)443 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
444 LUnallocated* result) {
445 result->set_virtual_register(current_instruction_->id());
446 instr->set_result(result);
447 return instr;
448 }
449
DefineAsRegister(LTemplateResultInstruction<1> * instr)450 LInstruction* LChunkBuilder::DefineAsRegister(
451 LTemplateResultInstruction<1>* instr) {
452 return Define(instr,
453 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
454 }
455
DefineAsSpilled(LTemplateResultInstruction<1> * instr,int index)456 LInstruction* LChunkBuilder::DefineAsSpilled(
457 LTemplateResultInstruction<1>* instr, int index) {
458 return Define(instr,
459 new (zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
460 }
461
DefineSameAsFirst(LTemplateResultInstruction<1> * instr)462 LInstruction* LChunkBuilder::DefineSameAsFirst(
463 LTemplateResultInstruction<1>* instr) {
464 return Define(instr,
465 new (zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
466 }
467
DefineFixed(LTemplateResultInstruction<1> * instr,Register reg)468 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr,
469 Register reg) {
470 return Define(instr, ToUnallocated(reg));
471 }
472
DefineFixedDouble(LTemplateResultInstruction<1> * instr,DoubleRegister reg)473 LInstruction* LChunkBuilder::DefineFixedDouble(
474 LTemplateResultInstruction<1>* instr, DoubleRegister reg) {
475 return Define(instr, ToUnallocated(reg));
476 }
477
AssignEnvironment(LInstruction * instr)478 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
479 HEnvironment* hydrogen_env = current_block_->last_environment();
480 return LChunkBuilderBase::AssignEnvironment(instr, hydrogen_env);
481 }
482
MarkAsCall(LInstruction * instr,HInstruction * hinstr,CanDeoptimize can_deoptimize)483 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
484 HInstruction* hinstr,
485 CanDeoptimize can_deoptimize) {
486 info()->MarkAsNonDeferredCalling();
487 #ifdef DEBUG
488 instr->VerifyCall();
489 #endif
490 instr->MarkAsCall();
491 instr = AssignPointerMap(instr);
492
493 // If instruction does not have side-effects lazy deoptimization
494 // after the call will try to deoptimize to the point before the call.
495 // Thus we still need to attach environment to this call even if
496 // call sequence can not deoptimize eagerly.
497 bool needs_environment = (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
498 !hinstr->HasObservableSideEffects();
499 if (needs_environment && !instr->HasEnvironment()) {
500 instr = AssignEnvironment(instr);
501 // We can't really figure out if the environment is needed or not.
502 instr->environment()->set_has_been_used();
503 }
504
505 return instr;
506 }
507
AssignPointerMap(LInstruction * instr)508 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
509 DCHECK(!instr->HasPointerMap());
510 instr->set_pointer_map(new (zone()) LPointerMap(zone()));
511 return instr;
512 }
513
TempRegister()514 LUnallocated* LChunkBuilder::TempRegister() {
515 LUnallocated* operand =
516 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
517 int vreg = allocator_->GetVirtualRegister();
518 if (!allocator_->AllocationOk()) {
519 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
520 vreg = 0;
521 }
522 operand->set_virtual_register(vreg);
523 return operand;
524 }
525
TempDoubleRegister()526 LUnallocated* LChunkBuilder::TempDoubleRegister() {
527 LUnallocated* operand =
528 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER);
529 int vreg = allocator_->GetVirtualRegister();
530 if (!allocator_->AllocationOk()) {
531 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
532 vreg = 0;
533 }
534 operand->set_virtual_register(vreg);
535 return operand;
536 }
537
FixedTemp(Register reg)538 LOperand* LChunkBuilder::FixedTemp(Register reg) {
539 LUnallocated* operand = ToUnallocated(reg);
540 DCHECK(operand->HasFixedPolicy());
541 return operand;
542 }
543
FixedTemp(DoubleRegister reg)544 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
545 LUnallocated* operand = ToUnallocated(reg);
546 DCHECK(operand->HasFixedPolicy());
547 return operand;
548 }
549
DoBlockEntry(HBlockEntry * instr)550 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
551 return new (zone()) LLabel(instr->block());
552 }
553
DoDummyUse(HDummyUse * instr)554 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
555 return DefineAsRegister(new (zone()) LDummyUse(UseAny(instr->value())));
556 }
557
DoEnvironmentMarker(HEnvironmentMarker * instr)558 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
559 UNREACHABLE();
560 return NULL;
561 }
562
DoDeoptimize(HDeoptimize * instr)563 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
564 return AssignEnvironment(new (zone()) LDeoptimize);
565 }
566
DoShift(Token::Value op,HBitwiseBinaryOperation * instr)567 LInstruction* LChunkBuilder::DoShift(Token::Value op,
568 HBitwiseBinaryOperation* instr) {
569 if (instr->representation().IsSmiOrInteger32()) {
570 DCHECK(instr->left()->representation().Equals(instr->representation()));
571 DCHECK(instr->right()->representation().Equals(instr->representation()));
572 LOperand* left = UseRegisterAtStart(instr->left());
573
574 HValue* right_value = instr->right();
575 LOperand* right = NULL;
576 int constant_value = 0;
577 bool does_deopt = false;
578 if (right_value->IsConstant()) {
579 HConstant* constant = HConstant::cast(right_value);
580 right = chunk_->DefineConstantOperand(constant);
581 constant_value = constant->Integer32Value() & 0x1f;
582 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
583 // truncated to smi.
584 if (instr->representation().IsSmi() && constant_value > 0) {
585 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
586 }
587 } else {
588 right = UseRegisterAtStart(right_value);
589 }
590
591 // Shift operations can only deoptimize if we do a logical shift
592 // by 0 and the result cannot be truncated to int32.
593 if (op == Token::SHR && constant_value == 0) {
594 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
595 }
596
597 LInstruction* result =
598 DefineAsRegister(new (zone()) LShiftI(op, left, right, does_deopt));
599 return does_deopt ? AssignEnvironment(result) : result;
600 } else {
601 return DoArithmeticT(op, instr);
602 }
603 }
604
DoArithmeticD(Token::Value op,HArithmeticBinaryOperation * instr)605 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
606 HArithmeticBinaryOperation* instr) {
607 DCHECK(instr->representation().IsDouble());
608 DCHECK(instr->left()->representation().IsDouble());
609 DCHECK(instr->right()->representation().IsDouble());
610 if (op == Token::MOD) {
611 LOperand* left = UseFixedDouble(instr->left(), d1);
612 LOperand* right = UseFixedDouble(instr->right(), d2);
613 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right);
614 // We call a C function for double modulo. It can't trigger a GC. We need
615 // to use fixed result register for the call.
616 // TODO(fschneider): Allow any register as input registers.
617 return MarkAsCall(DefineFixedDouble(result, d1), instr);
618 } else {
619 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
620 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
621 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right);
622 return CpuFeatures::IsSupported(VECTOR_FACILITY)
623 ? DefineAsRegister(result)
624 : DefineSameAsFirst(result);
625 }
626 }
627
DoArithmeticT(Token::Value op,HBinaryOperation * instr)628 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
629 HBinaryOperation* instr) {
630 HValue* left = instr->left();
631 HValue* right = instr->right();
632 DCHECK(left->representation().IsTagged());
633 DCHECK(right->representation().IsTagged());
634 LOperand* context = UseFixed(instr->context(), cp);
635 LOperand* left_operand = UseFixed(left, r3);
636 LOperand* right_operand = UseFixed(right, r2);
637 LArithmeticT* result =
638 new (zone()) LArithmeticT(op, context, left_operand, right_operand);
639 return MarkAsCall(DefineFixed(result, r2), instr);
640 }
641
DoBasicBlock(HBasicBlock * block,HBasicBlock * next_block)642 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
643 DCHECK(is_building());
644 current_block_ = block;
645 next_block_ = next_block;
646 if (block->IsStartBlock()) {
647 block->UpdateEnvironment(graph_->start_environment());
648 argument_count_ = 0;
649 } else if (block->predecessors()->length() == 1) {
650 // We have a single predecessor => copy environment and outgoing
651 // argument count from the predecessor.
652 DCHECK(block->phis()->length() == 0);
653 HBasicBlock* pred = block->predecessors()->at(0);
654 HEnvironment* last_environment = pred->last_environment();
655 DCHECK(last_environment != NULL);
656 // Only copy the environment, if it is later used again.
657 if (pred->end()->SecondSuccessor() == NULL) {
658 DCHECK(pred->end()->FirstSuccessor() == block);
659 } else {
660 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
661 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
662 last_environment = last_environment->Copy();
663 }
664 }
665 block->UpdateEnvironment(last_environment);
666 DCHECK(pred->argument_count() >= 0);
667 argument_count_ = pred->argument_count();
668 } else {
669 // We are at a state join => process phis.
670 HBasicBlock* pred = block->predecessors()->at(0);
671 // No need to copy the environment, it cannot be used later.
672 HEnvironment* last_environment = pred->last_environment();
673 for (int i = 0; i < block->phis()->length(); ++i) {
674 HPhi* phi = block->phis()->at(i);
675 if (phi->HasMergedIndex()) {
676 last_environment->SetValueAt(phi->merged_index(), phi);
677 }
678 }
679 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
680 if (block->deleted_phis()->at(i) < last_environment->length()) {
681 last_environment->SetValueAt(block->deleted_phis()->at(i),
682 graph_->GetConstantUndefined());
683 }
684 }
685 block->UpdateEnvironment(last_environment);
686 // Pick up the outgoing argument count of one of the predecessors.
687 argument_count_ = pred->argument_count();
688 }
689 HInstruction* current = block->first();
690 int start = chunk_->instructions()->length();
691 while (current != NULL && !is_aborted()) {
692 // Code for constants in registers is generated lazily.
693 if (!current->EmitAtUses()) {
694 VisitInstruction(current);
695 }
696 current = current->next();
697 }
698 int end = chunk_->instructions()->length() - 1;
699 if (end >= start) {
700 block->set_first_instruction_index(start);
701 block->set_last_instruction_index(end);
702 }
703 block->set_argument_count(argument_count_);
704 next_block_ = NULL;
705 current_block_ = NULL;
706 }
707
VisitInstruction(HInstruction * current)708 void LChunkBuilder::VisitInstruction(HInstruction* current) {
709 HInstruction* old_current = current_instruction_;
710 current_instruction_ = current;
711
712 LInstruction* instr = NULL;
713 if (current->CanReplaceWithDummyUses()) {
714 if (current->OperandCount() == 0) {
715 instr = DefineAsRegister(new (zone()) LDummy());
716 } else {
717 DCHECK(!current->OperandAt(0)->IsControlInstruction());
718 instr = DefineAsRegister(new (zone())
719 LDummyUse(UseAny(current->OperandAt(0))));
720 }
721 for (int i = 1; i < current->OperandCount(); ++i) {
722 if (current->OperandAt(i)->IsControlInstruction()) continue;
723 LInstruction* dummy =
724 new (zone()) LDummyUse(UseAny(current->OperandAt(i)));
725 dummy->set_hydrogen_value(current);
726 chunk_->AddInstruction(dummy, current_block_);
727 }
728 } else {
729 HBasicBlock* successor;
730 if (current->IsControlInstruction() &&
731 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
732 successor != NULL) {
733 instr = new (zone()) LGoto(successor);
734 } else {
735 instr = current->CompileToLithium(this);
736 }
737 }
738
739 argument_count_ += current->argument_delta();
740 DCHECK(argument_count_ >= 0);
741
742 if (instr != NULL) {
743 AddInstruction(instr, current);
744 }
745
746 current_instruction_ = old_current;
747 }
748
AddInstruction(LInstruction * instr,HInstruction * hydrogen_val)749 void LChunkBuilder::AddInstruction(LInstruction* instr,
750 HInstruction* hydrogen_val) {
751 // Associate the hydrogen instruction first, since we may need it for
752 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
753 instr->set_hydrogen_value(hydrogen_val);
754
755 #if DEBUG
756 // Make sure that the lithium instruction has either no fixed register
757 // constraints in temps or the result OR no uses that are only used at
758 // start. If this invariant doesn't hold, the register allocator can decide
759 // to insert a split of a range immediately before the instruction due to an
760 // already allocated register needing to be used for the instruction's fixed
761 // register constraint. In this case, The register allocator won't see an
762 // interference between the split child and the use-at-start (it would if
763 // the it was just a plain use), so it is free to move the split child into
764 // the same register that is used for the use-at-start.
765 // See https://code.google.com/p/chromium/issues/detail?id=201590
766 if (!(instr->ClobbersRegisters() &&
767 instr->ClobbersDoubleRegisters(isolate()))) {
768 int fixed = 0;
769 int used_at_start = 0;
770 for (UseIterator it(instr); !it.Done(); it.Advance()) {
771 LUnallocated* operand = LUnallocated::cast(it.Current());
772 if (operand->IsUsedAtStart()) ++used_at_start;
773 }
774 if (instr->Output() != NULL) {
775 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
776 }
777 for (TempIterator it(instr); !it.Done(); it.Advance()) {
778 LUnallocated* operand = LUnallocated::cast(it.Current());
779 if (operand->HasFixedPolicy()) ++fixed;
780 }
781 DCHECK(fixed == 0 || used_at_start == 0);
782 }
783 #endif
784
785 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
786 instr = AssignPointerMap(instr);
787 }
788 if (FLAG_stress_environments && !instr->HasEnvironment()) {
789 instr = AssignEnvironment(instr);
790 }
791 chunk_->AddInstruction(instr, current_block_);
792
793 CreateLazyBailoutForCall(current_block_, instr, hydrogen_val);
794 }
795
DoPrologue(HPrologue * instr)796 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
797 LInstruction* result = new (zone()) LPrologue();
798 if (info_->scope()->NeedsContext()) {
799 result = MarkAsCall(result, instr);
800 }
801 return result;
802 }
803
DoGoto(HGoto * instr)804 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
805 return new (zone()) LGoto(instr->FirstSuccessor());
806 }
807
DoBranch(HBranch * instr)808 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
809 HValue* value = instr->value();
810 Representation r = value->representation();
811 HType type = value->type();
812 ToBooleanHints expected = instr->expected_input_types();
813 if (expected == ToBooleanHint::kNone) expected = ToBooleanHint::kAny;
814
815 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
816 type.IsJSArray() || type.IsHeapNumber() || type.IsString();
817 LInstruction* branch = new (zone()) LBranch(UseRegister(value));
818 if (!easy_case && ((!(expected & ToBooleanHint::kSmallInteger) &&
819 (expected & ToBooleanHint::kNeedsMap)) ||
820 expected != ToBooleanHint::kAny)) {
821 branch = AssignEnvironment(branch);
822 }
823 return branch;
824 }
825
DoDebugBreak(HDebugBreak * instr)826 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
827 return new (zone()) LDebugBreak();
828 }
829
DoCompareMap(HCompareMap * instr)830 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
831 DCHECK(instr->value()->representation().IsTagged());
832 LOperand* value = UseRegister(instr->value());
833 LOperand* temp = TempRegister();
834 return new (zone()) LCmpMapAndBranch(value, temp);
835 }
836
DoArgumentsLength(HArgumentsLength * instr)837 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
838 info()->MarkAsRequiresFrame();
839 LOperand* value = UseRegister(instr->value());
840 return DefineAsRegister(new (zone()) LArgumentsLength(value));
841 }
842
DoArgumentsElements(HArgumentsElements * elems)843 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
844 info()->MarkAsRequiresFrame();
845 return DefineAsRegister(new (zone()) LArgumentsElements);
846 }
847
DoHasInPrototypeChainAndBranch(HHasInPrototypeChainAndBranch * instr)848 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
849 HHasInPrototypeChainAndBranch* instr) {
850 LOperand* object = UseRegister(instr->object());
851 LOperand* prototype = UseRegister(instr->prototype());
852 LHasInPrototypeChainAndBranch* result =
853 new (zone()) LHasInPrototypeChainAndBranch(object, prototype);
854 return AssignEnvironment(result);
855 }
856
DoWrapReceiver(HWrapReceiver * instr)857 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
858 LOperand* receiver = UseRegisterAtStart(instr->receiver());
859 LOperand* function = UseRegisterAtStart(instr->function());
860 LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function);
861 return AssignEnvironment(DefineAsRegister(result));
862 }
863
DoApplyArguments(HApplyArguments * instr)864 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
865 LOperand* function = UseFixed(instr->function(), r3);
866 LOperand* receiver = UseFixed(instr->receiver(), r2);
867 LOperand* length = UseFixed(instr->length(), r4);
868 LOperand* elements = UseFixed(instr->elements(), r5);
869 LApplyArguments* result =
870 new (zone()) LApplyArguments(function, receiver, length, elements);
871 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY);
872 }
873
DoPushArguments(HPushArguments * instr)874 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
875 int argc = instr->OperandCount();
876 for (int i = 0; i < argc; ++i) {
877 LOperand* argument = Use(instr->argument(i));
878 AddInstruction(new (zone()) LPushArgument(argument), instr);
879 }
880 return NULL;
881 }
882
DoStoreCodeEntry(HStoreCodeEntry * store_code_entry)883 LInstruction* LChunkBuilder::DoStoreCodeEntry(
884 HStoreCodeEntry* store_code_entry) {
885 LOperand* function = UseRegister(store_code_entry->function());
886 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
887 return new (zone()) LStoreCodeEntry(function, code_object);
888 }
889
DoInnerAllocatedObject(HInnerAllocatedObject * instr)890 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
891 HInnerAllocatedObject* instr) {
892 LOperand* base_object = UseRegisterAtStart(instr->base_object());
893 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
894 return DefineAsRegister(new (zone())
895 LInnerAllocatedObject(base_object, offset));
896 }
897
DoThisFunction(HThisFunction * instr)898 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
899 return instr->HasNoUses() ? NULL
900 : DefineAsRegister(new (zone()) LThisFunction);
901 }
902
DoContext(HContext * instr)903 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
904 if (instr->HasNoUses()) return NULL;
905
906 if (info()->IsStub()) {
907 return DefineFixed(new (zone()) LContext, cp);
908 }
909
910 return DefineAsRegister(new (zone()) LContext);
911 }
912
DoDeclareGlobals(HDeclareGlobals * instr)913 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
914 LOperand* context = UseFixed(instr->context(), cp);
915 return MarkAsCall(new (zone()) LDeclareGlobals(context), instr);
916 }
917
DoCallWithDescriptor(HCallWithDescriptor * instr)918 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) {
919 CallInterfaceDescriptor descriptor = instr->descriptor();
920 DCHECK_EQ(descriptor.GetParameterCount() +
921 LCallWithDescriptor::kImplicitRegisterParameterCount,
922 instr->OperandCount());
923
924 LOperand* target = UseRegisterOrConstantAtStart(instr->target());
925 ZoneList<LOperand*> ops(instr->OperandCount(), zone());
926 // Target
927 ops.Add(target, zone());
928 // Context
929 LOperand* op = UseFixed(instr->OperandAt(1), cp);
930 ops.Add(op, zone());
931 // Load register parameters.
932 int i = 0;
933 for (; i < descriptor.GetRegisterParameterCount(); i++) {
934 op = UseFixed(instr->OperandAt(
935 i + LCallWithDescriptor::kImplicitRegisterParameterCount),
936 descriptor.GetRegisterParameter(i));
937 ops.Add(op, zone());
938 }
939 // Push stack parameters.
940 for (; i < descriptor.GetParameterCount(); i++) {
941 op = UseAny(instr->OperandAt(
942 i + LCallWithDescriptor::kImplicitRegisterParameterCount));
943 AddInstruction(new (zone()) LPushArgument(op), instr);
944 }
945
946 LCallWithDescriptor* result =
947 new (zone()) LCallWithDescriptor(descriptor, ops, zone());
948 if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
949 result->MarkAsSyntacticTailCall();
950 }
951 return MarkAsCall(DefineFixed(result, r2), instr);
952 }
953
DoInvokeFunction(HInvokeFunction * instr)954 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
955 LOperand* context = UseFixed(instr->context(), cp);
956 LOperand* function = UseFixed(instr->function(), r3);
957 LInvokeFunction* result = new (zone()) LInvokeFunction(context, function);
958 if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
959 result->MarkAsSyntacticTailCall();
960 }
961 return MarkAsCall(DefineFixed(result, r2), instr, CANNOT_DEOPTIMIZE_EAGERLY);
962 }
963
DoUnaryMathOperation(HUnaryMathOperation * instr)964 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
965 switch (instr->op()) {
966 case kMathFloor:
967 return DoMathFloor(instr);
968 case kMathRound:
969 return DoMathRound(instr);
970 case kMathFround:
971 return DoMathFround(instr);
972 case kMathAbs:
973 return DoMathAbs(instr);
974 case kMathLog:
975 return DoMathLog(instr);
976 case kMathCos:
977 return DoMathCos(instr);
978 case kMathSin:
979 return DoMathSin(instr);
980 case kMathExp:
981 return DoMathExp(instr);
982 case kMathSqrt:
983 return DoMathSqrt(instr);
984 case kMathPowHalf:
985 return DoMathPowHalf(instr);
986 case kMathClz32:
987 return DoMathClz32(instr);
988 default:
989 UNREACHABLE();
990 return NULL;
991 }
992 }
993
DoMathFloor(HUnaryMathOperation * instr)994 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
995 LOperand* input = UseRegister(instr->value());
996 LMathFloor* result = new (zone()) LMathFloor(input);
997 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
998 }
999
DoMathRound(HUnaryMathOperation * instr)1000 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1001 LOperand* input = UseRegister(instr->value());
1002 LOperand* temp = TempDoubleRegister();
1003 LMathRound* result = new (zone()) LMathRound(input, temp);
1004 return AssignEnvironment(DefineAsRegister(result));
1005 }
1006
DoMathFround(HUnaryMathOperation * instr)1007 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) {
1008 LOperand* input = UseRegister(instr->value());
1009 LMathFround* result = new (zone()) LMathFround(input);
1010 return DefineAsRegister(result);
1011 }
1012
DoMathAbs(HUnaryMathOperation * instr)1013 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1014 Representation r = instr->value()->representation();
1015 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32())
1016 ? NULL
1017 : UseFixed(instr->context(), cp);
1018 LOperand* input = UseRegister(instr->value());
1019 LInstruction* result =
1020 DefineAsRegister(new (zone()) LMathAbs(context, input));
1021 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result);
1022 if (!r.IsDouble()) result = AssignEnvironment(result);
1023 return result;
1024 }
1025
DoMathLog(HUnaryMathOperation * instr)1026 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1027 DCHECK(instr->representation().IsDouble());
1028 DCHECK(instr->value()->representation().IsDouble());
1029 LOperand* input = UseFixedDouble(instr->value(), d0);
1030 return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d0), instr);
1031 }
1032
DoMathClz32(HUnaryMathOperation * instr)1033 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) {
1034 LOperand* input = UseRegisterAtStart(instr->value());
1035 LMathClz32* result = new (zone()) LMathClz32(input);
1036 return DefineAsRegister(result);
1037 }
1038
DoMathCos(HUnaryMathOperation * instr)1039 LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1040 DCHECK(instr->representation().IsDouble());
1041 DCHECK(instr->value()->representation().IsDouble());
1042 LOperand* input = UseFixedDouble(instr->value(), d0);
1043 return MarkAsCall(DefineFixedDouble(new (zone()) LMathCos(input), d0), instr);
1044 }
1045
DoMathSin(HUnaryMathOperation * instr)1046 LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1047 DCHECK(instr->representation().IsDouble());
1048 DCHECK(instr->value()->representation().IsDouble());
1049 LOperand* input = UseFixedDouble(instr->value(), d0);
1050 return MarkAsCall(DefineFixedDouble(new (zone()) LMathSin(input), d0), instr);
1051 }
1052
DoMathExp(HUnaryMathOperation * instr)1053 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1054 DCHECK(instr->representation().IsDouble());
1055 DCHECK(instr->value()->representation().IsDouble());
1056 LOperand* input = UseFixedDouble(instr->value(), d0);
1057 return MarkAsCall(DefineFixedDouble(new (zone()) LMathExp(input), d0), instr);
1058 }
1059
DoMathSqrt(HUnaryMathOperation * instr)1060 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1061 LOperand* input = UseAtStart(instr->value());
1062 LMathSqrt* result = new (zone()) LMathSqrt(input);
1063 return DefineAsRegister(result);
1064 }
1065
DoMathPowHalf(HUnaryMathOperation * instr)1066 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1067 LOperand* input = UseRegisterAtStart(instr->value());
1068 LMathPowHalf* result = new (zone()) LMathPowHalf(input);
1069 return DefineAsRegister(result);
1070 }
1071
DoCallNewArray(HCallNewArray * instr)1072 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1073 LOperand* context = UseFixed(instr->context(), cp);
1074 LOperand* constructor = UseFixed(instr->constructor(), r3);
1075 LCallNewArray* result = new (zone()) LCallNewArray(context, constructor);
1076 return MarkAsCall(DefineFixed(result, r2), instr);
1077 }
1078
DoCallRuntime(HCallRuntime * instr)1079 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1080 LOperand* context = UseFixed(instr->context(), cp);
1081 return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r2), instr);
1082 }
1083
DoRor(HRor * instr)1084 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1085 return DoShift(Token::ROR, instr);
1086 }
1087
DoShr(HShr * instr)1088 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1089 return DoShift(Token::SHR, instr);
1090 }
1091
DoSar(HSar * instr)1092 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1093 return DoShift(Token::SAR, instr);
1094 }
1095
DoShl(HShl * instr)1096 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1097 return DoShift(Token::SHL, instr);
1098 }
1099
DoBitwise(HBitwise * instr)1100 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1101 if (instr->representation().IsSmiOrInteger32()) {
1102 DCHECK(instr->left()->representation().Equals(instr->representation()));
1103 DCHECK(instr->right()->representation().Equals(instr->representation()));
1104 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32));
1105
1106 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1107 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1108 return DefineAsRegister(new (zone()) LBitI(left, right));
1109 } else {
1110 return DoArithmeticT(instr->op(), instr);
1111 }
1112 }
1113
DoDivByPowerOf2I(HDiv * instr)1114 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1115 DCHECK(instr->representation().IsSmiOrInteger32());
1116 DCHECK(instr->left()->representation().Equals(instr->representation()));
1117 DCHECK(instr->right()->representation().Equals(instr->representation()));
1118 LOperand* dividend = UseRegister(instr->left());
1119 int32_t divisor = instr->right()->GetInteger32Constant();
1120 LInstruction* result =
1121 DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor));
1122 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1123 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
1124 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1125 divisor != 1 && divisor != -1)) {
1126 result = AssignEnvironment(result);
1127 }
1128 return result;
1129 }
1130
DoDivByConstI(HDiv * instr)1131 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1132 DCHECK(instr->representation().IsInteger32());
1133 DCHECK(instr->left()->representation().Equals(instr->representation()));
1134 DCHECK(instr->right()->representation().Equals(instr->representation()));
1135 LOperand* dividend = UseRegister(instr->left());
1136 int32_t divisor = instr->right()->GetInteger32Constant();
1137 LInstruction* result =
1138 DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor));
1139 if (divisor == 0 ||
1140 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1141 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1142 result = AssignEnvironment(result);
1143 }
1144 return result;
1145 }
1146
DoDivI(HDiv * instr)1147 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
1148 DCHECK(instr->representation().IsSmiOrInteger32());
1149 DCHECK(instr->left()->representation().Equals(instr->representation()));
1150 DCHECK(instr->right()->representation().Equals(instr->representation()));
1151 LOperand* dividend = UseRegister(instr->left());
1152 LOperand* divisor = UseRegister(instr->right());
1153 LInstruction* result =
1154 DefineAsRegister(new (zone()) LDivI(dividend, divisor));
1155 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1156 instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1157 (instr->CheckFlag(HValue::kCanOverflow) &&
1158 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) ||
1159 (!instr->IsMathFloorOfDiv() &&
1160 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1161 result = AssignEnvironment(result);
1162 }
1163 return result;
1164 }
1165
DoDiv(HDiv * instr)1166 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1167 if (instr->representation().IsSmiOrInteger32()) {
1168 if (instr->RightIsPowerOf2()) {
1169 return DoDivByPowerOf2I(instr);
1170 } else if (instr->right()->IsConstant()) {
1171 return DoDivByConstI(instr);
1172 } else {
1173 return DoDivI(instr);
1174 }
1175 } else if (instr->representation().IsDouble()) {
1176 return DoArithmeticD(Token::DIV, instr);
1177 } else {
1178 return DoArithmeticT(Token::DIV, instr);
1179 }
1180 }
1181
DoFlooringDivByPowerOf2I(HMathFloorOfDiv * instr)1182 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1183 LOperand* dividend = UseRegisterAtStart(instr->left());
1184 int32_t divisor = instr->right()->GetInteger32Constant();
1185 LInstruction* result =
1186 DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor));
1187 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1188 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
1189 result = AssignEnvironment(result);
1190 }
1191 return result;
1192 }
1193
DoFlooringDivByConstI(HMathFloorOfDiv * instr)1194 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1195 DCHECK(instr->representation().IsInteger32());
1196 DCHECK(instr->left()->representation().Equals(instr->representation()));
1197 DCHECK(instr->right()->representation().Equals(instr->representation()));
1198 LOperand* dividend = UseRegister(instr->left());
1199 int32_t divisor = instr->right()->GetInteger32Constant();
1200 LOperand* temp =
1201 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
1202 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive)))
1203 ? NULL
1204 : TempRegister();
1205 LInstruction* result = DefineAsRegister(
1206 new (zone()) LFlooringDivByConstI(dividend, divisor, temp));
1207 if (divisor == 0 ||
1208 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
1209 result = AssignEnvironment(result);
1210 }
1211 return result;
1212 }
1213
DoFlooringDivI(HMathFloorOfDiv * instr)1214 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
1215 DCHECK(instr->representation().IsSmiOrInteger32());
1216 DCHECK(instr->left()->representation().Equals(instr->representation()));
1217 DCHECK(instr->right()->representation().Equals(instr->representation()));
1218 LOperand* dividend = UseRegister(instr->left());
1219 LOperand* divisor = UseRegister(instr->right());
1220 LInstruction* result =
1221 DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor));
1222 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1223 instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1224 (instr->CheckFlag(HValue::kCanOverflow) &&
1225 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1226 result = AssignEnvironment(result);
1227 }
1228 return result;
1229 }
1230
DoMathFloorOfDiv(HMathFloorOfDiv * instr)1231 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1232 if (instr->RightIsPowerOf2()) {
1233 return DoFlooringDivByPowerOf2I(instr);
1234 } else if (instr->right()->IsConstant()) {
1235 return DoFlooringDivByConstI(instr);
1236 } else {
1237 return DoFlooringDivI(instr);
1238 }
1239 }
1240
DoModByPowerOf2I(HMod * instr)1241 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1242 DCHECK(instr->representation().IsSmiOrInteger32());
1243 DCHECK(instr->left()->representation().Equals(instr->representation()));
1244 DCHECK(instr->right()->representation().Equals(instr->representation()));
1245 LOperand* dividend = UseRegisterAtStart(instr->left());
1246 int32_t divisor = instr->right()->GetInteger32Constant();
1247 LInstruction* result =
1248 DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor));
1249 if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
1250 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1251 result = AssignEnvironment(result);
1252 }
1253 return result;
1254 }
1255
DoModByConstI(HMod * instr)1256 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1257 DCHECK(instr->representation().IsSmiOrInteger32());
1258 DCHECK(instr->left()->representation().Equals(instr->representation()));
1259 DCHECK(instr->right()->representation().Equals(instr->representation()));
1260 LOperand* dividend = UseRegister(instr->left());
1261 int32_t divisor = instr->right()->GetInteger32Constant();
1262 LInstruction* result =
1263 DefineAsRegister(new (zone()) LModByConstI(dividend, divisor));
1264 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1265 result = AssignEnvironment(result);
1266 }
1267 return result;
1268 }
1269
DoModI(HMod * instr)1270 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1271 DCHECK(instr->representation().IsSmiOrInteger32());
1272 DCHECK(instr->left()->representation().Equals(instr->representation()));
1273 DCHECK(instr->right()->representation().Equals(instr->representation()));
1274 LOperand* dividend = UseRegister(instr->left());
1275 LOperand* divisor = UseRegister(instr->right());
1276 LInstruction* result =
1277 DefineAsRegister(new (zone()) LModI(dividend, divisor));
1278 if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
1279 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1280 result = AssignEnvironment(result);
1281 }
1282 return result;
1283 }
1284
DoMod(HMod * instr)1285 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1286 if (instr->representation().IsSmiOrInteger32()) {
1287 if (instr->RightIsPowerOf2()) {
1288 return DoModByPowerOf2I(instr);
1289 } else if (instr->right()->IsConstant()) {
1290 return DoModByConstI(instr);
1291 } else {
1292 return DoModI(instr);
1293 }
1294 } else if (instr->representation().IsDouble()) {
1295 return DoArithmeticD(Token::MOD, instr);
1296 } else {
1297 return DoArithmeticT(Token::MOD, instr);
1298 }
1299 }
1300
DoMul(HMul * instr)1301 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1302 if (instr->representation().IsSmiOrInteger32()) {
1303 DCHECK(instr->left()->representation().Equals(instr->representation()));
1304 DCHECK(instr->right()->representation().Equals(instr->representation()));
1305 HValue* left = instr->BetterLeftOperand();
1306 HValue* right = instr->BetterRightOperand();
1307 LOperand* left_op;
1308 LOperand* right_op;
1309 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1310 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
1311
1312 int32_t constant_value = 0;
1313 if (right->IsConstant()) {
1314 HConstant* constant = HConstant::cast(right);
1315 constant_value = constant->Integer32Value();
1316 // Constants -1, 0 and 1 can be optimized if the result can overflow.
1317 // For other constants, it can be optimized only without overflow.
1318 if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
1319 left_op = UseRegisterAtStart(left);
1320 right_op = UseConstant(right);
1321 } else {
1322 if (bailout_on_minus_zero) {
1323 left_op = UseRegister(left);
1324 } else {
1325 left_op = UseRegisterAtStart(left);
1326 }
1327 right_op = UseRegister(right);
1328 }
1329 } else {
1330 if (bailout_on_minus_zero) {
1331 left_op = UseRegister(left);
1332 } else {
1333 left_op = UseRegisterAtStart(left);
1334 }
1335 right_op = UseRegister(right);
1336 }
1337 LMulI* mul = new (zone()) LMulI(left_op, right_op);
1338 if (right_op->IsConstantOperand()
1339 ? ((can_overflow && constant_value == -1) ||
1340 (bailout_on_minus_zero && constant_value <= 0))
1341 : (can_overflow || bailout_on_minus_zero)) {
1342 AssignEnvironment(mul);
1343 }
1344 return DefineAsRegister(mul);
1345
1346 } else if (instr->representation().IsDouble()) {
1347 return DoArithmeticD(Token::MUL, instr);
1348 } else {
1349 return DoArithmeticT(Token::MUL, instr);
1350 }
1351 }
1352
DoSub(HSub * instr)1353 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1354 if (instr->representation().IsSmiOrInteger32()) {
1355 DCHECK(instr->left()->representation().Equals(instr->representation()));
1356 DCHECK(instr->right()->representation().Equals(instr->representation()));
1357
1358 LOperand* left = UseRegisterAtStart(instr->left());
1359 LOperand* right = UseOrConstantAtStart(instr->right());
1360 LSubI* sub = new (zone()) LSubI(left, right);
1361 LInstruction* result = DefineAsRegister(sub);
1362 if (instr->CheckFlag(HValue::kCanOverflow)) {
1363 result = AssignEnvironment(result);
1364 }
1365 return result;
1366 } else if (instr->representation().IsDouble()) {
1367 return DoArithmeticD(Token::SUB, instr);
1368 } else {
1369 return DoArithmeticT(Token::SUB, instr);
1370 }
1371 }
1372
DoMultiplyAdd(HMul * mul,HValue * addend)1373 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
1374 LOperand* multiplier_op = UseRegister(mul->left());
1375 LOperand* multiplicand_op = UseRegister(mul->right());
1376 LOperand* addend_op = UseRegister(addend);
1377 return DefineAsRegister(
1378 new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op));
1379 }
1380
DoMultiplySub(HValue * minuend,HMul * mul)1381 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
1382 LOperand* minuend_op = UseRegister(minuend);
1383 LOperand* multiplier_op = UseRegister(mul->left());
1384 LOperand* multiplicand_op = UseRegister(mul->right());
1385
1386 return DefineAsRegister(
1387 new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op));
1388 }
1389
DoAdd(HAdd * instr)1390 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1391 if (instr->representation().IsSmiOrInteger32()) {
1392 DCHECK(instr->left()->representation().Equals(instr->representation()));
1393 DCHECK(instr->right()->representation().Equals(instr->representation()));
1394 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1395 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1396 LAddI* add = new (zone()) LAddI(left, right);
1397 LInstruction* result = DefineAsRegister(add);
1398 if (instr->CheckFlag(HValue::kCanOverflow)) {
1399 result = AssignEnvironment(result);
1400 }
1401 return result;
1402 } else if (instr->representation().IsExternal()) {
1403 DCHECK(instr->IsConsistentExternalRepresentation());
1404 DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
1405 LOperand* left = UseRegisterAtStart(instr->left());
1406 LOperand* right = UseOrConstantAtStart(instr->right());
1407 LAddI* add = new (zone()) LAddI(left, right);
1408 LInstruction* result = DefineAsRegister(add);
1409 return result;
1410 } else if (instr->representation().IsDouble()) {
1411 return DoArithmeticD(Token::ADD, instr);
1412 } else {
1413 return DoArithmeticT(Token::ADD, instr);
1414 }
1415 }
1416
DoMathMinMax(HMathMinMax * instr)1417 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1418 LOperand* left = NULL;
1419 LOperand* right = NULL;
1420 if (instr->representation().IsSmiOrInteger32()) {
1421 DCHECK(instr->left()->representation().Equals(instr->representation()));
1422 DCHECK(instr->right()->representation().Equals(instr->representation()));
1423 left = UseRegisterAtStart(instr->BetterLeftOperand());
1424 right = UseOrConstantAtStart(instr->BetterRightOperand());
1425 } else {
1426 DCHECK(instr->representation().IsDouble());
1427 DCHECK(instr->left()->representation().IsDouble());
1428 DCHECK(instr->right()->representation().IsDouble());
1429 left = UseRegister(instr->left());
1430 right = UseRegister(instr->right());
1431 }
1432 return DefineAsRegister(new (zone()) LMathMinMax(left, right));
1433 }
1434
DoPower(HPower * instr)1435 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1436 DCHECK(instr->representation().IsDouble());
1437 // We call a C function for double power. It can't trigger a GC.
1438 // We need to use fixed result register for the call.
1439 Representation exponent_type = instr->right()->representation();
1440 DCHECK(instr->left()->representation().IsDouble());
1441 LOperand* left = UseFixedDouble(instr->left(), d1);
1442 LOperand* right = exponent_type.IsDouble()
1443 ? UseFixedDouble(instr->right(), d2)
1444 : UseFixed(instr->right(), r4);
1445 LPower* result = new (zone()) LPower(left, right);
1446 return MarkAsCall(DefineFixedDouble(result, d3), instr,
1447 CAN_DEOPTIMIZE_EAGERLY);
1448 }
1449
DoCompareGeneric(HCompareGeneric * instr)1450 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1451 DCHECK(instr->left()->representation().IsTagged());
1452 DCHECK(instr->right()->representation().IsTagged());
1453 LOperand* context = UseFixed(instr->context(), cp);
1454 LOperand* left = UseFixed(instr->left(), r3);
1455 LOperand* right = UseFixed(instr->right(), r2);
1456 LCmpT* result = new (zone()) LCmpT(context, left, right);
1457 return MarkAsCall(DefineFixed(result, r2), instr);
1458 }
1459
DoCompareNumericAndBranch(HCompareNumericAndBranch * instr)1460 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1461 HCompareNumericAndBranch* instr) {
1462 Representation r = instr->representation();
1463 if (r.IsSmiOrInteger32()) {
1464 DCHECK(instr->left()->representation().Equals(r));
1465 DCHECK(instr->right()->representation().Equals(r));
1466 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1467 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1468 return new (zone()) LCompareNumericAndBranch(left, right);
1469 } else {
1470 DCHECK(r.IsDouble());
1471 DCHECK(instr->left()->representation().IsDouble());
1472 DCHECK(instr->right()->representation().IsDouble());
1473 LOperand* left = UseRegisterAtStart(instr->left());
1474 LOperand* right = UseRegisterAtStart(instr->right());
1475 return new (zone()) LCompareNumericAndBranch(left, right);
1476 }
1477 }
1478
DoCompareObjectEqAndBranch(HCompareObjectEqAndBranch * instr)1479 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1480 HCompareObjectEqAndBranch* instr) {
1481 LOperand* left = UseRegisterAtStart(instr->left());
1482 LOperand* right = UseRegisterAtStart(instr->right());
1483 return new (zone()) LCmpObjectEqAndBranch(left, right);
1484 }
1485
DoCompareHoleAndBranch(HCompareHoleAndBranch * instr)1486 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1487 HCompareHoleAndBranch* instr) {
1488 LOperand* value = UseRegisterAtStart(instr->value());
1489 return new (zone()) LCmpHoleAndBranch(value);
1490 }
1491
DoIsStringAndBranch(HIsStringAndBranch * instr)1492 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1493 DCHECK(instr->value()->representation().IsTagged());
1494 LOperand* value = UseRegisterAtStart(instr->value());
1495 LOperand* temp = TempRegister();
1496 return new (zone()) LIsStringAndBranch(value, temp);
1497 }
1498
DoIsSmiAndBranch(HIsSmiAndBranch * instr)1499 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1500 DCHECK(instr->value()->representation().IsTagged());
1501 return new (zone()) LIsSmiAndBranch(Use(instr->value()));
1502 }
1503
DoIsUndetectableAndBranch(HIsUndetectableAndBranch * instr)1504 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1505 HIsUndetectableAndBranch* instr) {
1506 DCHECK(instr->value()->representation().IsTagged());
1507 LOperand* value = UseRegisterAtStart(instr->value());
1508 return new (zone()) LIsUndetectableAndBranch(value, TempRegister());
1509 }
1510
DoStringCompareAndBranch(HStringCompareAndBranch * instr)1511 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1512 HStringCompareAndBranch* instr) {
1513 DCHECK(instr->left()->representation().IsTagged());
1514 DCHECK(instr->right()->representation().IsTagged());
1515 LOperand* context = UseFixed(instr->context(), cp);
1516 LOperand* left = UseFixed(instr->left(), r3);
1517 LOperand* right = UseFixed(instr->right(), r2);
1518 LStringCompareAndBranch* result =
1519 new (zone()) LStringCompareAndBranch(context, left, right);
1520 return MarkAsCall(result, instr);
1521 }
1522
DoHasInstanceTypeAndBranch(HHasInstanceTypeAndBranch * instr)1523 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1524 HHasInstanceTypeAndBranch* instr) {
1525 DCHECK(instr->value()->representation().IsTagged());
1526 LOperand* value = UseRegisterAtStart(instr->value());
1527 return new (zone()) LHasInstanceTypeAndBranch(value);
1528 }
1529
DoClassOfTestAndBranch(HClassOfTestAndBranch * instr)1530 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1531 HClassOfTestAndBranch* instr) {
1532 DCHECK(instr->value()->representation().IsTagged());
1533 LOperand* value = UseRegister(instr->value());
1534 return new (zone()) LClassOfTestAndBranch(value, TempRegister());
1535 }
1536
DoSeqStringGetChar(HSeqStringGetChar * instr)1537 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1538 LOperand* string = UseRegisterAtStart(instr->string());
1539 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1540 return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index));
1541 }
1542
DoSeqStringSetChar(HSeqStringSetChar * instr)1543 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1544 LOperand* string = UseRegisterAtStart(instr->string());
1545 LOperand* index = FLAG_debug_code
1546 ? UseRegisterAtStart(instr->index())
1547 : UseRegisterOrConstantAtStart(instr->index());
1548 LOperand* value = UseRegisterAtStart(instr->value());
1549 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
1550 return new (zone()) LSeqStringSetChar(context, string, index, value);
1551 }
1552
DoBoundsCheck(HBoundsCheck * instr)1553 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1554 if (!FLAG_debug_code && instr->skip_check()) return NULL;
1555 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1556 LOperand* length = !index->IsConstantOperand()
1557 ? UseRegisterOrConstantAtStart(instr->length())
1558 : UseRegisterAtStart(instr->length());
1559 LInstruction* result = new (zone()) LBoundsCheck(index, length);
1560 if (!FLAG_debug_code || !instr->skip_check()) {
1561 result = AssignEnvironment(result);
1562 }
1563 return result;
1564 }
1565
DoAbnormalExit(HAbnormalExit * instr)1566 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1567 // The control instruction marking the end of a block that completed
1568 // abruptly (e.g., threw an exception). There is nothing specific to do.
1569 return NULL;
1570 }
1571
DoUseConst(HUseConst * instr)1572 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; }
1573
DoForceRepresentation(HForceRepresentation * bad)1574 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1575 // All HForceRepresentation instructions should be eliminated in the
1576 // representation change phase of Hydrogen.
1577 UNREACHABLE();
1578 return NULL;
1579 }
1580
DoChange(HChange * instr)1581 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1582 Representation from = instr->from();
1583 Representation to = instr->to();
1584 HValue* val = instr->value();
1585 if (from.IsSmi()) {
1586 if (to.IsTagged()) {
1587 LOperand* value = UseRegister(val);
1588 return DefineSameAsFirst(new (zone()) LDummyUse(value));
1589 }
1590 from = Representation::Tagged();
1591 }
1592 if (from.IsTagged()) {
1593 if (to.IsDouble()) {
1594 LOperand* value = UseRegister(val);
1595 LInstruction* result =
1596 DefineAsRegister(new (zone()) LNumberUntagD(value));
1597 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1598 return result;
1599 } else if (to.IsSmi()) {
1600 LOperand* value = UseRegister(val);
1601 if (val->type().IsSmi()) {
1602 return DefineSameAsFirst(new (zone()) LDummyUse(value));
1603 }
1604 return AssignEnvironment(
1605 DefineSameAsFirst(new (zone()) LCheckSmi(value)));
1606 } else {
1607 DCHECK(to.IsInteger32());
1608 if (val->type().IsSmi() || val->representation().IsSmi()) {
1609 LOperand* value = UseRegisterAtStart(val);
1610 return DefineAsRegister(new (zone()) LSmiUntag(value, false));
1611 } else {
1612 LOperand* value = UseRegister(val);
1613 LOperand* temp1 = TempRegister();
1614 LOperand* temp2 = TempDoubleRegister();
1615 LInstruction* result =
1616 DefineSameAsFirst(new (zone()) LTaggedToI(value, temp1, temp2));
1617 if (!val->representation().IsSmi()) result = AssignEnvironment(result);
1618 return result;
1619 }
1620 }
1621 } else if (from.IsDouble()) {
1622 if (to.IsTagged()) {
1623 info()->MarkAsDeferredCalling();
1624 LOperand* value = UseRegister(val);
1625 LOperand* temp1 = TempRegister();
1626 LOperand* temp2 = TempRegister();
1627 LUnallocated* result_temp = TempRegister();
1628 LNumberTagD* result = new (zone()) LNumberTagD(value, temp1, temp2);
1629 return AssignPointerMap(Define(result, result_temp));
1630 } else if (to.IsSmi()) {
1631 LOperand* value = UseRegister(val);
1632 return AssignEnvironment(
1633 DefineAsRegister(new (zone()) LDoubleToSmi(value)));
1634 } else {
1635 DCHECK(to.IsInteger32());
1636 LOperand* value = UseRegister(val);
1637 LInstruction* result = DefineAsRegister(new (zone()) LDoubleToI(value));
1638 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
1639 return result;
1640 }
1641 } else if (from.IsInteger32()) {
1642 info()->MarkAsDeferredCalling();
1643 if (to.IsTagged()) {
1644 if (!instr->CheckFlag(HValue::kCanOverflow)) {
1645 LOperand* value = UseRegisterAtStart(val);
1646 return DefineAsRegister(new (zone()) LSmiTag(value));
1647 } else if (val->CheckFlag(HInstruction::kUint32)) {
1648 LOperand* value = UseRegisterAtStart(val);
1649 LOperand* temp1 = TempRegister();
1650 LOperand* temp2 = TempRegister();
1651 LNumberTagU* result = new (zone()) LNumberTagU(value, temp1, temp2);
1652 return AssignPointerMap(DefineAsRegister(result));
1653 } else {
1654 LOperand* value = UseRegisterAtStart(val);
1655 LOperand* temp1 = TempRegister();
1656 LOperand* temp2 = TempRegister();
1657 LNumberTagI* result = new (zone()) LNumberTagI(value, temp1, temp2);
1658 return AssignPointerMap(DefineAsRegister(result));
1659 }
1660 } else if (to.IsSmi()) {
1661 LOperand* value = UseRegister(val);
1662 LInstruction* result = DefineAsRegister(new (zone()) LSmiTag(value));
1663 if (instr->CheckFlag(HValue::kCanOverflow)) {
1664 result = AssignEnvironment(result);
1665 }
1666 return result;
1667 } else {
1668 DCHECK(to.IsDouble());
1669 if (val->CheckFlag(HInstruction::kUint32)) {
1670 return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val)));
1671 } else {
1672 return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val)));
1673 }
1674 }
1675 }
1676 UNREACHABLE();
1677 return NULL;
1678 }
1679
DoCheckHeapObject(HCheckHeapObject * instr)1680 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
1681 LOperand* value = UseAtStart(instr->value());
1682 LInstruction* result = new (zone()) LCheckNonSmi(value);
1683 if (!instr->value()->type().IsHeapObject()) {
1684 result = AssignEnvironment(result);
1685 }
1686 return result;
1687 }
1688
DoCheckSmi(HCheckSmi * instr)1689 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1690 LOperand* value = UseAtStart(instr->value());
1691 return AssignEnvironment(new (zone()) LCheckSmi(value));
1692 }
1693
DoCheckArrayBufferNotNeutered(HCheckArrayBufferNotNeutered * instr)1694 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
1695 HCheckArrayBufferNotNeutered* instr) {
1696 LOperand* view = UseRegisterAtStart(instr->value());
1697 LCheckArrayBufferNotNeutered* result =
1698 new (zone()) LCheckArrayBufferNotNeutered(view);
1699 return AssignEnvironment(result);
1700 }
1701
DoCheckInstanceType(HCheckInstanceType * instr)1702 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1703 LOperand* value = UseRegisterAtStart(instr->value());
1704 LInstruction* result = new (zone()) LCheckInstanceType(value);
1705 return AssignEnvironment(result);
1706 }
1707
DoCheckValue(HCheckValue * instr)1708 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
1709 LOperand* value = UseRegisterAtStart(instr->value());
1710 return AssignEnvironment(new (zone()) LCheckValue(value));
1711 }
1712
DoCheckMaps(HCheckMaps * instr)1713 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1714 if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps;
1715 LOperand* value = UseRegisterAtStart(instr->value());
1716 LOperand* temp = TempRegister();
1717 LInstruction* result =
1718 AssignEnvironment(new (zone()) LCheckMaps(value, temp));
1719 if (instr->HasMigrationTarget()) {
1720 info()->MarkAsDeferredCalling();
1721 result = AssignPointerMap(result);
1722 }
1723 return result;
1724 }
1725
DoClampToUint8(HClampToUint8 * instr)1726 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1727 HValue* value = instr->value();
1728 Representation input_rep = value->representation();
1729 LOperand* reg = UseRegister(value);
1730 if (input_rep.IsDouble()) {
1731 return DefineAsRegister(new (zone()) LClampDToUint8(reg));
1732 } else if (input_rep.IsInteger32()) {
1733 return DefineAsRegister(new (zone()) LClampIToUint8(reg));
1734 } else {
1735 DCHECK(input_rep.IsSmiOrTagged());
1736 LClampTToUint8* result =
1737 new (zone()) LClampTToUint8(reg, TempDoubleRegister());
1738 return AssignEnvironment(DefineAsRegister(result));
1739 }
1740 }
1741
DoReturn(HReturn * instr)1742 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1743 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL;
1744 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1745 return new (zone())
1746 LReturn(UseFixed(instr->value(), r2), context, parameter_count);
1747 }
1748
DoConstant(HConstant * instr)1749 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1750 Representation r = instr->representation();
1751 if (r.IsSmi()) {
1752 return DefineAsRegister(new (zone()) LConstantS);
1753 } else if (r.IsInteger32()) {
1754 return DefineAsRegister(new (zone()) LConstantI);
1755 } else if (r.IsDouble()) {
1756 return DefineAsRegister(new (zone()) LConstantD);
1757 } else if (r.IsExternal()) {
1758 return DefineAsRegister(new (zone()) LConstantE);
1759 } else if (r.IsTagged()) {
1760 return DefineAsRegister(new (zone()) LConstantT);
1761 } else {
1762 UNREACHABLE();
1763 return NULL;
1764 }
1765 }
1766
DoLoadContextSlot(HLoadContextSlot * instr)1767 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1768 LOperand* context = UseRegisterAtStart(instr->value());
1769 LInstruction* result =
1770 DefineAsRegister(new (zone()) LLoadContextSlot(context));
1771 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
1772 result = AssignEnvironment(result);
1773 }
1774 return result;
1775 }
1776
DoStoreContextSlot(HStoreContextSlot * instr)1777 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1778 LOperand* context;
1779 LOperand* value;
1780 if (instr->NeedsWriteBarrier()) {
1781 context = UseTempRegister(instr->context());
1782 value = UseTempRegister(instr->value());
1783 } else {
1784 context = UseRegister(instr->context());
1785 value = UseRegister(instr->value());
1786 }
1787 LInstruction* result = new (zone()) LStoreContextSlot(context, value);
1788 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
1789 result = AssignEnvironment(result);
1790 }
1791 return result;
1792 }
1793
DoLoadNamedField(HLoadNamedField * instr)1794 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1795 LOperand* obj = UseRegisterAtStart(instr->object());
1796 return DefineAsRegister(new (zone()) LLoadNamedField(obj));
1797 }
1798
DoLoadFunctionPrototype(HLoadFunctionPrototype * instr)1799 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1800 HLoadFunctionPrototype* instr) {
1801 return AssignEnvironment(DefineAsRegister(
1802 new (zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
1803 }
1804
DoLoadRoot(HLoadRoot * instr)1805 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
1806 return DefineAsRegister(new (zone()) LLoadRoot);
1807 }
1808
DoLoadKeyed(HLoadKeyed * instr)1809 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
1810 DCHECK(instr->key()->representation().IsSmiOrInteger32());
1811 ElementsKind elements_kind = instr->elements_kind();
1812 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1813 LInstruction* result = NULL;
1814
1815 if (!instr->is_fixed_typed_array()) {
1816 LOperand* obj = NULL;
1817 if (instr->representation().IsDouble()) {
1818 obj = UseRegister(instr->elements());
1819 } else {
1820 obj = UseRegisterAtStart(instr->elements());
1821 }
1822 result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
1823 } else {
1824 DCHECK((instr->representation().IsInteger32() &&
1825 !IsDoubleOrFloatElementsKind(elements_kind)) ||
1826 (instr->representation().IsDouble() &&
1827 IsDoubleOrFloatElementsKind(elements_kind)));
1828 LOperand* backing_store = UseRegister(instr->elements());
1829 LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
1830 result = DefineAsRegister(
1831 new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
1832 }
1833
1834 bool needs_environment;
1835 if (instr->is_fixed_typed_array()) {
1836 // see LCodeGen::DoLoadKeyedExternalArray
1837 needs_environment = elements_kind == UINT32_ELEMENTS &&
1838 !instr->CheckFlag(HInstruction::kUint32);
1839 } else {
1840 // see LCodeGen::DoLoadKeyedFixedDoubleArray and
1841 // LCodeGen::DoLoadKeyedFixedArray
1842 needs_environment =
1843 instr->RequiresHoleCheck() ||
1844 (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub());
1845 }
1846
1847 if (needs_environment) {
1848 result = AssignEnvironment(result);
1849 }
1850 return result;
1851 }
1852
DoStoreKeyed(HStoreKeyed * instr)1853 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
1854 if (!instr->is_fixed_typed_array()) {
1855 DCHECK(instr->elements()->representation().IsTagged());
1856 bool needs_write_barrier = instr->NeedsWriteBarrier();
1857 LOperand* object = NULL;
1858 LOperand* key = NULL;
1859 LOperand* val = NULL;
1860
1861 if (instr->value()->representation().IsDouble()) {
1862 object = UseRegisterAtStart(instr->elements());
1863 val = UseRegister(instr->value());
1864 key = UseRegisterOrConstantAtStart(instr->key());
1865 } else {
1866 if (needs_write_barrier) {
1867 object = UseTempRegister(instr->elements());
1868 val = UseTempRegister(instr->value());
1869 key = UseTempRegister(instr->key());
1870 } else {
1871 object = UseRegisterAtStart(instr->elements());
1872 val = UseRegisterAtStart(instr->value());
1873 key = UseRegisterOrConstantAtStart(instr->key());
1874 }
1875 }
1876
1877 return new (zone()) LStoreKeyed(object, key, val, nullptr);
1878 }
1879
1880 DCHECK((instr->value()->representation().IsInteger32() &&
1881 !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
1882 (instr->value()->representation().IsDouble() &&
1883 IsDoubleOrFloatElementsKind(instr->elements_kind())));
1884 DCHECK(instr->elements()->representation().IsExternal());
1885 LOperand* val = UseRegister(instr->value());
1886 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1887 LOperand* backing_store = UseRegister(instr->elements());
1888 LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
1889 return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
1890 }
1891
DoTransitionElementsKind(HTransitionElementsKind * instr)1892 LInstruction* LChunkBuilder::DoTransitionElementsKind(
1893 HTransitionElementsKind* instr) {
1894 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
1895 LOperand* object = UseRegister(instr->object());
1896 LOperand* new_map_reg = TempRegister();
1897 LTransitionElementsKind* result =
1898 new (zone()) LTransitionElementsKind(object, NULL, new_map_reg);
1899 return result;
1900 } else {
1901 LOperand* object = UseFixed(instr->object(), r2);
1902 LOperand* context = UseFixed(instr->context(), cp);
1903 LTransitionElementsKind* result =
1904 new (zone()) LTransitionElementsKind(object, context, NULL);
1905 return MarkAsCall(result, instr);
1906 }
1907 }
1908
DoTrapAllocationMemento(HTrapAllocationMemento * instr)1909 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
1910 HTrapAllocationMemento* instr) {
1911 LOperand* object = UseRegister(instr->object());
1912 LOperand* temp1 = TempRegister();
1913 LOperand* temp2 = TempRegister();
1914 LTrapAllocationMemento* result =
1915 new (zone()) LTrapAllocationMemento(object, temp1, temp2);
1916 return AssignEnvironment(result);
1917 }
1918
DoMaybeGrowElements(HMaybeGrowElements * instr)1919 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) {
1920 info()->MarkAsDeferredCalling();
1921 LOperand* context = UseFixed(instr->context(), cp);
1922 LOperand* object = Use(instr->object());
1923 LOperand* elements = Use(instr->elements());
1924 LOperand* key = UseRegisterOrConstant(instr->key());
1925 LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity());
1926
1927 LMaybeGrowElements* result = new (zone())
1928 LMaybeGrowElements(context, object, elements, key, current_capacity);
1929 DefineFixed(result, r2);
1930 return AssignPointerMap(AssignEnvironment(result));
1931 }
1932
DoStoreNamedField(HStoreNamedField * instr)1933 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1934 bool is_in_object = instr->access().IsInobject();
1935 bool needs_write_barrier = instr->NeedsWriteBarrier();
1936 bool needs_write_barrier_for_map =
1937 instr->has_transition() && instr->NeedsWriteBarrierForMap();
1938
1939 LOperand* obj;
1940 if (needs_write_barrier) {
1941 obj = is_in_object ? UseRegister(instr->object())
1942 : UseTempRegister(instr->object());
1943 } else {
1944 obj = needs_write_barrier_for_map ? UseRegister(instr->object())
1945 : UseRegisterAtStart(instr->object());
1946 }
1947
1948 LOperand* val;
1949 if (needs_write_barrier) {
1950 val = UseTempRegister(instr->value());
1951 } else if (instr->field_representation().IsDouble()) {
1952 val = UseRegisterAtStart(instr->value());
1953 } else {
1954 val = UseRegister(instr->value());
1955 }
1956
1957 // We need a temporary register for write barrier of the map field.
1958 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
1959
1960 return new (zone()) LStoreNamedField(obj, val, temp);
1961 }
1962
DoStringAdd(HStringAdd * instr)1963 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1964 LOperand* context = UseFixed(instr->context(), cp);
1965 LOperand* left = UseFixed(instr->left(), r3);
1966 LOperand* right = UseFixed(instr->right(), r2);
1967 return MarkAsCall(
1968 DefineFixed(new (zone()) LStringAdd(context, left, right), r2), instr);
1969 }
1970
DoStringCharCodeAt(HStringCharCodeAt * instr)1971 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1972 LOperand* string = UseTempRegister(instr->string());
1973 LOperand* index = UseTempRegister(instr->index());
1974 LOperand* context = UseAny(instr->context());
1975 LStringCharCodeAt* result =
1976 new (zone()) LStringCharCodeAt(context, string, index);
1977 return AssignPointerMap(DefineAsRegister(result));
1978 }
1979
DoStringCharFromCode(HStringCharFromCode * instr)1980 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
1981 LOperand* char_code = UseRegister(instr->value());
1982 LOperand* context = UseAny(instr->context());
1983 LStringCharFromCode* result =
1984 new (zone()) LStringCharFromCode(context, char_code);
1985 return AssignPointerMap(DefineAsRegister(result));
1986 }
1987
DoAllocate(HAllocate * instr)1988 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
1989 LOperand* size = UseRegisterOrConstant(instr->size());
1990 LOperand* temp1 = TempRegister();
1991 LOperand* temp2 = TempRegister();
1992 if (instr->IsAllocationFolded()) {
1993 LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
1994 return DefineAsRegister(result);
1995 } else {
1996 info()->MarkAsDeferredCalling();
1997 LOperand* context = UseAny(instr->context());
1998 LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
1999 return AssignPointerMap(DefineAsRegister(result));
2000 }
2001 }
2002
DoOsrEntry(HOsrEntry * instr)2003 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2004 DCHECK(argument_count_ == 0);
2005 allocator_->MarkAsOsrEntry();
2006 current_block_->last_environment()->set_ast_id(instr->ast_id());
2007 return AssignEnvironment(new (zone()) LOsrEntry);
2008 }
2009
DoParameter(HParameter * instr)2010 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2011 LParameter* result = new (zone()) LParameter;
2012 if (instr->kind() == HParameter::STACK_PARAMETER) {
2013 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2014 return DefineAsSpilled(result, spill_index);
2015 } else {
2016 DCHECK(info()->IsStub());
2017 CallInterfaceDescriptor descriptor = graph()->descriptor();
2018 int index = static_cast<int>(instr->index());
2019 Register reg = descriptor.GetRegisterParameter(index);
2020 return DefineFixed(result, reg);
2021 }
2022 }
2023
DoUnknownOSRValue(HUnknownOSRValue * instr)2024 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2025 // Use an index that corresponds to the location in the unoptimized frame,
2026 // which the optimized frame will subsume.
2027 int env_index = instr->index();
2028 int spill_index = 0;
2029 if (instr->environment()->is_parameter_index(env_index)) {
2030 spill_index = chunk()->GetParameterStackSlot(env_index);
2031 } else {
2032 spill_index = env_index - instr->environment()->first_local_index();
2033 if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2034 Retry(kTooManySpillSlotsNeededForOSR);
2035 spill_index = 0;
2036 }
2037 spill_index += StandardFrameConstants::kFixedSlotCount;
2038 }
2039 return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index);
2040 }
2041
DoArgumentsObject(HArgumentsObject * instr)2042 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2043 // There are no real uses of the arguments object.
2044 // arguments.length and element access are supported directly on
2045 // stack arguments, and any real arguments object use causes a bailout.
2046 // So this value is never used.
2047 return NULL;
2048 }
2049
DoCapturedObject(HCapturedObject * instr)2050 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
2051 instr->ReplayEnvironment(current_block_->last_environment());
2052
2053 // There are no real uses of a captured object.
2054 return NULL;
2055 }
2056
DoAccessArgumentsAt(HAccessArgumentsAt * instr)2057 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2058 info()->MarkAsRequiresFrame();
2059 LOperand* args = UseRegister(instr->arguments());
2060 LOperand* length = UseRegisterOrConstantAtStart(instr->length());
2061 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
2062 return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index));
2063 }
2064
DoTypeof(HTypeof * instr)2065 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2066 LOperand* context = UseFixed(instr->context(), cp);
2067 LOperand* value = UseFixed(instr->value(), r5);
2068 LTypeof* result = new (zone()) LTypeof(context, value);
2069 return MarkAsCall(DefineFixed(result, r2), instr);
2070 }
2071
DoTypeofIsAndBranch(HTypeofIsAndBranch * instr)2072 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2073 return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
2074 }
2075
DoSimulate(HSimulate * instr)2076 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2077 instr->ReplayEnvironment(current_block_->last_environment());
2078 return NULL;
2079 }
2080
DoStackCheck(HStackCheck * instr)2081 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2082 if (instr->is_function_entry()) {
2083 LOperand* context = UseFixed(instr->context(), cp);
2084 return MarkAsCall(new (zone()) LStackCheck(context), instr);
2085 } else {
2086 DCHECK(instr->is_backwards_branch());
2087 LOperand* context = UseAny(instr->context());
2088 return AssignEnvironment(
2089 AssignPointerMap(new (zone()) LStackCheck(context)));
2090 }
2091 }
2092
DoEnterInlined(HEnterInlined * instr)2093 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2094 HEnvironment* outer = current_block_->last_environment();
2095 outer->set_ast_id(instr->ReturnId());
2096 HConstant* undefined = graph()->GetConstantUndefined();
2097 HEnvironment* inner = outer->CopyForInlining(
2098 instr->closure(), instr->arguments_count(), instr->function(), undefined,
2099 instr->inlining_kind(), instr->syntactic_tail_call_mode());
2100 // Only replay binding of arguments object if it wasn't removed from graph.
2101 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2102 inner->Bind(instr->arguments_var(), instr->arguments_object());
2103 }
2104 inner->BindContext(instr->closure_context());
2105 inner->set_entry(instr);
2106 current_block_->UpdateEnvironment(inner);
2107 return NULL;
2108 }
2109
DoLeaveInlined(HLeaveInlined * instr)2110 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2111 LInstruction* pop = NULL;
2112
2113 HEnvironment* env = current_block_->last_environment();
2114
2115 if (env->entry()->arguments_pushed()) {
2116 int argument_count = env->arguments_environment()->parameter_count();
2117 pop = new (zone()) LDrop(argument_count);
2118 DCHECK(instr->argument_delta() == -argument_count);
2119 }
2120
2121 HEnvironment* outer =
2122 current_block_->last_environment()->DiscardInlined(false);
2123 current_block_->UpdateEnvironment(outer);
2124
2125 return pop;
2126 }
2127
DoForInPrepareMap(HForInPrepareMap * instr)2128 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2129 LOperand* context = UseFixed(instr->context(), cp);
2130 LOperand* object = UseFixed(instr->enumerable(), r2);
2131 LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object);
2132 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY);
2133 }
2134
DoForInCacheArray(HForInCacheArray * instr)2135 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2136 LOperand* map = UseRegister(instr->map());
2137 return AssignEnvironment(
2138 DefineAsRegister(new (zone()) LForInCacheArray(map)));
2139 }
2140
DoCheckMapValue(HCheckMapValue * instr)2141 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2142 LOperand* value = UseRegisterAtStart(instr->value());
2143 LOperand* map = UseRegisterAtStart(instr->map());
2144 return AssignEnvironment(new (zone()) LCheckMapValue(value, map));
2145 }
2146
DoLoadFieldByIndex(HLoadFieldByIndex * instr)2147 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2148 LOperand* object = UseRegister(instr->object());
2149 LOperand* index = UseTempRegister(instr->index());
2150 LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index);
2151 LInstruction* result = DefineSameAsFirst(load);
2152 return AssignPointerMap(result);
2153 }
2154
2155 } // namespace internal
2156 } // namespace v8
2157