blob: 2bfbb67bce1525e2affa766c1ed727c51c800b61 [file] [log] [blame]
Ben Murdochc7cc0282012-03-05 14:35:55 +00001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002// 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
Ben Murdochb8e0da22011-05-16 14:20:40 +010028#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_IA32)
31
Steve Block1e0659c2011-05-24 12:43:12 +010032#include "lithium-allocator-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010033#include "ia32/lithium-ia32.h"
34#include "ia32/lithium-codegen-ia32.h"
35
36namespace v8 {
37namespace internal {
38
39#define DEFINE_COMPILE(type) \
40 void L##type::CompileToNative(LCodeGen* generator) { \
41 generator->Do##type(this); \
42 }
43LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
44#undef DEFINE_COMPILE
45
46LOsrEntry::LOsrEntry() {
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
56void 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
64void 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
Steve Block1e0659c2011-05-24 12:43:12 +010072#ifdef DEBUG
73void LInstruction::VerifyCall() {
Ben Murdoch257744e2011-11-30 15:57:28 +000074 // 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.
Steve Block1e0659c2011-05-24 12:43:12 +010078 ASSERT(Output() == NULL ||
79 LUnallocated::cast(Output())->HasFixedPolicy() ||
80 !LUnallocated::cast(Output())->HasRegisterPolicy());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000081 for (UseIterator it(this); !it.Done(); it.Advance()) {
82 LUnallocated* operand = LUnallocated::cast(it.Current());
Ben Murdoch257744e2011-11-30 15:57:28 +000083 ASSERT(operand->HasFixedPolicy() ||
84 operand->IsUsedAtStart());
Steve Block1e0659c2011-05-24 12:43:12 +010085 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000086 for (TempIterator it(this); !it.Done(); it.Advance()) {
87 LUnallocated* operand = LUnallocated::cast(it.Current());
Ben Murdoch257744e2011-11-30 15:57:28 +000088 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
Steve Block1e0659c2011-05-24 12:43:12 +010089 }
90}
91#endif
92
93
Ben Murdochb8e0da22011-05-16 14:20:40 +010094void LInstruction::PrintTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +010095 stream->Add("%s ", this->Mnemonic());
Steve Block1e0659c2011-05-24 12:43:12 +010096
97 PrintOutputOperandTo(stream);
Ben Murdochb8e0da22011-05-16 14:20:40 +010098
Ben Murdochb0fe1622011-05-05 13:52:32 +010099 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
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000113void LInstruction::PrintDataTo(StringStream* stream) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100114 stream->Add("= ");
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000115 for (int i = 0; i < InputCount(); i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000116 if (i > 0) stream->Add(" ");
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000117 InputAt(i)->PrintTo(stream);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000118 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100119}
120
121
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000122void LInstruction::PrintOutputOperandTo(StringStream* stream) {
123 if (HasResult()) result()->PrintTo(stream);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100124}
125
126
127void LLabel::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100128 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
Ben Murdochb0fe1622011-05-05 13:52:32 +0100136bool 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
Ben Murdochb8e0da22011-05-16 14:20:40 +0100147void LGap::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100148 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
158const 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
172const 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";
Steve Block1e0659c2011-05-24 12:43:12 +0100179 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";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185 default:
186 UNREACHABLE();
187 return NULL;
188 }
189}
190
191
Ben Murdochb8e0da22011-05-16 14:20:40 +0100192void LGoto::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100193 stream->Add("B%d", block_id());
194}
195
196
Ben Murdochb8e0da22011-05-16 14:20:40 +0100197void LBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100198 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100199 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100200}
201
202
Ben Murdochb8e0da22011-05-16 14:20:40 +0100203void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100204 stream->Add("if ");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100205 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100206 stream->Add(" %s ", Token::String(op()));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100207 InputAt(1)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100208 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
209}
210
211
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000212void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100213 stream->Add("if ");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100214 InputAt(0)->PrintTo(stream);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000215 stream->Add(kind() == kStrictEquality ? " === " : " == ");
216 stream->Add(nil() == kNullValue ? "null" : "undefined");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100217 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
218}
219
220
Ben Murdochb8e0da22011-05-16 14:20:40 +0100221void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100222 stream->Add("if is_object(");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100223 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
225}
226
227
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000228void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
229 stream->Add("if is_string(");
230 InputAt(0)->PrintTo(stream);
231 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
232}
233
234
Ben Murdochb8e0da22011-05-16 14:20:40 +0100235void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100236 stream->Add("if is_smi(");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100237 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100238 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
239}
240
241
Ben Murdoch257744e2011-11-30 15:57:28 +0000242void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
243 stream->Add("if is_undetectable(");
244 InputAt(0)->PrintTo(stream);
245 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
246}
247
248
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000249void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
250 stream->Add("if string_compare(");
251 InputAt(1)->PrintTo(stream);
252 InputAt(2)->PrintTo(stream);
253 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
254}
255
256
Ben Murdochb8e0da22011-05-16 14:20:40 +0100257void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100258 stream->Add("if has_instance_type(");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100259 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100260 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
261}
262
263
Ben Murdochb8e0da22011-05-16 14:20:40 +0100264void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100265 stream->Add("if has_cached_array_index(");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100266 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100267 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
268}
269
270
Ben Murdochb8e0da22011-05-16 14:20:40 +0100271void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100272 stream->Add("if class_of_test(");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100273 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100274 stream->Add(", \"%o\") then B%d else B%d",
275 *hydrogen()->class_name(),
276 true_block_id(),
277 false_block_id());
278}
279
280
Ben Murdochb8e0da22011-05-16 14:20:40 +0100281void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100282 stream->Add("if typeof ");
Ben Murdochb8e0da22011-05-16 14:20:40 +0100283 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100284 stream->Add(" == \"%s\" then B%d else B%d",
285 *hydrogen()->type_literal()->ToCString(),
286 true_block_id(), false_block_id());
287}
288
289
Ben Murdochb8e0da22011-05-16 14:20:40 +0100290void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100291 stream->Add("#%d / ", arity());
292}
293
294
Ben Murdochb8e0da22011-05-16 14:20:40 +0100295void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100296 stream->Add("/%s ", hydrogen()->OpName());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100297 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100298}
299
300
Ben Murdochc7cc0282012-03-05 14:35:55 +0000301void LMathPowHalf::PrintDataTo(StringStream* stream) {
302 stream->Add("/pow_half ");
303 InputAt(0)->PrintTo(stream);
304}
305
306
Ben Murdochb8e0da22011-05-16 14:20:40 +0100307void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100308 InputAt(0)->PrintTo(stream);
309 stream->Add("[%d]", slot_index());
310}
311
312
313void LStoreContextSlot::PrintDataTo(StringStream* stream) {
314 InputAt(0)->PrintTo(stream);
315 stream->Add("[%d] <- ", slot_index());
316 InputAt(1)->PrintTo(stream);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100317}
318
319
Ben Murdoch257744e2011-11-30 15:57:28 +0000320void LInvokeFunction::PrintDataTo(StringStream* stream) {
321 stream->Add("= ");
322 InputAt(0)->PrintTo(stream);
323 stream->Add(" ");
324 InputAt(1)->PrintTo(stream);
325 stream->Add(" #%d / ", arity());
326}
327
328
Ben Murdochb8e0da22011-05-16 14:20:40 +0100329void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100330 stream->Add("[ecx] #%d / ", arity());
331}
332
333
Ben Murdochb8e0da22011-05-16 14:20:40 +0100334void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000335 SmartArrayPointer<char> name_string = name()->ToCString();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100336 stream->Add("%s #%d / ", *name_string, arity());
337}
338
339
Ben Murdochb8e0da22011-05-16 14:20:40 +0100340void LCallGlobal::PrintDataTo(StringStream* stream) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000341 SmartArrayPointer<char> name_string = name()->ToCString();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100342 stream->Add("%s #%d / ", *name_string, arity());
343}
344
345
Ben Murdochb8e0da22011-05-16 14:20:40 +0100346void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100347 stream->Add("#%d / ", arity());
348}
349
350
Ben Murdochb8e0da22011-05-16 14:20:40 +0100351void LCallNew::PrintDataTo(StringStream* stream) {
352 stream->Add("= ");
353 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100354 stream->Add(" #%d / ", arity());
355}
356
357
Ben Murdochb8e0da22011-05-16 14:20:40 +0100358void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100359 arguments()->PrintTo(stream);
360
361 stream->Add(" length ");
362 length()->PrintTo(stream);
363
364 stream->Add(" index ");
365 index()->PrintTo(stream);
366}
367
368
Ben Murdochb0fe1622011-05-05 13:52:32 +0100369int LChunk::GetNextSpillIndex(bool is_double) {
370 // Skip a slot if for a double-width slot.
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100371 if (is_double) spill_slot_count_++;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100372 return spill_slot_count_++;
373}
374
375
Ben Murdochb8e0da22011-05-16 14:20:40 +0100376LOperand* LChunk::GetNextSpillSlot(bool is_double) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377 int index = GetNextSpillIndex(is_double);
378 if (is_double) {
379 return LDoubleStackSlot::Create(index);
380 } else {
381 return LStackSlot::Create(index);
382 }
383}
384
385
386void LChunk::MarkEmptyBlocks() {
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100387 HPhase phase("L_Mark empty blocks", this);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100388 for (int i = 0; i < graph()->blocks()->length(); ++i) {
389 HBasicBlock* block = graph()->blocks()->at(i);
390 int first = block->first_instruction_index();
391 int last = block->last_instruction_index();
392 LInstruction* first_instr = instructions()->at(first);
393 LInstruction* last_instr = instructions()->at(last);
394
395 LLabel* label = LLabel::cast(first_instr);
396 if (last_instr->IsGoto()) {
397 LGoto* goto_instr = LGoto::cast(last_instr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000398 if (label->IsRedundant() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +0100399 !label->is_loop_header()) {
400 bool can_eliminate = true;
401 for (int i = first + 1; i < last && can_eliminate; ++i) {
402 LInstruction* cur = instructions()->at(i);
403 if (cur->IsGap()) {
404 LGap* gap = LGap::cast(cur);
405 if (!gap->IsRedundant()) {
406 can_eliminate = false;
407 }
408 } else {
409 can_eliminate = false;
410 }
411 }
412
413 if (can_eliminate) {
414 label->set_replacement(GetLabel(goto_instr->block_id()));
415 }
416 }
417 }
418 }
419}
420
421
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100422void LStoreNamedField::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100423 object()->PrintTo(stream);
424 stream->Add(".");
425 stream->Add(*String::cast(*name())->ToCString());
426 stream->Add(" <- ");
427 value()->PrintTo(stream);
428}
429
430
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100431void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
432 object()->PrintTo(stream);
433 stream->Add(".");
434 stream->Add(*String::cast(*name())->ToCString());
435 stream->Add(" <- ");
436 value()->PrintTo(stream);
437}
438
439
440void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
441 object()->PrintTo(stream);
442 stream->Add("[");
443 key()->PrintTo(stream);
444 stream->Add("] <- ");
445 value()->PrintTo(stream);
446}
447
448
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000449void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
450 elements()->PrintTo(stream);
451 stream->Add("[");
452 key()->PrintTo(stream);
453 stream->Add("] <- ");
454 value()->PrintTo(stream);
455}
456
457
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100458void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100459 object()->PrintTo(stream);
460 stream->Add("[");
461 key()->PrintTo(stream);
462 stream->Add("] <- ");
463 value()->PrintTo(stream);
464}
465
466
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000467void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
468 object()->PrintTo(stream);
469 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
470}
471
472
Steve Block1e0659c2011-05-24 12:43:12 +0100473void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000474 LInstructionGap* gap = new(graph_->zone()) LInstructionGap(block);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100475 int index = -1;
476 if (instr->IsControl()) {
477 instructions_.Add(gap);
478 index = instructions_.length();
479 instructions_.Add(instr);
480 } else {
481 index = instructions_.length();
482 instructions_.Add(instr);
483 instructions_.Add(gap);
484 }
485 if (instr->HasPointerMap()) {
486 pointer_maps_.Add(instr->pointer_map());
487 instr->pointer_map()->set_lithium_position(index);
488 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100489}
490
491
492LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
493 return LConstantOperand::Create(constant->id());
494}
495
496
497int LChunk::GetParameterStackSlot(int index) const {
498 // The receiver is at index 0, the first parameter at index 1, so we
499 // shift all parameter indexes down by the number of parameters, and
500 // make sure they end up negative so they are distinguishable from
501 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100502 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100503 ASSERT(result < 0);
504 return result;
505}
506
507// A parameter relative to ebp in the arguments stub.
508int LChunk::ParameterAt(int index) {
509 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100510 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100511 kPointerSize;
512}
513
514
515LGap* LChunk::GetGapAt(int index) const {
516 return LGap::cast(instructions_[index]);
517}
518
519
520bool LChunk::IsGapAt(int index) const {
521 return instructions_[index]->IsGap();
522}
523
524
525int LChunk::NearestGapPos(int index) const {
526 while (!IsGapAt(index)) index--;
527 return index;
528}
529
530
531void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
532 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
533}
534
535
Ben Murdochb0fe1622011-05-05 13:52:32 +0100536Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
537 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
538}
539
540
541Representation LChunk::LookupLiteralRepresentation(
542 LConstantOperand* operand) const {
543 return graph_->LookupValue(operand->index())->representation();
544}
545
546
547LChunk* LChunkBuilder::Build() {
548 ASSERT(is_unused());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000549 chunk_ = new(zone()) LChunk(info(), graph());
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100550 HPhase phase("L_Building chunk", chunk_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100551 status_ = BUILDING;
552 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
553 for (int i = 0; i < blocks->length(); i++) {
554 HBasicBlock* next = NULL;
555 if (i < blocks->length() - 1) next = blocks->at(i + 1);
556 DoBasicBlock(blocks->at(i), next);
557 if (is_aborted()) return NULL;
558 }
559 status_ = DONE;
560 return chunk_;
561}
562
563
564void LChunkBuilder::Abort(const char* format, ...) {
565 if (FLAG_trace_bailout) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000566 SmartArrayPointer<char> name(
567 info()->shared_info()->DebugName()->ToCString());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100568 PrintF("Aborting LChunk building in @\"%s\": ", *name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100569 va_list arguments;
570 va_start(arguments, format);
571 OS::VPrint(format, arguments);
572 va_end(arguments);
573 PrintF("\n");
574 }
575 status_ = ABORTED;
576}
577
578
Ben Murdochb0fe1622011-05-05 13:52:32 +0100579LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000580 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
581 Register::ToAllocationIndex(reg));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100582}
583
584
585LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000586 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
587 XMMRegister::ToAllocationIndex(reg));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100588}
589
590
591LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
592 return Use(value, ToUnallocated(fixed_register));
593}
594
595
596LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
597 return Use(value, ToUnallocated(reg));
598}
599
600
601LOperand* LChunkBuilder::UseRegister(HValue* value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000602 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100603}
604
605
606LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
607 return Use(value,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000608 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
609 LUnallocated::USED_AT_START));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100610}
611
612
613LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000614 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100615}
616
617
618LOperand* LChunkBuilder::Use(HValue* value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000619 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620}
621
622
623LOperand* LChunkBuilder::UseAtStart(HValue* value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000624 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
625 LUnallocated::USED_AT_START));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100626}
627
628
629LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
630 return value->IsConstant()
631 ? chunk_->DefineConstantOperand(HConstant::cast(value))
632 : Use(value);
633}
634
635
636LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
637 return value->IsConstant()
638 ? chunk_->DefineConstantOperand(HConstant::cast(value))
639 : UseAtStart(value);
640}
641
642
643LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
644 return value->IsConstant()
645 ? chunk_->DefineConstantOperand(HConstant::cast(value))
646 : UseRegister(value);
647}
648
649
650LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
651 return value->IsConstant()
652 ? chunk_->DefineConstantOperand(HConstant::cast(value))
653 : UseRegisterAtStart(value);
654}
655
656
Ben Murdochb8e0da22011-05-16 14:20:40 +0100657LOperand* LChunkBuilder::UseAny(HValue* value) {
658 return value->IsConstant()
659 ? chunk_->DefineConstantOperand(HConstant::cast(value))
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000660 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100661}
662
663
Ben Murdochb0fe1622011-05-05 13:52:32 +0100664LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
665 if (value->EmitAtUses()) {
666 HInstruction* instr = HInstruction::cast(value);
667 VisitInstruction(instr);
668 }
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100669 operand->set_virtual_register(value->id());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100670 return operand;
671}
672
673
Ben Murdochb8e0da22011-05-16 14:20:40 +0100674template<int I, int T>
675LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
676 LUnallocated* result) {
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100677 result->set_virtual_register(current_instruction_->id());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100678 instr->set_result(result);
679 return instr;
680}
681
682
683template<int I, int T>
Ben Murdochb8e0da22011-05-16 14:20:40 +0100684LInstruction* LChunkBuilder::DefineAsRegister(
685 LTemplateInstruction<1, I, T>* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000686 return Define(instr,
687 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100688}
689
690
Ben Murdochb8e0da22011-05-16 14:20:40 +0100691template<int I, int T>
692LInstruction* LChunkBuilder::DefineAsSpilled(
693 LTemplateInstruction<1, I, T>* instr,
694 int index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000695 return Define(instr,
696 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100697}
698
699
Ben Murdochb8e0da22011-05-16 14:20:40 +0100700template<int I, int T>
701LInstruction* LChunkBuilder::DefineSameAsFirst(
702 LTemplateInstruction<1, I, T>* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000703 return Define(instr,
704 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705}
706
707
Ben Murdochb8e0da22011-05-16 14:20:40 +0100708template<int I, int T>
709LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
710 Register reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100711 return Define(instr, ToUnallocated(reg));
712}
713
714
Ben Murdochb8e0da22011-05-16 14:20:40 +0100715template<int I, int T>
716LInstruction* LChunkBuilder::DefineFixedDouble(
717 LTemplateInstruction<1, I, T>* instr,
718 XMMRegister reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719 return Define(instr, ToUnallocated(reg));
720}
721
722
723LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
724 HEnvironment* hydrogen_env = current_block_->last_environment();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000725 int argument_index_accumulator = 0;
726 instr->set_environment(CreateEnvironment(hydrogen_env,
727 &argument_index_accumulator));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100728 return instr;
729}
730
731
732LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
733 LInstruction* instr, int ast_id) {
Steve Block1e0659c2011-05-24 12:43:12 +0100734 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100735 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
Steve Block1e0659c2011-05-24 12:43:12 +0100736 instruction_pending_deoptimization_environment_ = instr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100737 pending_deoptimization_ast_id_ = ast_id;
738 return instr;
739}
740
741
742void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
Steve Block1e0659c2011-05-24 12:43:12 +0100743 instruction_pending_deoptimization_environment_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100744 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
745}
746
747
748LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
749 HInstruction* hinstr,
750 CanDeoptimize can_deoptimize) {
Steve Block1e0659c2011-05-24 12:43:12 +0100751#ifdef DEBUG
752 instr->VerifyCall();
753#endif
754 instr->MarkAsCall();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100755 instr = AssignPointerMap(instr);
756
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000757 if (hinstr->HasObservableSideEffects()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100758 ASSERT(hinstr->next()->IsSimulate());
759 HSimulate* sim = HSimulate::cast(hinstr->next());
760 instr = SetInstructionPendingDeoptimizationEnvironment(
761 instr, sim->ast_id());
762 }
763
764 // If instruction does not have side-effects lazy deoptimization
765 // after the call will try to deoptimize to the point before the call.
766 // Thus we still need to attach environment to this call even if
767 // call sequence can not deoptimize eagerly.
768 bool needs_environment =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000769 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
770 !hinstr->HasObservableSideEffects();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100771 if (needs_environment && !instr->HasEnvironment()) {
772 instr = AssignEnvironment(instr);
773 }
774
775 return instr;
776}
777
778
Ben Murdoch086aeea2011-05-13 15:57:08 +0100779LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100780 instr->MarkAsSaveDoubles();
Ben Murdoch086aeea2011-05-13 15:57:08 +0100781 return instr;
782}
783
784
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
786 ASSERT(!instr->HasPointerMap());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000787 instr->set_pointer_map(new(zone()) LPointerMap(position_));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100788 return instr;
789}
790
791
Ben Murdochb0fe1622011-05-05 13:52:32 +0100792LUnallocated* LChunkBuilder::TempRegister() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000793 LUnallocated* operand =
794 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100795 operand->set_virtual_register(allocator_->GetVirtualRegister());
796 if (!allocator_->AllocationOk()) {
797 Abort("Not enough virtual registers (temps).");
798 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100799 return operand;
800}
801
802
803LOperand* LChunkBuilder::FixedTemp(Register reg) {
804 LUnallocated* operand = ToUnallocated(reg);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100805 ASSERT(operand->HasFixedPolicy());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100806 return operand;
807}
808
809
810LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
811 LUnallocated* operand = ToUnallocated(reg);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100812 ASSERT(operand->HasFixedPolicy());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100813 return operand;
814}
815
816
817LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000818 return new(zone()) LLabel(instr->block());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100819}
820
821
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000822LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000823 return AssignEnvironment(new(zone()) LDeoptimize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000824}
825
826
Ben Murdochb0fe1622011-05-05 13:52:32 +0100827LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000828 return AssignEnvironment(new(zone()) LDeoptimize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100829}
830
831
832LInstruction* LChunkBuilder::DoShift(Token::Value op,
833 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100834 if (instr->representation().IsTagged()) {
835 ASSERT(instr->left()->representation().IsTagged());
836 ASSERT(instr->right()->representation().IsTagged());
837
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000838 LOperand* context = UseFixed(instr->context(), esi);
Steve Block1e0659c2011-05-24 12:43:12 +0100839 LOperand* left = UseFixed(instr->left(), edx);
840 LOperand* right = UseFixed(instr->right(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000841 LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right);
Steve Block1e0659c2011-05-24 12:43:12 +0100842 return MarkAsCall(DefineFixed(result, eax), instr);
843 }
844
Ben Murdochb0fe1622011-05-05 13:52:32 +0100845 ASSERT(instr->representation().IsInteger32());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000846 ASSERT(instr->left()->representation().IsInteger32());
847 ASSERT(instr->right()->representation().IsInteger32());
848 LOperand* left = UseRegisterAtStart(instr->left());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100849
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000850 HValue* right_value = instr->right();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100851 LOperand* right = NULL;
852 int constant_value = 0;
853 if (right_value->IsConstant()) {
854 HConstant* constant = HConstant::cast(right_value);
855 right = chunk_->DefineConstantOperand(constant);
856 constant_value = constant->Integer32Value() & 0x1f;
857 } else {
858 right = UseFixed(right_value, ecx);
859 }
860
Ben Murdoch257744e2011-11-30 15:57:28 +0000861 // Shift operations can only deoptimize if we do a logical shift by 0 and
862 // the result cannot be truncated to int32.
863 bool may_deopt = (op == Token::SHR && constant_value == 0);
864 bool does_deopt = false;
865 if (may_deopt) {
866 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
867 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
868 does_deopt = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100869 break;
870 }
871 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100872 }
873
Ben Murdoch257744e2011-11-30 15:57:28 +0000874 LInstruction* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000875 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
Ben Murdoch257744e2011-11-30 15:57:28 +0000876 return does_deopt ? AssignEnvironment(result) : result;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100877}
878
879
880LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
881 HArithmeticBinaryOperation* instr) {
882 ASSERT(instr->representation().IsDouble());
883 ASSERT(instr->left()->representation().IsDouble());
884 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100885 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100886 LOperand* left = UseRegisterAtStart(instr->left());
887 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000888 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100889 return DefineSameAsFirst(result);
890}
891
892
893LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
894 HArithmeticBinaryOperation* instr) {
895 ASSERT(op == Token::ADD ||
896 op == Token::DIV ||
897 op == Token::MOD ||
898 op == Token::MUL ||
899 op == Token::SUB);
900 HValue* left = instr->left();
901 HValue* right = instr->right();
902 ASSERT(left->representation().IsTagged());
903 ASSERT(right->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000904 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100905 LOperand* left_operand = UseFixed(left, edx);
906 LOperand* right_operand = UseFixed(right, eax);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000907 LArithmeticT* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000908 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100909 return MarkAsCall(DefineFixed(result, eax), instr);
910}
911
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000912
Ben Murdochb0fe1622011-05-05 13:52:32 +0100913void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
914 ASSERT(is_building());
915 current_block_ = block;
916 next_block_ = next_block;
917 if (block->IsStartBlock()) {
918 block->UpdateEnvironment(graph_->start_environment());
919 argument_count_ = 0;
920 } else if (block->predecessors()->length() == 1) {
921 // We have a single predecessor => copy environment and outgoing
922 // argument count from the predecessor.
923 ASSERT(block->phis()->length() == 0);
924 HBasicBlock* pred = block->predecessors()->at(0);
925 HEnvironment* last_environment = pred->last_environment();
926 ASSERT(last_environment != NULL);
927 // Only copy the environment, if it is later used again.
928 if (pred->end()->SecondSuccessor() == NULL) {
929 ASSERT(pred->end()->FirstSuccessor() == block);
930 } else {
931 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
932 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
933 last_environment = last_environment->Copy();
934 }
935 }
936 block->UpdateEnvironment(last_environment);
937 ASSERT(pred->argument_count() >= 0);
938 argument_count_ = pred->argument_count();
939 } else {
940 // We are at a state join => process phis.
941 HBasicBlock* pred = block->predecessors()->at(0);
942 // No need to copy the environment, it cannot be used later.
943 HEnvironment* last_environment = pred->last_environment();
944 for (int i = 0; i < block->phis()->length(); ++i) {
945 HPhi* phi = block->phis()->at(i);
946 last_environment->SetValueAt(phi->merged_index(), phi);
947 }
948 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
949 last_environment->SetValueAt(block->deleted_phis()->at(i),
950 graph_->GetConstantUndefined());
951 }
952 block->UpdateEnvironment(last_environment);
953 // Pick up the outgoing argument count of one of the predecessors.
954 argument_count_ = pred->argument_count();
955 }
956 HInstruction* current = block->first();
957 int start = chunk_->instructions()->length();
958 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100959 // Code for constants in registers is generated lazily.
960 if (!current->EmitAtUses()) {
961 VisitInstruction(current);
962 }
963 current = current->next();
964 }
965 int end = chunk_->instructions()->length() - 1;
966 if (end >= start) {
967 block->set_first_instruction_index(start);
968 block->set_last_instruction_index(end);
969 }
970 block->set_argument_count(argument_count_);
971 next_block_ = NULL;
972 current_block_ = NULL;
973}
974
975
976void LChunkBuilder::VisitInstruction(HInstruction* current) {
977 HInstruction* old_current = current_instruction_;
978 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100979 if (current->has_position()) position_ = current->position();
980 LInstruction* instr = current->CompileToLithium(this);
981
982 if (instr != NULL) {
983 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
984 instr = AssignPointerMap(instr);
985 }
986 if (FLAG_stress_environments && !instr->HasEnvironment()) {
987 instr = AssignEnvironment(instr);
988 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000989 instr->set_hydrogen_value(current);
Steve Block1e0659c2011-05-24 12:43:12 +0100990 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100991 }
992 current_instruction_ = old_current;
993}
994
995
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000996LEnvironment* LChunkBuilder::CreateEnvironment(
997 HEnvironment* hydrogen_env,
998 int* argument_index_accumulator) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100999 if (hydrogen_env == NULL) return NULL;
1000
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001001 LEnvironment* outer =
1002 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001003 int ast_id = hydrogen_env->ast_id();
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001004 ASSERT(ast_id != AstNode::kNoNumber ||
1005 hydrogen_env->frame_type() != JS_FUNCTION);
Steve Block9fac8402011-05-12 15:51:54 +01001006 int value_count = hydrogen_env->length();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001007 LEnvironment* result =
1008 new(zone()) LEnvironment(hydrogen_env->closure(),
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001009 hydrogen_env->frame_type(),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001010 ast_id,
1011 hydrogen_env->parameter_count(),
1012 argument_count_,
1013 value_count,
1014 outer);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001015 int argument_index = *argument_index_accumulator;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001016 for (int i = 0; i < value_count; ++i) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001017 if (hydrogen_env->is_special_index(i)) continue;
1018
Ben Murdochb0fe1622011-05-05 13:52:32 +01001019 HValue* value = hydrogen_env->values()->at(i);
1020 LOperand* op = NULL;
1021 if (value->IsArgumentsObject()) {
1022 op = NULL;
1023 } else if (value->IsPushArgument()) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00001024 op = new(zone()) LArgument(argument_index++);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001025 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001026 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001027 }
1028 result->AddValue(op, value->representation());
1029 }
1030
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001031 if (hydrogen_env->frame_type() == JS_FUNCTION) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00001032 *argument_index_accumulator = argument_index;
1033 }
1034
Ben Murdochb0fe1622011-05-05 13:52:32 +01001035 return result;
1036}
1037
1038
1039LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001040 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001041}
1042
1043
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001044LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00001045 HValue* value = instr->value();
1046 if (value->EmitAtUses()) {
1047 ASSERT(value->IsConstant());
1048 ASSERT(!value->representation().IsDouble());
1049 HBasicBlock* successor = HConstant::cast(value)->ToBoolean()
Ben Murdoch257744e2011-11-30 15:57:28 +00001050 ? instr->FirstSuccessor()
1051 : instr->SecondSuccessor();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001052 return new(zone()) LGoto(successor->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001053 }
Ben Murdochc7cc0282012-03-05 14:35:55 +00001054
1055 // Untagged integers or doubles, smis and booleans don't require a
1056 // deoptimization environment nor a temp register.
1057 Representation rep = value->representation();
1058 HType type = value->type();
1059 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) {
1060 return new(zone()) LBranch(UseRegister(value), NULL);
1061 }
1062
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001063 ToBooleanStub::Types expected = instr->expected_input_types();
1064 // We need a temporary register when we have to access the map *or* we have
1065 // no type info yet, in which case we handle all cases (including the ones
1066 // involving maps).
1067 bool needs_temp = expected.NeedsMap() || expected.IsEmpty();
1068 LOperand* temp = needs_temp ? TempRegister() : NULL;
Ben Murdochc7cc0282012-03-05 14:35:55 +00001069 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001070}
1071
1072
Steve Block1e0659c2011-05-24 12:43:12 +01001073LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001074 ASSERT(instr->value()->representation().IsTagged());
1075 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001076 return new(zone()) LCmpMapAndBranch(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001077}
1078
1079
1080LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001081 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082}
1083
1084
1085LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001086 return DefineAsRegister(new(zone()) LArgumentsElements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001087}
1088
1089
1090LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001091 LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
1092 LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
1093 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001094 LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001095 return MarkAsCall(DefineFixed(result, eax), instr);
1096}
1097
1098
Ben Murdoch086aeea2011-05-13 15:57:08 +01001099LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1100 HInstanceOfKnownGlobal* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001101 LInstanceOfKnownGlobal* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001102 new(zone()) LInstanceOfKnownGlobal(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001103 UseFixed(instr->context(), esi),
1104 UseFixed(instr->left(), InstanceofStub::left()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001105 FixedTemp(edi));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001106 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001107}
1108
1109
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001110LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1111 LOperand* receiver = UseRegister(instr->receiver());
1112 LOperand* function = UseRegisterAtStart(instr->function());
1113 LOperand* temp = TempRegister();
1114 LWrapReceiver* result =
1115 new(zone()) LWrapReceiver(receiver, function, temp);
1116 return AssignEnvironment(DefineSameAsFirst(result));
1117}
1118
1119
Ben Murdochb0fe1622011-05-05 13:52:32 +01001120LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1121 LOperand* function = UseFixed(instr->function(), edi);
1122 LOperand* receiver = UseFixed(instr->receiver(), eax);
Steve Block1e0659c2011-05-24 12:43:12 +01001123 LOperand* length = UseFixed(instr->length(), ebx);
1124 LOperand* elements = UseFixed(instr->elements(), ecx);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001125 LApplyArguments* result = new(zone()) LApplyArguments(function,
1126 receiver,
1127 length,
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001128 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001129 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1130}
1131
1132
1133LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1134 ++argument_count_;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001135 LOperand* argument = UseAny(instr->argument());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001136 return new(zone()) LPushArgument(argument);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001137}
1138
1139
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001140LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001141 return instr->HasNoUses()
1142 ? NULL
1143 : DefineAsRegister(new(zone()) LThisFunction);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001144}
1145
1146
Steve Block1e0659c2011-05-24 12:43:12 +01001147LInstruction* LChunkBuilder::DoContext(HContext* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001148 return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
Steve Block1e0659c2011-05-24 12:43:12 +01001149}
1150
1151
1152LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1153 LOperand* context = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001154 return DefineAsRegister(new(zone()) LOuterContext(context));
Steve Block1e0659c2011-05-24 12:43:12 +01001155}
1156
1157
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001158LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1159 LOperand* context = UseFixed(instr->context(), esi);
1160 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1161}
1162
1163
Ben Murdochb0fe1622011-05-05 13:52:32 +01001164LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001165 LOperand* context = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001166 return DefineAsRegister(new(zone()) LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001167}
1168
1169
1170LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001171 LOperand* global_object = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001172 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001173}
1174
1175
1176LInstruction* LChunkBuilder::DoCallConstantFunction(
1177 HCallConstantFunction* instr) {
1178 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001179 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001180}
1181
1182
Ben Murdoch257744e2011-11-30 15:57:28 +00001183LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1184 LOperand* context = UseFixed(instr->context(), esi);
1185 LOperand* function = UseFixed(instr->function(), edi);
1186 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001187 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
Ben Murdoch257744e2011-11-30 15:57:28 +00001188 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1189}
1190
1191
Ben Murdochb0fe1622011-05-05 13:52:32 +01001192LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1193 BuiltinFunctionId op = instr->op();
Ben Murdoch8b112d22011-06-08 16:22:53 +01001194 if (op == kMathLog) {
1195 ASSERT(instr->representation().IsDouble());
1196 ASSERT(instr->value()->representation().IsDouble());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001197 LOperand* context = UseAny(instr->context()); // Not actually used.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001198 LOperand* input = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001199 LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1200 input);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001201 return DefineSameAsFirst(result);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001202 } else if (op == kMathSin || op == kMathCos || op == kMathTan) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001203 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001204 LOperand* input = UseFixedDouble(instr->value(), xmm1);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001205 LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1206 input);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001207 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1208 } else {
1209 LOperand* input = UseRegisterAtStart(instr->value());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001210 LOperand* context = UseAny(instr->context()); // Deferred use by MathAbs.
Ben Murdochc7cc0282012-03-05 14:35:55 +00001211 if (op == kMathPowHalf) {
1212 LOperand* temp = TempRegister();
1213 LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp);
1214 return DefineSameAsFirst(result);
1215 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001216 LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context,
1217 input);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001218 switch (op) {
1219 case kMathAbs:
1220 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1221 case kMathFloor:
1222 return AssignEnvironment(DefineAsRegister(result));
1223 case kMathRound:
1224 return AssignEnvironment(DefineAsRegister(result));
1225 case kMathSqrt:
1226 return DefineSameAsFirst(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001227 default:
1228 UNREACHABLE();
1229 return NULL;
1230 }
1231 }
1232}
1233
1234
1235LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1236 ASSERT(instr->key()->representation().IsTagged());
Steve Block1e0659c2011-05-24 12:43:12 +01001237 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001238 LOperand* key = UseFixed(instr->key(), ecx);
Steve Block1e0659c2011-05-24 12:43:12 +01001239 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001240 LCallKeyed* result = new(zone()) LCallKeyed(context, key);
Steve Block1e0659c2011-05-24 12:43:12 +01001241 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001242}
1243
1244
1245LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001246 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001247 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001248 LCallNamed* result = new(zone()) LCallNamed(context);
Steve Block1e0659c2011-05-24 12:43:12 +01001249 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001250}
1251
1252
1253LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001254 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001255 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001256 LCallGlobal* result = new(zone()) LCallGlobal(context);
Steve Block1e0659c2011-05-24 12:43:12 +01001257 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001258}
1259
1260
1261LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1262 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001263 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001264}
1265
1266
1267LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001268 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001269 LOperand* constructor = UseFixed(instr->constructor(), edi);
1270 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001271 LCallNew* result = new(zone()) LCallNew(context, constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001272 return MarkAsCall(DefineFixed(result, eax), instr);
1273}
1274
1275
1276LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001277 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001278 LOperand* function = UseFixed(instr->function(), edi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001279 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001280 LCallFunction* result = new(zone()) LCallFunction(context, function);
Steve Block1e0659c2011-05-24 12:43:12 +01001281 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001282}
1283
1284
1285LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1286 argument_count_ -= instr->argument_count();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001287 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001288 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001289}
1290
1291
1292LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1293 return DoShift(Token::SHR, instr);
1294}
1295
1296
1297LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1298 return DoShift(Token::SAR, instr);
1299}
1300
1301
1302LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1303 return DoShift(Token::SHL, instr);
1304}
1305
1306
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001307LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1308 if (instr->representation().IsInteger32()) {
1309 ASSERT(instr->left()->representation().IsInteger32());
1310 ASSERT(instr->right()->representation().IsInteger32());
1311
1312 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1313 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1314 return DefineSameAsFirst(new(zone()) LBitI(left, right));
1315 } else {
1316 ASSERT(instr->representation().IsTagged());
1317 ASSERT(instr->left()->representation().IsTagged());
1318 ASSERT(instr->right()->representation().IsTagged());
1319
1320 LOperand* context = UseFixed(instr->context(), esi);
1321 LOperand* left = UseFixed(instr->left(), edx);
1322 LOperand* right = UseFixed(instr->right(), eax);
1323 LArithmeticT* result =
1324 new(zone()) LArithmeticT(instr->op(), context, left, right);
1325 return MarkAsCall(DefineFixed(result, eax), instr);
1326 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001327}
1328
1329
1330LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1331 ASSERT(instr->value()->representation().IsInteger32());
1332 ASSERT(instr->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001333 LOperand* input = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001334 LBitNotI* result = new(zone()) LBitNotI(input);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001335 return DefineSameAsFirst(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001336}
1337
1338
Ben Murdochb0fe1622011-05-05 13:52:32 +01001339LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1340 if (instr->representation().IsDouble()) {
1341 return DoArithmeticD(Token::DIV, instr);
1342 } else if (instr->representation().IsInteger32()) {
1343 // The temporary operand is necessary to ensure that right is not allocated
1344 // into edx.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001345 LOperand* temp = FixedTemp(edx);
Steve Block1e0659c2011-05-24 12:43:12 +01001346 LOperand* dividend = UseFixed(instr->left(), eax);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001347 LOperand* divisor = UseRegister(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001348 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001349 return AssignEnvironment(DefineFixed(result, eax));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001350 } else {
1351 ASSERT(instr->representation().IsTagged());
1352 return DoArithmeticT(Token::DIV, instr);
1353 }
1354}
1355
1356
1357LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1358 if (instr->representation().IsInteger32()) {
1359 ASSERT(instr->left()->representation().IsInteger32());
1360 ASSERT(instr->right()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01001361
1362 LInstruction* result;
1363 if (instr->HasPowerOf2Divisor()) {
1364 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1365 LOperand* value = UseRegisterAtStart(instr->left());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001366 LModI* mod =
1367 new(zone()) LModI(value, UseOrConstant(instr->right()), NULL);
Steve Block44f0eee2011-05-26 01:26:41 +01001368 result = DefineSameAsFirst(mod);
1369 } else {
1370 // The temporary operand is necessary to ensure that right is
1371 // not allocated into edx.
1372 LOperand* temp = FixedTemp(edx);
1373 LOperand* value = UseFixed(instr->left(), eax);
1374 LOperand* divisor = UseRegister(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001375 LModI* mod = new(zone()) LModI(value, divisor, temp);
Steve Block44f0eee2011-05-26 01:26:41 +01001376 result = DefineFixed(mod, edx);
1377 }
1378
Ben Murdochb8e0da22011-05-16 14:20:40 +01001379 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1380 instr->CheckFlag(HValue::kCanBeDivByZero))
1381 ? AssignEnvironment(result)
1382 : result;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001383 } else if (instr->representation().IsTagged()) {
1384 return DoArithmeticT(Token::MOD, instr);
1385 } else {
1386 ASSERT(instr->representation().IsDouble());
1387 // We call a C function for double modulo. It can't trigger a GC.
1388 // We need to use fixed result register for the call.
1389 // TODO(fschneider): Allow any register as input registers.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001390 LOperand* left = UseFixedDouble(instr->left(), xmm2);
1391 LOperand* right = UseFixedDouble(instr->right(), xmm1);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001392 LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001393 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1394 }
1395}
1396
1397
1398LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1399 if (instr->representation().IsInteger32()) {
1400 ASSERT(instr->left()->representation().IsInteger32());
1401 ASSERT(instr->right()->representation().IsInteger32());
1402 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1403 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1404 LOperand* temp = NULL;
1405 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1406 temp = TempRegister();
1407 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001408 LMulI* mul = new(zone()) LMulI(left, right, temp);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001409 if (instr->CheckFlag(HValue::kCanOverflow) ||
1410 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1411 AssignEnvironment(mul);
1412 }
1413 return DefineSameAsFirst(mul);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001414 } else if (instr->representation().IsDouble()) {
1415 return DoArithmeticD(Token::MUL, instr);
1416 } else {
1417 ASSERT(instr->representation().IsTagged());
1418 return DoArithmeticT(Token::MUL, instr);
1419 }
1420}
1421
1422
1423LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1424 if (instr->representation().IsInteger32()) {
1425 ASSERT(instr->left()->representation().IsInteger32());
1426 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001427 LOperand* left = UseRegisterAtStart(instr->left());
1428 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001429 LSubI* sub = new(zone()) LSubI(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001430 LInstruction* result = DefineSameAsFirst(sub);
1431 if (instr->CheckFlag(HValue::kCanOverflow)) {
1432 result = AssignEnvironment(result);
1433 }
1434 return result;
1435 } else if (instr->representation().IsDouble()) {
1436 return DoArithmeticD(Token::SUB, instr);
1437 } else {
1438 ASSERT(instr->representation().IsTagged());
1439 return DoArithmeticT(Token::SUB, instr);
1440 }
1441}
1442
1443
1444LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1445 if (instr->representation().IsInteger32()) {
1446 ASSERT(instr->left()->representation().IsInteger32());
1447 ASSERT(instr->right()->representation().IsInteger32());
1448 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1449 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001450 LAddI* add = new(zone()) LAddI(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001451 LInstruction* result = DefineSameAsFirst(add);
1452 if (instr->CheckFlag(HValue::kCanOverflow)) {
1453 result = AssignEnvironment(result);
1454 }
1455 return result;
1456 } else if (instr->representation().IsDouble()) {
1457 return DoArithmeticD(Token::ADD, instr);
1458 } else {
1459 ASSERT(instr->representation().IsTagged());
1460 return DoArithmeticT(Token::ADD, instr);
1461 }
1462}
1463
1464
1465LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1466 ASSERT(instr->representation().IsDouble());
1467 // We call a C function for double power. It can't trigger a GC.
1468 // We need to use fixed result register for the call.
1469 Representation exponent_type = instr->right()->representation();
1470 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochc7cc0282012-03-05 14:35:55 +00001471 LOperand* left = UseFixedDouble(instr->left(), xmm2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001472 LOperand* right = exponent_type.IsDouble() ?
Ben Murdochc7cc0282012-03-05 14:35:55 +00001473 UseFixedDouble(instr->right(), xmm1) :
Ben Murdochb0fe1622011-05-05 13:52:32 +01001474 UseFixed(instr->right(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001475 LPower* result = new(zone()) LPower(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001476 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
1477 CAN_DEOPTIMIZE_EAGERLY);
1478}
1479
1480
Ben Murdochc7cc0282012-03-05 14:35:55 +00001481LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1482 ASSERT(instr->representation().IsDouble());
1483 ASSERT(instr->global_object()->representation().IsTagged());
1484 LOperand* global_object = UseFixed(instr->global_object(), eax);
1485 LRandom* result = new(zone()) LRandom(global_object);
1486 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1487}
1488
1489
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001490LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001491 ASSERT(instr->left()->representation().IsTagged());
1492 ASSERT(instr->right()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001493 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001494 LOperand* left = UseFixed(instr->left(), edx);
1495 LOperand* right = UseFixed(instr->right(), eax);
1496 LCmpT* result = new(zone()) LCmpT(context, left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001497 return MarkAsCall(DefineFixed(result, eax), instr);
1498}
1499
1500
1501LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1502 HCompareIDAndBranch* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001503 Representation r = instr->GetInputRepresentation();
1504 if (r.IsInteger32()) {
1505 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001506 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001507 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001508 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001509 return new(zone()) LCmpIDAndBranch(left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001510 } else {
1511 ASSERT(r.IsDouble());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001512 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001513 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001514 LOperand* left;
1515 LOperand* right;
1516 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1517 left = UseRegisterOrConstantAtStart(instr->left());
1518 right = UseRegisterOrConstantAtStart(instr->right());
1519 } else {
1520 left = UseRegisterAtStart(instr->left());
1521 right = UseRegisterAtStart(instr->right());
1522 }
1523 return new(zone()) LCmpIDAndBranch(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001524 }
1525}
1526
1527
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001528LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1529 HCompareObjectEqAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001530 LOperand* left = UseRegisterAtStart(instr->left());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001531 LOperand* right = UseAtStart(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001532 return new(zone()) LCmpObjectEqAndBranch(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001533}
1534
1535
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001536LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1537 HCompareConstantEqAndBranch* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001538 return new(zone()) LCmpConstantEqAndBranch(
1539 UseRegisterAtStart(instr->value()));
Ben Murdoch257744e2011-11-30 15:57:28 +00001540}
1541
1542
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001543LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001544 // We only need a temp register for non-strict compare.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001545 LOperand* temp = instr->kind() == kStrictEquality ? NULL : TempRegister();
1546 return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001547}
1548
1549
1550LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001551 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001552 LOperand* temp = TempRegister();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001553 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
1554}
1555
1556
1557LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1558 ASSERT(instr->value()->representation().IsTagged());
1559 LOperand* temp = TempRegister();
1560 return new LIsStringAndBranch(UseRegister(instr->value()), temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001561}
1562
1563
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001564LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001565 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001566 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001567}
1568
1569
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001570LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1571 HIsUndetectableAndBranch* instr) {
1572 ASSERT(instr ->value()->representation().IsTagged());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001573 return new(zone()) LIsUndetectableAndBranch(
1574 UseRegisterAtStart(instr->value()), TempRegister());
1575}
1576
1577
1578LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1579 HStringCompareAndBranch* instr) {
1580 ASSERT(instr->left()->representation().IsTagged());
1581 ASSERT(instr->right()->representation().IsTagged());
1582 LOperand* context = UseFixed(instr->context(), esi);
1583 LOperand* left = UseFixed(instr->left(), edx);
1584 LOperand* right = UseFixed(instr->right(), eax);
1585
1586 LStringCompareAndBranch* result = new
1587 LStringCompareAndBranch(context, left, right);
1588
1589 return MarkAsCall(result, instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001590}
1591
1592
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001593LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1594 HHasInstanceTypeAndBranch* instr) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001595 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001596 return new(zone()) LHasInstanceTypeAndBranch(
1597 UseRegisterAtStart(instr->value()),
1598 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001599}
1600
1601
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001602LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1603 HGetCachedArrayIndex* instr) {
1604 ASSERT(instr->value()->representation().IsTagged());
1605 LOperand* value = UseRegisterAtStart(instr->value());
1606
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001607 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001608}
1609
1610
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001611LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1612 HHasCachedArrayIndexAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001613 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001614 return new(zone()) LHasCachedArrayIndexAndBranch(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001615 UseRegisterAtStart(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001616}
1617
1618
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001619LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1620 HClassOfTestAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001621 ASSERT(instr->value()->representation().IsTagged());
Ben Murdochc7cc0282012-03-05 14:35:55 +00001622 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1623 TempRegister(),
1624 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001625}
1626
1627
Steve Block9fac8402011-05-12 15:51:54 +01001628LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1629 LOperand* array = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001630 return DefineAsRegister(new(zone()) LJSArrayLength(array));
Steve Block9fac8402011-05-12 15:51:54 +01001631}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001632
Ben Murdochb0fe1622011-05-05 13:52:32 +01001633
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001634LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1635 HFixedArrayBaseLength* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001636 LOperand* array = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001637 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
Steve Block1e0659c2011-05-24 12:43:12 +01001638}
1639
1640
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001641LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1642 LOperand* object = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001643 return DefineAsRegister(new(zone()) LElementsKind(object));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001644}
1645
1646
Ben Murdochb0fe1622011-05-05 13:52:32 +01001647LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1648 LOperand* object = UseRegister(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001649 LValueOf* result = new(zone()) LValueOf(object, TempRegister());
Ben Murdochc7cc0282012-03-05 14:35:55 +00001650 return DefineSameAsFirst(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001651}
1652
1653
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001654LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1655 LOperand* date = UseFixed(instr->value(), eax);
1656 LDateField* result =
1657 new(zone()) LDateField(date, FixedTemp(ecx), instr->index());
1658 return MarkAsCall(DefineFixed(result, eax), instr);
1659}
1660
1661
Ben Murdochb0fe1622011-05-05 13:52:32 +01001662LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001663 return AssignEnvironment(new(zone()) LBoundsCheck(
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001664 UseRegisterOrConstantAtStart(instr->index()),
1665 UseAtStart(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001666}
1667
1668
Steve Block1e0659c2011-05-24 12:43:12 +01001669LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1670 // The control instruction marking the end of a block that completed
1671 // abruptly (e.g., threw an exception). There is nothing specific to do.
1672 return NULL;
1673}
1674
1675
Ben Murdochb0fe1622011-05-05 13:52:32 +01001676LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001677 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001678 LOperand* value = UseFixed(instr->value(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001679 return MarkAsCall(new(zone()) LThrow(context, value), instr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001680}
1681
1682
1683LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1684 return NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001685}
1686
1687
Ben Murdoch257744e2011-11-30 15:57:28 +00001688LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1689 // All HForceRepresentation instructions should be eliminated in the
1690 // representation change phase of Hydrogen.
1691 UNREACHABLE();
1692 return NULL;
1693}
1694
1695
Ben Murdochb0fe1622011-05-05 13:52:32 +01001696LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1697 Representation from = instr->from();
1698 Representation to = instr->to();
1699 if (from.IsTagged()) {
1700 if (to.IsDouble()) {
1701 LOperand* value = UseRegister(instr->value());
Ben Murdochc7cc0282012-03-05 14:35:55 +00001702 // Temp register only necessary for minus zero check.
1703 LOperand* temp = instr->deoptimize_on_minus_zero()
1704 ? TempRegister()
1705 : NULL;
1706 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001707 return AssignEnvironment(DefineAsRegister(res));
1708 } else {
1709 ASSERT(to.IsInteger32());
1710 LOperand* value = UseRegister(instr->value());
1711 bool needs_check = !instr->value()->type().IsSmi();
1712 if (needs_check) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001713 bool truncating = instr->CanTruncateToInt32();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001714 LOperand* xmm_temp =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001715 (truncating && CpuFeatures::IsSupported(SSE3))
Ben Murdochb0fe1622011-05-05 13:52:32 +01001716 ? NULL
1717 : FixedTemp(xmm1);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001718 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001719 return AssignEnvironment(DefineSameAsFirst(res));
1720 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001721 return DefineSameAsFirst(new(zone()) LSmiUntag(value, needs_check));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001722 }
1723 }
1724 } else if (from.IsDouble()) {
1725 if (to.IsTagged()) {
1726 LOperand* value = UseRegister(instr->value());
1727 LOperand* temp = TempRegister();
1728
1729 // Make sure that temp and result_temp are different registers.
1730 LUnallocated* result_temp = TempRegister();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001731 LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001732 return AssignPointerMap(Define(result, result_temp));
1733 } else {
1734 ASSERT(to.IsInteger32());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001735 bool truncating = instr->CanTruncateToInt32();
1736 bool needs_temp = truncating && !CpuFeatures::IsSupported(SSE3);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001737 LOperand* value = needs_temp ?
1738 UseTempRegister(instr->value()) : UseRegister(instr->value());
1739 LOperand* temp = needs_temp ? TempRegister() : NULL;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001740 return AssignEnvironment(
1741 DefineAsRegister(new(zone()) LDoubleToI(value, temp)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001742 }
1743 } else if (from.IsInteger32()) {
1744 if (to.IsTagged()) {
1745 HValue* val = instr->value();
1746 LOperand* value = UseRegister(val);
1747 if (val->HasRange() && val->range()->IsInSmiRange()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001748 return DefineSameAsFirst(new(zone()) LSmiTag(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001749 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001750 LNumberTagI* result = new(zone()) LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001751 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1752 }
1753 } else {
1754 ASSERT(to.IsDouble());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001755 return DefineAsRegister(
1756 new(zone()) LInteger32ToDouble(Use(instr->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001757 }
1758 }
1759 UNREACHABLE();
1760 return NULL;
1761}
1762
1763
1764LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001765 LOperand* value = UseAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001766 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001767}
1768
1769
1770LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1771 LOperand* value = UseRegisterAtStart(instr->value());
1772 LOperand* temp = TempRegister();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001773 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001774 return AssignEnvironment(result);
1775}
1776
1777
1778LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1779 LOperand* temp = TempRegister();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001780 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001781 return AssignEnvironment(result);
1782}
1783
1784
1785LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001786 LOperand* value = UseAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001787 return AssignEnvironment(new(zone()) LCheckSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001788}
1789
1790
1791LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001792 // If the target is in new space, we'll emit a global cell compare and so
1793 // want the value in a register. If the target gets promoted before we
1794 // emit code, we will still get the register but will do an immediate
1795 // compare instead of the cell compare. This is safe.
1796 LOperand* value = Isolate::Current()->heap()->InNewSpace(*instr->target())
1797 ? UseRegisterAtStart(instr->value())
1798 : UseAtStart(instr->value());
1799 return AssignEnvironment(new(zone()) LCheckFunction(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001800}
1801
1802
1803LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1804 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001805 LCheckMap* result = new(zone()) LCheckMap(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001806 return AssignEnvironment(result);
1807}
1808
1809
Ben Murdoch257744e2011-11-30 15:57:28 +00001810LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1811 HValue* value = instr->value();
1812 Representation input_rep = value->representation();
1813 if (input_rep.IsDouble()) {
1814 LOperand* reg = UseRegister(value);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001815 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
Ben Murdoch257744e2011-11-30 15:57:28 +00001816 } else if (input_rep.IsInteger32()) {
1817 LOperand* reg = UseFixed(value, eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001818 return DefineFixed(new(zone()) LClampIToUint8(reg), eax);
Ben Murdoch257744e2011-11-30 15:57:28 +00001819 } else {
1820 ASSERT(input_rep.IsTagged());
1821 LOperand* reg = UseFixed(value, eax);
1822 // Register allocator doesn't (yet) support allocation of double
1823 // temps. Reserve xmm1 explicitly.
1824 LOperand* temp = FixedTemp(xmm1);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001825 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp);
Ben Murdoch257744e2011-11-30 15:57:28 +00001826 return AssignEnvironment(DefineFixed(result, eax));
1827 }
1828}
1829
1830
Ben Murdochb0fe1622011-05-05 13:52:32 +01001831LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001832 return new(zone()) LReturn(UseFixed(instr->value(), eax));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001833}
1834
1835
1836LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1837 Representation r = instr->representation();
1838 if (r.IsInteger32()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001839 return DefineAsRegister(new(zone()) LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001840 } else if (r.IsDouble()) {
1841 double value = instr->DoubleValue();
Steve Block1e0659c2011-05-24 12:43:12 +01001842 LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
1843 ? TempRegister()
1844 : NULL;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001845 return DefineAsRegister(new(zone()) LConstantD(temp));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001846 } else if (r.IsTagged()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001847 return DefineAsRegister(new(zone()) LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001848 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001849 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001850 return NULL;
1851 }
1852}
1853
1854
Ben Murdoch8b112d22011-06-08 16:22:53 +01001855LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001856 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
1857 return instr->RequiresHoleCheck()
Ben Murdochb0fe1622011-05-05 13:52:32 +01001858 ? AssignEnvironment(DefineAsRegister(result))
1859 : DefineAsRegister(result);
1860}
1861
1862
Ben Murdoch8b112d22011-06-08 16:22:53 +01001863LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1864 LOperand* context = UseFixed(instr->context(), esi);
1865 LOperand* global_object = UseFixed(instr->global_object(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001866 LLoadGlobalGeneric* result =
1867 new(zone()) LLoadGlobalGeneric(context, global_object);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001868 return MarkAsCall(DefineFixed(result, eax), instr);
1869}
1870
1871
1872LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1873 LStoreGlobalCell* result =
Ben Murdochc7cc0282012-03-05 14:35:55 +00001874 new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001875 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001876}
1877
1878
Ben Murdoch8b112d22011-06-08 16:22:53 +01001879LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1880 LOperand* context = UseFixed(instr->context(), esi);
1881 LOperand* global_object = UseFixed(instr->global_object(), edx);
1882 LOperand* value = UseFixed(instr->value(), eax);
1883 LStoreGlobalGeneric* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001884 new(zone()) LStoreGlobalGeneric(context, global_object, value);
Ben Murdoch8b112d22011-06-08 16:22:53 +01001885 return MarkAsCall(result, instr);
1886}
1887
1888
Ben Murdochb8e0da22011-05-16 14:20:40 +01001889LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001890 LOperand* context = UseRegisterAtStart(instr->value());
Ben Murdochc7cc0282012-03-05 14:35:55 +00001891 LInstruction* result =
1892 DefineAsRegister(new(zone()) LLoadContextSlot(context));
1893 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
Steve Block1e0659c2011-05-24 12:43:12 +01001894}
1895
1896
1897LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001898 LOperand* value;
1899 LOperand* temp;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001900 LOperand* context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001901 if (instr->NeedsWriteBarrier()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001902 value = UseTempRegister(instr->value());
1903 temp = TempRegister();
1904 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001905 value = UseRegister(instr->value());
1906 temp = NULL;
1907 }
Ben Murdochc7cc0282012-03-05 14:35:55 +00001908 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
1909 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001910}
1911
1912
Ben Murdochb0fe1622011-05-05 13:52:32 +01001913LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001914 ASSERT(instr->representation().IsTagged());
1915 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001916 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001917}
1918
1919
Steve Block44f0eee2011-05-26 01:26:41 +01001920LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1921 HLoadNamedFieldPolymorphic* instr) {
1922 ASSERT(instr->representation().IsTagged());
1923 if (instr->need_generic()) {
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001924 LOperand* context = UseFixed(instr->context(), esi);
Steve Block44f0eee2011-05-26 01:26:41 +01001925 LOperand* obj = UseFixed(instr->object(), eax);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001926 LLoadNamedFieldPolymorphic* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001927 new(zone()) LLoadNamedFieldPolymorphic(context, obj);
Steve Block44f0eee2011-05-26 01:26:41 +01001928 return MarkAsCall(DefineFixed(result, eax), instr);
1929 } else {
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001930 LOperand* context = UseAny(instr->context()); // Not actually used.
Steve Block44f0eee2011-05-26 01:26:41 +01001931 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001932 LLoadNamedFieldPolymorphic* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001933 new(zone()) LLoadNamedFieldPolymorphic(context, obj);
Steve Block44f0eee2011-05-26 01:26:41 +01001934 return AssignEnvironment(DefineAsRegister(result));
1935 }
1936}
1937
1938
Ben Murdochb0fe1622011-05-05 13:52:32 +01001939LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001940 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001941 LOperand* object = UseFixed(instr->object(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001942 LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001943 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001944}
1945
1946
Steve Block9fac8402011-05-12 15:51:54 +01001947LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1948 HLoadFunctionPrototype* instr) {
1949 return AssignEnvironment(DefineAsRegister(
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001950 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
1951 TempRegister())));
Steve Block9fac8402011-05-12 15:51:54 +01001952}
1953
1954
Ben Murdochb0fe1622011-05-05 13:52:32 +01001955LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1956 LOperand* input = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001957 return DefineAsRegister(new(zone()) LLoadElements(input));
Steve Block1e0659c2011-05-24 12:43:12 +01001958}
1959
1960
Steve Block44f0eee2011-05-26 01:26:41 +01001961LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1962 HLoadExternalArrayPointer* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001963 LOperand* input = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001964 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001965}
1966
1967
1968LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1969 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001970 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001971 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001972 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001973 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001974 LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key);
Ben Murdochc7cc0282012-03-05 14:35:55 +00001975 if (instr->RequiresHoleCheck()) AssignEnvironment(result);
1976 return DefineAsRegister(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001977}
1978
1979
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001980LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1981 HLoadKeyedFastDoubleElement* instr) {
1982 ASSERT(instr->representation().IsDouble());
1983 ASSERT(instr->key()->representation().IsInteger32());
1984 LOperand* elements = UseRegisterAtStart(instr->elements());
1985 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1986 LLoadKeyedFastDoubleElement* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001987 new(zone()) LLoadKeyedFastDoubleElement(elements, key);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001988 return AssignEnvironment(DefineAsRegister(result));
1989}
1990
1991
Steve Block44f0eee2011-05-26 01:26:41 +01001992LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1993 HLoadKeyedSpecializedArrayElement* instr) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001994 ElementsKind elements_kind = instr->elements_kind();
Ben Murdoch257744e2011-11-30 15:57:28 +00001995 ASSERT(
Ben Murdochc7cc0282012-03-05 14:35:55 +00001996 (instr->representation().IsInteger32() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00001997 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1998 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
Ben Murdochc7cc0282012-03-05 14:35:55 +00001999 (instr->representation().IsDouble() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00002000 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2001 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
Steve Block1e0659c2011-05-24 12:43:12 +01002002 ASSERT(instr->key()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01002003 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch257744e2011-11-30 15:57:28 +00002004 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01002005 LLoadKeyedSpecializedArrayElement* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002006 new(zone()) LLoadKeyedSpecializedArrayElement(external_pointer,
Steve Block44f0eee2011-05-26 01:26:41 +01002007 key);
2008 LInstruction* load_instr = DefineAsRegister(result);
2009 // An unsigned int array load might overflow and cause a deopt, make sure it
2010 // has an environment.
Ben Murdoch589d6972011-11-30 16:04:58 +00002011 return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS)
Steve Block44f0eee2011-05-26 01:26:41 +01002012 ? AssignEnvironment(load_instr)
2013 : load_instr;
Steve Block1e0659c2011-05-24 12:43:12 +01002014}
2015
2016
Ben Murdochb0fe1622011-05-05 13:52:32 +01002017LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002018 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002019 LOperand* object = UseFixed(instr->object(), edx);
2020 LOperand* key = UseFixed(instr->key(), eax);
2021
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002022 LLoadKeyedGeneric* result =
2023 new(zone()) LLoadKeyedGeneric(context, object, key);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002024 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002025}
2026
2027
2028LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
2029 HStoreKeyedFastElement* instr) {
2030 bool needs_write_barrier = instr->NeedsWriteBarrier();
2031 ASSERT(instr->value()->representation().IsTagged());
2032 ASSERT(instr->object()->representation().IsTagged());
2033 ASSERT(instr->key()->representation().IsInteger32());
2034
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002035 LOperand* obj = UseRegister(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002036 LOperand* val = needs_write_barrier
2037 ? UseTempRegister(instr->value())
2038 : UseRegisterAtStart(instr->value());
2039 LOperand* key = needs_write_barrier
2040 ? UseTempRegister(instr->key())
2041 : UseRegisterOrConstantAtStart(instr->key());
Ben Murdochc7cc0282012-03-05 14:35:55 +00002042 return new(zone()) LStoreKeyedFastElement(obj, key, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002043}
2044
2045
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002046LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
2047 HStoreKeyedFastDoubleElement* instr) {
2048 ASSERT(instr->value()->representation().IsDouble());
2049 ASSERT(instr->elements()->representation().IsTagged());
2050 ASSERT(instr->key()->representation().IsInteger32());
2051
2052 LOperand* elements = UseRegisterAtStart(instr->elements());
2053 LOperand* val = UseTempRegister(instr->value());
2054 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2055
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002056 return new(zone()) LStoreKeyedFastDoubleElement(elements, key, val);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002057}
2058
2059
Steve Block44f0eee2011-05-26 01:26:41 +01002060LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
2061 HStoreKeyedSpecializedArrayElement* instr) {
Ben Murdoch589d6972011-11-30 16:04:58 +00002062 ElementsKind elements_kind = instr->elements_kind();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002063 ASSERT(
Ben Murdochc7cc0282012-03-05 14:35:55 +00002064 (instr->value()->representation().IsInteger32() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00002065 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2066 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
Ben Murdochc7cc0282012-03-05 14:35:55 +00002067 (instr->value()->representation().IsDouble() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00002068 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2069 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002070 ASSERT(instr->external_pointer()->representation().IsExternal());
2071 ASSERT(instr->key()->representation().IsInteger32());
2072
2073 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch257744e2011-11-30 15:57:28 +00002074 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01002075 LOperand* val = NULL;
Ben Murdoch589d6972011-11-30 16:04:58 +00002076 if (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
2077 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
2078 elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
Steve Block44f0eee2011-05-26 01:26:41 +01002079 // We need a byte register in this case for the value.
2080 val = UseFixed(instr->value(), eax);
2081 } else {
2082 val = UseRegister(instr->value());
2083 }
2084
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002085 return new(zone()) LStoreKeyedSpecializedArrayElement(external_pointer,
2086 key,
2087 val);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002088}
2089
2090
Ben Murdochb0fe1622011-05-05 13:52:32 +01002091LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002092 LOperand* context = UseFixed(instr->context(), esi);
2093 LOperand* object = UseFixed(instr->object(), edx);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002094 LOperand* key = UseFixed(instr->key(), ecx);
Steve Block1e0659c2011-05-24 12:43:12 +01002095 LOperand* value = UseFixed(instr->value(), eax);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002096
2097 ASSERT(instr->object()->representation().IsTagged());
2098 ASSERT(instr->key()->representation().IsTagged());
2099 ASSERT(instr->value()->representation().IsTagged());
2100
Steve Block1e0659c2011-05-24 12:43:12 +01002101 LStoreKeyedGeneric* result =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002102 new(zone()) LStoreKeyedGeneric(context, object, key, value);
Steve Block1e0659c2011-05-24 12:43:12 +01002103 return MarkAsCall(result, instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002104}
2105
2106
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002107LInstruction* LChunkBuilder::DoTransitionElementsKind(
2108 HTransitionElementsKind* instr) {
2109 if (instr->original_map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
2110 instr->transitioned_map()->elements_kind() == FAST_ELEMENTS) {
2111 LOperand* object = UseRegister(instr->object());
2112 LOperand* new_map_reg = TempRegister();
2113 LOperand* temp_reg = TempRegister();
2114 LTransitionElementsKind* result =
2115 new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
2116 return DefineSameAsFirst(result);
2117 } else {
2118 LOperand* object = UseFixed(instr->object(), eax);
2119 LOperand* fixed_object_reg = FixedTemp(edx);
2120 LOperand* new_map_reg = FixedTemp(ebx);
2121 LTransitionElementsKind* result =
2122 new(zone()) LTransitionElementsKind(object,
2123 new_map_reg,
2124 fixed_object_reg);
2125 return MarkAsCall(DefineFixed(result, eax), instr);
2126 }
2127}
2128
2129
Ben Murdochb0fe1622011-05-05 13:52:32 +01002130LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01002131 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01002132
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002133 LOperand* obj;
2134 if (needs_write_barrier) {
2135 obj = instr->is_in_object()
2136 ? UseRegister(instr->object())
2137 : UseTempRegister(instr->object());
2138 } else {
2139 obj = UseRegisterAtStart(instr->object());
2140 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002141
2142 LOperand* val = needs_write_barrier
2143 ? UseTempRegister(instr->value())
2144 : UseRegister(instr->value());
2145
2146 // We only need a scratch register if we have a write barrier or we
2147 // have a store into the properties array (not in-object-property).
2148 LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
Steve Block1e0659c2011-05-24 12:43:12 +01002149 ? TempRegister()
2150 : NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01002151
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002152 return new(zone()) LStoreNamedField(obj, val, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002153}
2154
2155
2156LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002157 LOperand* context = UseFixed(instr->context(), esi);
2158 LOperand* object = UseFixed(instr->object(), edx);
2159 LOperand* value = UseFixed(instr->value(), eax);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002160
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002161 LStoreNamedGeneric* result =
2162 new(zone()) LStoreNamedGeneric(context, object, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002163 return MarkAsCall(result, instr);
2164}
2165
2166
Ben Murdoch257744e2011-11-30 15:57:28 +00002167LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002168 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch257744e2011-11-30 15:57:28 +00002169 LOperand* left = UseOrConstantAtStart(instr->left());
2170 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002171 LStringAdd* string_add = new(zone()) LStringAdd(context, left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002172 return MarkAsCall(DefineFixed(string_add, eax), instr);
Ben Murdoch257744e2011-11-30 15:57:28 +00002173}
2174
2175
Steve Block1e0659c2011-05-24 12:43:12 +01002176LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002177 LOperand* string = UseTempRegister(instr->string());
2178 LOperand* index = UseTempRegister(instr->index());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002179 LOperand* context = UseAny(instr->context());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002180 LStringCharCodeAt* result =
2181 new(zone()) LStringCharCodeAt(context, string, index);
Steve Block1e0659c2011-05-24 12:43:12 +01002182 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2183}
2184
2185
Steve Block44f0eee2011-05-26 01:26:41 +01002186LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2187 LOperand* char_code = UseRegister(instr->value());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002188 LOperand* context = UseAny(instr->context());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002189 LStringCharFromCode* result =
2190 new(zone()) LStringCharFromCode(context, char_code);
Steve Block44f0eee2011-05-26 01:26:41 +01002191 return AssignPointerMap(DefineAsRegister(result));
2192}
2193
2194
Steve Block1e0659c2011-05-24 12:43:12 +01002195LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2196 LOperand* string = UseRegisterAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002197 return DefineAsRegister(new(zone()) LStringLength(string));
Steve Block1e0659c2011-05-24 12:43:12 +01002198}
2199
2200
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01002201LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
2202 LOperand* context = UseFixed(instr->context(), esi);
2203 LOperand* temp = TempRegister();
2204 LAllocateObject* result = new(zone()) LAllocateObject(context, temp);
2205 return AssignPointerMap(DefineAsRegister(result));
2206}
2207
2208
2209LInstruction* LChunkBuilder::DoFastLiteral(HFastLiteral* instr) {
2210 LOperand* context = UseFixed(instr->context(), esi);
2211 return MarkAsCall(
2212 DefineFixed(new(zone()) LFastLiteral(context), eax), instr);
2213}
2214
2215
Ben Murdochb0fe1622011-05-05 13:52:32 +01002216LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002217 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002218 return MarkAsCall(
2219 DefineFixed(new(zone()) LArrayLiteral(context), eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002220}
2221
2222
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01002223LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002224 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002225 return MarkAsCall(
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01002226 DefineFixed(new(zone()) LObjectLiteral(context), eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002227}
2228
2229
2230LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002231 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002232 return MarkAsCall(
2233 DefineFixed(new(zone()) LRegExpLiteral(context), eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002234}
2235
2236
2237LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002238 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002239 return MarkAsCall(
2240 DefineFixed(new(zone()) LFunctionLiteral(context), eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002241}
2242
2243
2244LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002245 LOperand* context = UseFixed(instr->context(), esi);
2246 LOperand* object = UseAtStart(instr->object());
2247 LOperand* key = UseOrConstantAtStart(instr->key());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002248 LDeleteProperty* result = new(zone()) LDeleteProperty(context, object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002249 return MarkAsCall(DefineFixed(result, eax), instr);
2250}
2251
2252
2253LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2254 allocator_->MarkAsOsrEntry();
2255 current_block_->last_environment()->set_ast_id(instr->ast_id());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002256 return AssignEnvironment(new(zone()) LOsrEntry);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002257}
2258
2259
2260LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2261 int spill_index = chunk()->GetParameterStackSlot(instr->index());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002262 return DefineAsSpilled(new(zone()) LParameter, spill_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002263}
2264
2265
2266LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2267 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +01002268 if (spill_index > LUnallocated::kMaxFixedIndex) {
2269 Abort("Too many spill slots needed for OSR");
2270 spill_index = 0;
2271 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002272 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002273}
2274
2275
2276LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002277 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002278 argument_count_ -= instr->argument_count();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002279 LCallStub* result = new(zone()) LCallStub(context);
Steve Block1e0659c2011-05-24 12:43:12 +01002280 return MarkAsCall(DefineFixed(result, eax), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002281}
2282
2283
2284LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002285 // There are no real uses of the arguments object.
2286 // arguments.length and element access are supported directly on
2287 // stack arguments, and any real arguments object use causes a bailout.
2288 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002289 return NULL;
2290}
2291
2292
2293LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2294 LOperand* arguments = UseRegister(instr->arguments());
2295 LOperand* length = UseTempRegister(instr->length());
2296 LOperand* index = Use(instr->index());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002297 LAccessArgumentsAt* result =
2298 new(zone()) LAccessArgumentsAt(arguments, length, index);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002299 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002300}
2301
2302
Steve Block44f0eee2011-05-26 01:26:41 +01002303LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2304 LOperand* object = UseFixed(instr->value(), eax);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002305 LToFastProperties* result = new(zone()) LToFastProperties(object);
Steve Block44f0eee2011-05-26 01:26:41 +01002306 return MarkAsCall(DefineFixed(result, eax), instr);
2307}
2308
2309
Ben Murdochb0fe1622011-05-05 13:52:32 +01002310LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002311 LOperand* context = UseFixed(instr->context(), esi);
2312 LOperand* value = UseAtStart(instr->value());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002313 LTypeof* result = new(zone()) LTypeof(context, value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002314 return MarkAsCall(DefineFixed(result, eax), instr);
2315}
2316
2317
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002318LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002319 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002320}
2321
Steve Block1e0659c2011-05-24 12:43:12 +01002322
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002323LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2324 HIsConstructCallAndBranch* instr) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002325 return new(zone()) LIsConstructCallAndBranch(TempRegister());
Steve Block1e0659c2011-05-24 12:43:12 +01002326}
2327
2328
Ben Murdochb0fe1622011-05-05 13:52:32 +01002329LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2330 HEnvironment* env = current_block_->last_environment();
2331 ASSERT(env != NULL);
2332
2333 env->set_ast_id(instr->ast_id());
2334
2335 env->Drop(instr->pop_count());
2336 for (int i = 0; i < instr->values()->length(); ++i) {
2337 HValue* value = instr->values()->at(i);
2338 if (instr->HasAssignedIndexAt(i)) {
2339 env->Bind(instr->GetAssignedIndexAt(i), value);
2340 } else {
2341 env->Push(value);
2342 }
2343 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002344
2345 // If there is an instruction pending deoptimization environment create a
2346 // lazy bailout instruction to capture the environment.
Steve Block1e0659c2011-05-24 12:43:12 +01002347 if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
2348 ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002349 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002350 LInstruction* result = AssignEnvironment(lazy_bailout);
Steve Block1e0659c2011-05-24 12:43:12 +01002351 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002352 set_deoptimization_environment(result->environment());
2353 ClearInstructionPendingDeoptimizationEnvironment();
2354 return result;
2355 }
2356
2357 return NULL;
2358}
2359
2360
2361LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002362 if (instr->is_function_entry()) {
2363 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002364 return MarkAsCall(new(zone()) LStackCheck(context), instr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002365 } else {
2366 ASSERT(instr->is_backwards_branch());
2367 LOperand* context = UseAny(instr->context());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002368 return AssignEnvironment(
2369 AssignPointerMap(new(zone()) LStackCheck(context)));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002370 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002371}
2372
2373
2374LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2375 HEnvironment* outer = current_block_->last_environment();
2376 HConstant* undefined = graph()->GetConstantUndefined();
2377 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
Ben Murdochc7cc0282012-03-05 14:35:55 +00002378 instr->arguments_count(),
Ben Murdochb0fe1622011-05-05 13:52:32 +01002379 instr->function(),
Ben Murdoch257744e2011-11-30 15:57:28 +00002380 undefined,
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01002381 instr->call_kind(),
2382 instr->is_construct());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002383 current_block_->UpdateEnvironment(inner);
2384 chunk_->AddInlinedClosure(instr->closure());
2385 return NULL;
2386}
2387
2388
2389LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00002390 HEnvironment* outer = current_block_->last_environment()->
2391 DiscardInlined(false);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002392 current_block_->UpdateEnvironment(outer);
2393 return NULL;
2394}
2395
2396
Ben Murdoch257744e2011-11-30 15:57:28 +00002397LInstruction* LChunkBuilder::DoIn(HIn* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002398 LOperand* context = UseFixed(instr->context(), esi);
Ben Murdoch257744e2011-11-30 15:57:28 +00002399 LOperand* key = UseOrConstantAtStart(instr->key());
2400 LOperand* object = UseOrConstantAtStart(instr->object());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002401 LIn* result = new(zone()) LIn(context, key, object);
Ben Murdoch257744e2011-11-30 15:57:28 +00002402 return MarkAsCall(DefineFixed(result, eax), instr);
2403}
2404
2405
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01002406LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2407 LOperand* context = UseFixed(instr->context(), esi);
2408 LOperand* object = UseFixed(instr->enumerable(), eax);
2409 LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2410 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2411}
2412
2413
2414LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2415 LOperand* map = UseRegister(instr->map());
2416 return AssignEnvironment(DefineAsRegister(
2417 new(zone()) LForInCacheArray(map)));
2418}
2419
2420
2421LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2422 LOperand* value = UseRegisterAtStart(instr->value());
2423 LOperand* map = UseRegisterAtStart(instr->map());
2424 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2425}
2426
2427
2428LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2429 LOperand* object = UseRegister(instr->object());
2430 LOperand* index = UseTempRegister(instr->index());
2431 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
2432}
2433
2434
Ben Murdochb0fe1622011-05-05 13:52:32 +01002435} } // namespace v8::internal
Ben Murdochb8e0da22011-05-16 14:20:40 +01002436
2437#endif // V8_TARGET_ARCH_IA32