blob: 30ccd05beecb39c979a4dbe91ee301d381390d7d [file] [log] [blame]
Ben Murdoch086aeea2011-05-13 15:57:08 +01001// Copyright 2011 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
Steve Block44f0eee2011-05-26 01:26:41 +010028#include "v8.h"
29
Steve Block1e0659c2011-05-24 12:43:12 +010030#include "lithium-allocator-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010031#include "arm/lithium-arm.h"
32#include "arm/lithium-codegen-arm.h"
33
34namespace v8 {
35namespace internal {
36
37#define DEFINE_COMPILE(type) \
38 void L##type::CompileToNative(LCodeGen* generator) { \
39 generator->Do##type(this); \
40 }
41LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
42#undef DEFINE_COMPILE
43
44LOsrEntry::LOsrEntry() {
45 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
46 register_spills_[i] = NULL;
47 }
48 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
49 double_register_spills_[i] = NULL;
50 }
51}
52
53
54void LOsrEntry::MarkSpilledRegister(int allocation_index,
55 LOperand* spill_operand) {
56 ASSERT(spill_operand->IsStackSlot());
57 ASSERT(register_spills_[allocation_index] == NULL);
58 register_spills_[allocation_index] = spill_operand;
59}
60
61
Steve Block1e0659c2011-05-24 12:43:12 +010062#ifdef DEBUG
63void LInstruction::VerifyCall() {
Ben Murdoch257744e2011-11-30 15:57:28 +000064 // Call instructions can use only fixed registers as temporaries and
65 // outputs because all registers are blocked by the calling convention.
66 // Inputs operands must use a fixed register or use-at-start policy or
67 // a non-register policy.
Steve Block1e0659c2011-05-24 12:43:12 +010068 ASSERT(Output() == NULL ||
69 LUnallocated::cast(Output())->HasFixedPolicy() ||
70 !LUnallocated::cast(Output())->HasRegisterPolicy());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000071 for (UseIterator it(this); !it.Done(); it.Advance()) {
72 LUnallocated* operand = LUnallocated::cast(it.Current());
Ben Murdoch257744e2011-11-30 15:57:28 +000073 ASSERT(operand->HasFixedPolicy() ||
74 operand->IsUsedAtStart());
Steve Block1e0659c2011-05-24 12:43:12 +010075 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000076 for (TempIterator it(this); !it.Done(); it.Advance()) {
77 LUnallocated* operand = LUnallocated::cast(it.Current());
Ben Murdoch257744e2011-11-30 15:57:28 +000078 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
Steve Block1e0659c2011-05-24 12:43:12 +010079 }
80}
81#endif
82
83
Ben Murdochb0fe1622011-05-05 13:52:32 +010084void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
85 LOperand* spill_operand) {
86 ASSERT(spill_operand->IsDoubleStackSlot());
87 ASSERT(double_register_spills_[allocation_index] == NULL);
88 double_register_spills_[allocation_index] = spill_operand;
89}
90
91
Steve Block1e0659c2011-05-24 12:43:12 +010092void LInstruction::PrintTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +010093 stream->Add("%s ", this->Mnemonic());
Steve Block1e0659c2011-05-24 12:43:12 +010094
95 PrintOutputOperandTo(stream);
96
Ben Murdochb0fe1622011-05-05 13:52:32 +010097 PrintDataTo(stream);
98
99 if (HasEnvironment()) {
100 stream->Add(" ");
101 environment()->PrintTo(stream);
102 }
103
104 if (HasPointerMap()) {
105 stream->Add(" ");
106 pointer_map()->PrintTo(stream);
107 }
108}
109
110
Steve Block1e0659c2011-05-24 12:43:12 +0100111template<int R, int I, int T>
112void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
113 stream->Add("= ");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000114 for (int i = 0; i < inputs_.length(); i++) {
115 if (i > 0) stream->Add(" ");
116 inputs_[i]->PrintTo(stream);
117 }
Steve Block1e0659c2011-05-24 12:43:12 +0100118}
119
120
121template<int R, int I, int T>
122void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000123 for (int i = 0; i < results_.length(); i++) {
Steve Block1e0659c2011-05-24 12:43:12 +0100124 if (i > 0) stream->Add(" ");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000125 results_[i]->PrintTo(stream);
Steve Block1e0659c2011-05-24 12:43:12 +0100126 }
127}
128
129
130void LLabel::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100131 LGap::PrintDataTo(stream);
132 LLabel* rep = replacement();
133 if (rep != NULL) {
134 stream->Add(" Dead block replaced with B%d", rep->block_id());
135 }
136}
137
138
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139bool LGap::IsRedundant() const {
140 for (int i = 0; i < 4; i++) {
141 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
142 return false;
143 }
144 }
145
146 return true;
147}
148
149
Ben Murdoch257744e2011-11-30 15:57:28 +0000150void LGap::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100151 for (int i = 0; i < 4; i++) {
152 stream->Add("(");
153 if (parallel_moves_[i] != NULL) {
154 parallel_moves_[i]->PrintDataTo(stream);
155 }
156 stream->Add(") ");
157 }
158}
159
160
161const char* LArithmeticD::Mnemonic() const {
162 switch (op()) {
163 case Token::ADD: return "add-d";
164 case Token::SUB: return "sub-d";
165 case Token::MUL: return "mul-d";
166 case Token::DIV: return "div-d";
167 case Token::MOD: return "mod-d";
168 default:
169 UNREACHABLE();
170 return NULL;
171 }
172}
173
174
175const char* LArithmeticT::Mnemonic() const {
176 switch (op()) {
177 case Token::ADD: return "add-t";
178 case Token::SUB: return "sub-t";
179 case Token::MUL: return "mul-t";
180 case Token::MOD: return "mod-t";
181 case Token::DIV: return "div-t";
Steve Block1e0659c2011-05-24 12:43:12 +0100182 case Token::BIT_AND: return "bit-and-t";
183 case Token::BIT_OR: return "bit-or-t";
184 case Token::BIT_XOR: return "bit-xor-t";
185 case Token::SHL: return "shl-t";
186 case Token::SAR: return "sar-t";
187 case Token::SHR: return "shr-t";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100188 default:
189 UNREACHABLE();
190 return NULL;
191 }
192}
193
194
Steve Block1e0659c2011-05-24 12:43:12 +0100195void LGoto::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100196 stream->Add("B%d", block_id());
197}
198
199
Steve Block1e0659c2011-05-24 12:43:12 +0100200void LBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100201 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
Steve Block1e0659c2011-05-24 12:43:12 +0100202 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100203}
204
205
Steve Block1e0659c2011-05-24 12:43:12 +0100206void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100207 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100208 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100209 stream->Add(" %s ", Token::String(op()));
Steve Block1e0659c2011-05-24 12:43:12 +0100210 InputAt(1)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100211 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
212}
213
214
Steve Block1e0659c2011-05-24 12:43:12 +0100215void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100216 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100217 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100218 stream->Add(is_strict() ? " === null" : " == null");
219 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
220}
221
222
Steve Block1e0659c2011-05-24 12:43:12 +0100223void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 stream->Add("if is_object(");
Steve Block1e0659c2011-05-24 12:43:12 +0100225 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
227}
228
229
Steve Block1e0659c2011-05-24 12:43:12 +0100230void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100231 stream->Add("if is_smi(");
Steve Block1e0659c2011-05-24 12:43:12 +0100232 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
234}
235
236
Ben Murdoch257744e2011-11-30 15:57:28 +0000237void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
238 stream->Add("if is_undetectable(");
239 InputAt(0)->PrintTo(stream);
240 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
241}
242
243
Steve Block1e0659c2011-05-24 12:43:12 +0100244void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100245 stream->Add("if has_instance_type(");
Steve Block1e0659c2011-05-24 12:43:12 +0100246 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100247 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
248}
249
250
Steve Block1e0659c2011-05-24 12:43:12 +0100251void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100252 stream->Add("if has_cached_array_index(");
Steve Block1e0659c2011-05-24 12:43:12 +0100253 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100254 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
255}
256
257
Steve Block1e0659c2011-05-24 12:43:12 +0100258void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100259 stream->Add("if class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100260 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100261 stream->Add(", \"%o\") then B%d else B%d",
262 *hydrogen()->class_name(),
263 true_block_id(),
264 false_block_id());
265}
266
267
Steve Block1e0659c2011-05-24 12:43:12 +0100268void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100269 stream->Add("if typeof ");
Steve Block1e0659c2011-05-24 12:43:12 +0100270 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100271 stream->Add(" == \"%s\" then B%d else B%d",
272 *hydrogen()->type_literal()->ToCString(),
273 true_block_id(), false_block_id());
274}
275
276
Steve Block1e0659c2011-05-24 12:43:12 +0100277void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100278 stream->Add("#%d / ", arity());
279}
280
281
Steve Block1e0659c2011-05-24 12:43:12 +0100282void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100283 stream->Add("/%s ", hydrogen()->OpName());
Steve Block1e0659c2011-05-24 12:43:12 +0100284 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100285}
286
287
Ben Murdochb8e0da22011-05-16 14:20:40 +0100288void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100289 InputAt(0)->PrintTo(stream);
290 stream->Add("[%d]", slot_index());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100291}
292
293
Steve Block1e0659c2011-05-24 12:43:12 +0100294void LStoreContextSlot::PrintDataTo(StringStream* stream) {
295 InputAt(0)->PrintTo(stream);
296 stream->Add("[%d] <- ", slot_index());
297 InputAt(1)->PrintTo(stream);
298}
299
300
Ben Murdoch257744e2011-11-30 15:57:28 +0000301void LInvokeFunction::PrintDataTo(StringStream* stream) {
302 stream->Add("= ");
303 InputAt(0)->PrintTo(stream);
304 stream->Add(" #%d / ", arity());
305}
306
307
Steve Block1e0659c2011-05-24 12:43:12 +0100308void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100309 stream->Add("[r2] #%d / ", arity());
310}
311
312
Steve Block1e0659c2011-05-24 12:43:12 +0100313void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000314 SmartArrayPointer<char> name_string = name()->ToCString();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100315 stream->Add("%s #%d / ", *name_string, arity());
316}
317
318
Steve Block1e0659c2011-05-24 12:43:12 +0100319void LCallGlobal::PrintDataTo(StringStream* stream) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000320 SmartArrayPointer<char> name_string = name()->ToCString();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100321 stream->Add("%s #%d / ", *name_string, arity());
322}
323
324
Steve Block1e0659c2011-05-24 12:43:12 +0100325void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100326 stream->Add("#%d / ", arity());
327}
328
329
Steve Block1e0659c2011-05-24 12:43:12 +0100330void LCallNew::PrintDataTo(StringStream* stream) {
331 stream->Add("= ");
332 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100333 stream->Add(" #%d / ", arity());
334}
335
336
Steve Block1e0659c2011-05-24 12:43:12 +0100337void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100338 arguments()->PrintTo(stream);
339
340 stream->Add(" length ");
341 length()->PrintTo(stream);
342
343 stream->Add(" index ");
344 index()->PrintTo(stream);
345}
346
347
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100348void LStoreNamedField::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100349 object()->PrintTo(stream);
350 stream->Add(".");
351 stream->Add(*String::cast(*name())->ToCString());
352 stream->Add(" <- ");
353 value()->PrintTo(stream);
354}
355
356
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100357void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
358 object()->PrintTo(stream);
359 stream->Add(".");
360 stream->Add(*String::cast(*name())->ToCString());
361 stream->Add(" <- ");
362 value()->PrintTo(stream);
363}
364
365
366void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100367 object()->PrintTo(stream);
368 stream->Add("[");
369 key()->PrintTo(stream);
370 stream->Add("] <- ");
371 value()->PrintTo(stream);
372}
373
374
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000375void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
376 elements()->PrintTo(stream);
377 stream->Add("[");
378 key()->PrintTo(stream);
379 stream->Add("] <- ");
380 value()->PrintTo(stream);
381}
382
383
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100384void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
385 object()->PrintTo(stream);
386 stream->Add("[");
387 key()->PrintTo(stream);
388 stream->Add("] <- ");
389 value()->PrintTo(stream);
390}
391
392
393LChunk::LChunk(CompilationInfo* info, HGraph* graph)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100394 : spill_slot_count_(0),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100395 info_(info),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100396 graph_(graph),
397 instructions_(32),
398 pointer_maps_(8),
399 inlined_closures_(1) {
400}
401
402
Ben Murdochb0fe1622011-05-05 13:52:32 +0100403int LChunk::GetNextSpillIndex(bool is_double) {
404 // Skip a slot if for a double-width slot.
405 if (is_double) spill_slot_count_++;
406 return spill_slot_count_++;
407}
408
409
410LOperand* LChunk::GetNextSpillSlot(bool is_double) {
411 int index = GetNextSpillIndex(is_double);
412 if (is_double) {
413 return LDoubleStackSlot::Create(index);
414 } else {
415 return LStackSlot::Create(index);
416 }
417}
418
419
420void LChunk::MarkEmptyBlocks() {
421 HPhase phase("Mark empty blocks", this);
422 for (int i = 0; i < graph()->blocks()->length(); ++i) {
423 HBasicBlock* block = graph()->blocks()->at(i);
424 int first = block->first_instruction_index();
425 int last = block->last_instruction_index();
426 LInstruction* first_instr = instructions()->at(first);
427 LInstruction* last_instr = instructions()->at(last);
428
429 LLabel* label = LLabel::cast(first_instr);
430 if (last_instr->IsGoto()) {
431 LGoto* goto_instr = LGoto::cast(last_instr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000432 if (label->IsRedundant() &&
Ben Murdochb0fe1622011-05-05 13:52:32 +0100433 !label->is_loop_header()) {
434 bool can_eliminate = true;
435 for (int i = first + 1; i < last && can_eliminate; ++i) {
436 LInstruction* cur = instructions()->at(i);
437 if (cur->IsGap()) {
438 LGap* gap = LGap::cast(cur);
439 if (!gap->IsRedundant()) {
440 can_eliminate = false;
441 }
442 } else {
443 can_eliminate = false;
444 }
445 }
446
447 if (can_eliminate) {
448 label->set_replacement(GetLabel(goto_instr->block_id()));
449 }
450 }
451 }
452 }
453}
454
455
Steve Block1e0659c2011-05-24 12:43:12 +0100456void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000457 LInstructionGap* gap = new LInstructionGap(block);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100458 int index = -1;
459 if (instr->IsControl()) {
460 instructions_.Add(gap);
461 index = instructions_.length();
462 instructions_.Add(instr);
463 } else {
464 index = instructions_.length();
465 instructions_.Add(instr);
466 instructions_.Add(gap);
467 }
468 if (instr->HasPointerMap()) {
469 pointer_maps_.Add(instr->pointer_map());
470 instr->pointer_map()->set_lithium_position(index);
471 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100472}
473
474
475LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
476 return LConstantOperand::Create(constant->id());
477}
478
479
480int LChunk::GetParameterStackSlot(int index) const {
481 // The receiver is at index 0, the first parameter at index 1, so we
482 // shift all parameter indexes down by the number of parameters, and
483 // make sure they end up negative so they are distinguishable from
484 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100485 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100486 ASSERT(result < 0);
487 return result;
488}
489
490// A parameter relative to ebp in the arguments stub.
491int LChunk::ParameterAt(int index) {
492 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100493 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100494 kPointerSize;
495}
496
497
498LGap* LChunk::GetGapAt(int index) const {
499 return LGap::cast(instructions_[index]);
500}
501
502
503bool LChunk::IsGapAt(int index) const {
504 return instructions_[index]->IsGap();
505}
506
507
508int LChunk::NearestGapPos(int index) const {
509 while (!IsGapAt(index)) index--;
510 return index;
511}
512
513
514void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
515 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
516}
517
518
Ben Murdochb0fe1622011-05-05 13:52:32 +0100519Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
520 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
521}
522
523
524Representation LChunk::LookupLiteralRepresentation(
525 LConstantOperand* operand) const {
526 return graph_->LookupValue(operand->index())->representation();
527}
528
529
530LChunk* LChunkBuilder::Build() {
531 ASSERT(is_unused());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100532 chunk_ = new LChunk(info(), graph());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100533 HPhase phase("Building chunk", chunk_);
534 status_ = BUILDING;
535 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
536 for (int i = 0; i < blocks->length(); i++) {
537 HBasicBlock* next = NULL;
538 if (i < blocks->length() - 1) next = blocks->at(i + 1);
539 DoBasicBlock(blocks->at(i), next);
540 if (is_aborted()) return NULL;
541 }
542 status_ = DONE;
543 return chunk_;
544}
545
546
547void LChunkBuilder::Abort(const char* format, ...) {
548 if (FLAG_trace_bailout) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000549 SmartArrayPointer<char> name(
550 info()->shared_info()->DebugName()->ToCString());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100551 PrintF("Aborting LChunk building in @\"%s\": ", *name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100552 va_list arguments;
553 va_start(arguments, format);
554 OS::VPrint(format, arguments);
555 va_end(arguments);
556 PrintF("\n");
557 }
558 status_ = ABORTED;
559}
560
561
562LRegister* LChunkBuilder::ToOperand(Register reg) {
563 return LRegister::Create(Register::ToAllocationIndex(reg));
564}
565
566
567LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
568 return new LUnallocated(LUnallocated::FIXED_REGISTER,
569 Register::ToAllocationIndex(reg));
570}
571
572
573LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
574 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
575 DoubleRegister::ToAllocationIndex(reg));
576}
577
578
579LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
580 return Use(value, ToUnallocated(fixed_register));
581}
582
583
584LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
585 return Use(value, ToUnallocated(reg));
586}
587
588
589LOperand* LChunkBuilder::UseRegister(HValue* value) {
590 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
591}
592
593
594LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
595 return Use(value,
596 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
597 LUnallocated::USED_AT_START));
598}
599
600
601LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
602 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
603}
604
605
606LOperand* LChunkBuilder::Use(HValue* value) {
607 return Use(value, new LUnallocated(LUnallocated::NONE));
608}
609
610
611LOperand* LChunkBuilder::UseAtStart(HValue* value) {
612 return Use(value, new LUnallocated(LUnallocated::NONE,
613 LUnallocated::USED_AT_START));
614}
615
616
617LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
618 return value->IsConstant()
619 ? chunk_->DefineConstantOperand(HConstant::cast(value))
620 : Use(value);
621}
622
623
624LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
625 return value->IsConstant()
626 ? chunk_->DefineConstantOperand(HConstant::cast(value))
627 : UseAtStart(value);
628}
629
630
631LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
632 return value->IsConstant()
633 ? chunk_->DefineConstantOperand(HConstant::cast(value))
634 : UseRegister(value);
635}
636
637
638LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
639 return value->IsConstant()
640 ? chunk_->DefineConstantOperand(HConstant::cast(value))
641 : UseRegisterAtStart(value);
642}
643
644
Ben Murdochb8e0da22011-05-16 14:20:40 +0100645LOperand* LChunkBuilder::UseAny(HValue* value) {
646 return value->IsConstant()
647 ? chunk_->DefineConstantOperand(HConstant::cast(value))
648 : Use(value, new LUnallocated(LUnallocated::ANY));
649}
650
651
Ben Murdochb0fe1622011-05-05 13:52:32 +0100652LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
653 if (value->EmitAtUses()) {
654 HInstruction* instr = HInstruction::cast(value);
655 VisitInstruction(instr);
656 }
657 allocator_->RecordUse(value, operand);
658 return operand;
659}
660
661
Steve Block1e0659c2011-05-24 12:43:12 +0100662template<int I, int T>
663LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
664 LUnallocated* result) {
665 allocator_->RecordDefinition(current_instruction_, result);
666 instr->set_result(result);
667 return instr;
668}
669
670
671template<int I, int T>
672LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 return Define(instr, new LUnallocated(LUnallocated::NONE));
674}
675
676
Steve Block1e0659c2011-05-24 12:43:12 +0100677template<int I, int T>
678LInstruction* LChunkBuilder::DefineAsRegister(
679 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100680 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
681}
682
683
Steve Block1e0659c2011-05-24 12:43:12 +0100684template<int I, int T>
685LInstruction* LChunkBuilder::DefineAsSpilled(
686 LTemplateInstruction<1, I, T>* instr, int index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100687 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
688}
689
690
Steve Block1e0659c2011-05-24 12:43:12 +0100691template<int I, int T>
692LInstruction* LChunkBuilder::DefineSameAsFirst(
693 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100694 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
695}
696
697
Steve Block1e0659c2011-05-24 12:43:12 +0100698template<int I, int T>
699LInstruction* LChunkBuilder::DefineFixed(
700 LTemplateInstruction<1, I, T>* instr, Register reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100701 return Define(instr, ToUnallocated(reg));
702}
703
704
Steve Block1e0659c2011-05-24 12:43:12 +0100705template<int I, int T>
706LInstruction* LChunkBuilder::DefineFixedDouble(
707 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100708 return Define(instr, ToUnallocated(reg));
709}
710
711
712LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
713 HEnvironment* hydrogen_env = current_block_->last_environment();
Ben Murdoch589d6972011-11-30 16:04:58 +0000714 instr->set_environment(CreateEnvironment(hydrogen_env));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715 return instr;
716}
717
718
719LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
720 LInstruction* instr, int ast_id) {
Steve Block1e0659c2011-05-24 12:43:12 +0100721 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100722 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
Steve Block1e0659c2011-05-24 12:43:12 +0100723 instruction_pending_deoptimization_environment_ = instr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100724 pending_deoptimization_ast_id_ = ast_id;
725 return instr;
726}
727
728
729void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
Steve Block1e0659c2011-05-24 12:43:12 +0100730 instruction_pending_deoptimization_environment_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100731 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
732}
733
734
735LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
736 HInstruction* hinstr,
737 CanDeoptimize can_deoptimize) {
Steve Block1e0659c2011-05-24 12:43:12 +0100738#ifdef DEBUG
739 instr->VerifyCall();
740#endif
741 instr->MarkAsCall();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100742 instr = AssignPointerMap(instr);
743
744 if (hinstr->HasSideEffects()) {
745 ASSERT(hinstr->next()->IsSimulate());
746 HSimulate* sim = HSimulate::cast(hinstr->next());
747 instr = SetInstructionPendingDeoptimizationEnvironment(
748 instr, sim->ast_id());
749 }
750
751 // If instruction does not have side-effects lazy deoptimization
752 // after the call will try to deoptimize to the point before the call.
753 // Thus we still need to attach environment to this call even if
754 // call sequence can not deoptimize eagerly.
755 bool needs_environment =
756 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
757 if (needs_environment && !instr->HasEnvironment()) {
758 instr = AssignEnvironment(instr);
759 }
760
761 return instr;
762}
763
764
Steve Block1e0659c2011-05-24 12:43:12 +0100765LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
766 instr->MarkAsSaveDoubles();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100767 return instr;
768}
769
770
Steve Block1e0659c2011-05-24 12:43:12 +0100771LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
772 ASSERT(!instr->HasPointerMap());
773 instr->set_pointer_map(new LPointerMap(position_));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 return instr;
775}
776
777
Ben Murdochb0fe1622011-05-05 13:52:32 +0100778LUnallocated* LChunkBuilder::TempRegister() {
779 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
780 allocator_->RecordTemporary(operand);
781 return operand;
782}
783
784
785LOperand* LChunkBuilder::FixedTemp(Register reg) {
786 LUnallocated* operand = ToUnallocated(reg);
787 allocator_->RecordTemporary(operand);
788 return operand;
789}
790
791
792LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
793 LUnallocated* operand = ToUnallocated(reg);
794 allocator_->RecordTemporary(operand);
795 return operand;
796}
797
798
799LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
800 return new LLabel(instr->block());
801}
802
803
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000804LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
805 return AssignEnvironment(new LDeoptimize);
806}
807
808
Ben Murdochb0fe1622011-05-05 13:52:32 +0100809LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
810 return AssignEnvironment(new LDeoptimize);
811}
812
813
814LInstruction* LChunkBuilder::DoBit(Token::Value op,
815 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100816 if (instr->representation().IsInteger32()) {
817 ASSERT(instr->left()->representation().IsInteger32());
818 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100819
Steve Block1e0659c2011-05-24 12:43:12 +0100820 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
821 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000822 return DefineAsRegister(new LBitI(op, left, right));
Steve Block1e0659c2011-05-24 12:43:12 +0100823 } else {
824 ASSERT(instr->representation().IsTagged());
825 ASSERT(instr->left()->representation().IsTagged());
826 ASSERT(instr->right()->representation().IsTagged());
827
828 LOperand* left = UseFixed(instr->left(), r1);
829 LOperand* right = UseFixed(instr->right(), r0);
830 LArithmeticT* result = new LArithmeticT(op, left, right);
831 return MarkAsCall(DefineFixed(result, r0), instr);
832 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100833}
834
835
836LInstruction* LChunkBuilder::DoShift(Token::Value op,
837 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100838 if (instr->representation().IsTagged()) {
839 ASSERT(instr->left()->representation().IsTagged());
840 ASSERT(instr->right()->representation().IsTagged());
841
842 LOperand* left = UseFixed(instr->left(), r1);
843 LOperand* right = UseFixed(instr->right(), r0);
844 LArithmeticT* result = new LArithmeticT(op, left, right);
845 return MarkAsCall(DefineFixed(result, r0), instr);
846 }
847
Ben Murdochb0fe1622011-05-05 13:52:32 +0100848 ASSERT(instr->representation().IsInteger32());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000849 ASSERT(instr->left()->representation().IsInteger32());
850 ASSERT(instr->right()->representation().IsInteger32());
851 LOperand* left = UseRegisterAtStart(instr->left());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100852
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000853 HValue* right_value = instr->right();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100854 LOperand* right = NULL;
855 int constant_value = 0;
856 if (right_value->IsConstant()) {
857 HConstant* constant = HConstant::cast(right_value);
858 right = chunk_->DefineConstantOperand(constant);
859 constant_value = constant->Integer32Value() & 0x1f;
860 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000861 right = UseRegisterAtStart(right_value);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100862 }
863
864 // Shift operations can only deoptimize if we do a logical shift
865 // by 0 and the result cannot be truncated to int32.
Ben Murdoch257744e2011-11-30 15:57:28 +0000866 bool may_deopt = (op == Token::SHR && constant_value == 0);
867 bool does_deopt = false;
868 if (may_deopt) {
869 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
870 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
871 does_deopt = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100872 break;
873 }
874 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100875 }
876
877 LInstruction* result =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000878 DefineAsRegister(new LShiftI(op, left, right, does_deopt));
Ben Murdoch257744e2011-11-30 15:57:28 +0000879 return does_deopt ? AssignEnvironment(result) : result;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100880}
881
882
883LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
884 HArithmeticBinaryOperation* instr) {
885 ASSERT(instr->representation().IsDouble());
886 ASSERT(instr->left()->representation().IsDouble());
887 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100888 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100889 LOperand* left = UseRegisterAtStart(instr->left());
890 LOperand* right = UseRegisterAtStart(instr->right());
891 LArithmeticD* result = new LArithmeticD(op, left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000892 return DefineAsRegister(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100893}
894
895
896LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
897 HArithmeticBinaryOperation* instr) {
898 ASSERT(op == Token::ADD ||
899 op == Token::DIV ||
900 op == Token::MOD ||
901 op == Token::MUL ||
902 op == Token::SUB);
903 HValue* left = instr->left();
904 HValue* right = instr->right();
905 ASSERT(left->representation().IsTagged());
906 ASSERT(right->representation().IsTagged());
907 LOperand* left_operand = UseFixed(left, r1);
908 LOperand* right_operand = UseFixed(right, r0);
Steve Block1e0659c2011-05-24 12:43:12 +0100909 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100910 return MarkAsCall(DefineFixed(result, r0), instr);
911}
912
Steve Block1e0659c2011-05-24 12:43:12 +0100913
Ben Murdochb0fe1622011-05-05 13:52:32 +0100914void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
915 ASSERT(is_building());
916 current_block_ = block;
917 next_block_ = next_block;
918 if (block->IsStartBlock()) {
919 block->UpdateEnvironment(graph_->start_environment());
920 argument_count_ = 0;
921 } else if (block->predecessors()->length() == 1) {
922 // We have a single predecessor => copy environment and outgoing
923 // argument count from the predecessor.
924 ASSERT(block->phis()->length() == 0);
925 HBasicBlock* pred = block->predecessors()->at(0);
926 HEnvironment* last_environment = pred->last_environment();
927 ASSERT(last_environment != NULL);
928 // Only copy the environment, if it is later used again.
929 if (pred->end()->SecondSuccessor() == NULL) {
930 ASSERT(pred->end()->FirstSuccessor() == block);
931 } else {
932 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
933 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
934 last_environment = last_environment->Copy();
935 }
936 }
937 block->UpdateEnvironment(last_environment);
938 ASSERT(pred->argument_count() >= 0);
939 argument_count_ = pred->argument_count();
940 } else {
941 // We are at a state join => process phis.
942 HBasicBlock* pred = block->predecessors()->at(0);
943 // No need to copy the environment, it cannot be used later.
944 HEnvironment* last_environment = pred->last_environment();
945 for (int i = 0; i < block->phis()->length(); ++i) {
946 HPhi* phi = block->phis()->at(i);
947 last_environment->SetValueAt(phi->merged_index(), phi);
948 }
949 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
950 last_environment->SetValueAt(block->deleted_phis()->at(i),
951 graph_->GetConstantUndefined());
952 }
953 block->UpdateEnvironment(last_environment);
954 // Pick up the outgoing argument count of one of the predecessors.
955 argument_count_ = pred->argument_count();
956 }
957 HInstruction* current = block->first();
958 int start = chunk_->instructions()->length();
959 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100960 // Code for constants in registers is generated lazily.
961 if (!current->EmitAtUses()) {
962 VisitInstruction(current);
963 }
964 current = current->next();
965 }
966 int end = chunk_->instructions()->length() - 1;
967 if (end >= start) {
968 block->set_first_instruction_index(start);
969 block->set_last_instruction_index(end);
970 }
971 block->set_argument_count(argument_count_);
972 next_block_ = NULL;
973 current_block_ = NULL;
974}
975
976
977void LChunkBuilder::VisitInstruction(HInstruction* current) {
978 HInstruction* old_current = current_instruction_;
979 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100980 if (current->has_position()) position_ = current->position();
981 LInstruction* instr = current->CompileToLithium(this);
982
983 if (instr != NULL) {
984 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
985 instr = AssignPointerMap(instr);
986 }
987 if (FLAG_stress_environments && !instr->HasEnvironment()) {
988 instr = AssignEnvironment(instr);
989 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000990 instr->set_hydrogen_value(current);
Steve Block1e0659c2011-05-24 12:43:12 +0100991 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100992 }
993 current_instruction_ = old_current;
994}
995
996
Ben Murdoch589d6972011-11-30 16:04:58 +0000997LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100998 if (hydrogen_env == NULL) return NULL;
999
Ben Murdoch589d6972011-11-30 16:04:58 +00001000 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001001 int ast_id = hydrogen_env->ast_id();
1002 ASSERT(ast_id != AstNode::kNoNumber);
Steve Block9fac8402011-05-12 15:51:54 +01001003 int value_count = hydrogen_env->length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001004 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1005 ast_id,
1006 hydrogen_env->parameter_count(),
1007 argument_count_,
1008 value_count,
1009 outer);
Ben Murdoch589d6972011-11-30 16:04:58 +00001010 int argument_index = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001011 for (int i = 0; i < value_count; ++i) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001012 if (hydrogen_env->is_special_index(i)) continue;
1013
Ben Murdochb0fe1622011-05-05 13:52:32 +01001014 HValue* value = hydrogen_env->values()->at(i);
1015 LOperand* op = NULL;
1016 if (value->IsArgumentsObject()) {
1017 op = NULL;
1018 } else if (value->IsPushArgument()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001019 op = new LArgument(argument_index++);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001020 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001021 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001022 }
1023 result->AddValue(op, value->representation());
1024 }
1025
1026 return result;
1027}
1028
1029
1030LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001031 return new LGoto(instr->FirstSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001032}
1033
1034
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001035LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001036 HValue* v = instr->value();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001037 if (v->EmitAtUses()) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001038 HBasicBlock* successor = HConstant::cast(v)->ToBoolean()
1039 ? instr->FirstSuccessor()
1040 : instr->SecondSuccessor();
1041 return new LGoto(successor->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001042 }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001043 return AssignEnvironment(new LBranch(UseRegister(v)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001044}
1045
1046
Ben Murdoch257744e2011-11-30 15:57:28 +00001047
Steve Block1e0659c2011-05-24 12:43:12 +01001048LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001049 ASSERT(instr->value()->representation().IsTagged());
1050 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block9fac8402011-05-12 15:51:54 +01001051 LOperand* temp = TempRegister();
1052 return new LCmpMapAndBranch(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001053}
1054
1055
1056LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001057 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001058}
1059
1060
1061LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1062 return DefineAsRegister(new LArgumentsElements);
1063}
1064
1065
1066LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001067 LInstanceOf* result =
Steve Block9fac8402011-05-12 15:51:54 +01001068 new LInstanceOf(UseFixed(instr->left(), r0),
1069 UseFixed(instr->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001070 return MarkAsCall(DefineFixed(result, r0), instr);
1071}
1072
1073
Ben Murdoch086aeea2011-05-13 15:57:08 +01001074LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1075 HInstanceOfKnownGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001076 LInstanceOfKnownGlobal* result =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001077 new LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), FixedTemp(r4));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001078 return MarkAsCall(DefineFixed(result, r0), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001079}
1080
1081
Ben Murdochb0fe1622011-05-05 13:52:32 +01001082LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1083 LOperand* function = UseFixed(instr->function(), r1);
1084 LOperand* receiver = UseFixed(instr->receiver(), r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001085 LOperand* length = UseFixed(instr->length(), r2);
1086 LOperand* elements = UseFixed(instr->elements(), r3);
1087 LApplyArguments* result = new LApplyArguments(function,
1088 receiver,
1089 length,
1090 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001091 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1092}
1093
1094
1095LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1096 ++argument_count_;
1097 LOperand* argument = Use(instr->argument());
1098 return new LPushArgument(argument);
1099}
1100
1101
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001102LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
1103 return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction);
1104}
1105
1106
Steve Block1e0659c2011-05-24 12:43:12 +01001107LInstruction* LChunkBuilder::DoContext(HContext* instr) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001108 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
Steve Block1e0659c2011-05-24 12:43:12 +01001109}
1110
1111
1112LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1113 LOperand* context = UseRegisterAtStart(instr->value());
1114 return DefineAsRegister(new LOuterContext(context));
1115}
1116
1117
Ben Murdochb0fe1622011-05-05 13:52:32 +01001118LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001119 LOperand* context = UseRegisterAtStart(instr->value());
1120 return DefineAsRegister(new LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001121}
1122
1123
1124LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001125 LOperand* global_object = UseRegisterAtStart(instr->value());
1126 return DefineAsRegister(new LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001127}
1128
1129
1130LInstruction* LChunkBuilder::DoCallConstantFunction(
1131 HCallConstantFunction* instr) {
1132 argument_count_ -= instr->argument_count();
1133 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
1134}
1135
1136
Ben Murdoch257744e2011-11-30 15:57:28 +00001137LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1138 LOperand* function = UseFixed(instr->function(), r1);
1139 argument_count_ -= instr->argument_count();
1140 LInvokeFunction* result = new LInvokeFunction(function);
1141 return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1142}
1143
1144
Ben Murdochb0fe1622011-05-05 13:52:32 +01001145LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1146 BuiltinFunctionId op = instr->op();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001147 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1148 LOperand* input = UseFixedDouble(instr->value(), d2);
1149 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
1150 return MarkAsCall(DefineFixedDouble(result, d2), instr);
1151 } else {
1152 LOperand* input = UseRegisterAtStart(instr->value());
1153 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1154 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1155 switch (op) {
1156 case kMathAbs:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001157 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001158 case kMathFloor:
1159 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1160 case kMathSqrt:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001161 return DefineAsRegister(result);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001162 case kMathRound:
1163 return AssignEnvironment(DefineAsRegister(result));
1164 case kMathPowHalf:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001165 return DefineAsRegister(result);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001166 default:
1167 UNREACHABLE();
1168 return NULL;
1169 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001170 }
1171}
1172
1173
1174LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1175 ASSERT(instr->key()->representation().IsTagged());
1176 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001177 LOperand* key = UseFixed(instr->key(), r2);
1178 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001179}
1180
1181
1182LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1183 argument_count_ -= instr->argument_count();
1184 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
1185}
1186
1187
1188LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1189 argument_count_ -= instr->argument_count();
1190 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
1191}
1192
1193
1194LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1195 argument_count_ -= instr->argument_count();
1196 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
1197}
1198
1199
1200LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1201 LOperand* constructor = UseFixed(instr->constructor(), r1);
1202 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001203 LCallNew* result = new LCallNew(constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001204 return MarkAsCall(DefineFixed(result, r0), instr);
1205}
1206
1207
1208LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1209 argument_count_ -= instr->argument_count();
1210 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
1211}
1212
1213
1214LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1215 argument_count_ -= instr->argument_count();
1216 return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
1217}
1218
1219
1220LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1221 return DoShift(Token::SHR, instr);
1222}
1223
1224
1225LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1226 return DoShift(Token::SAR, instr);
1227}
1228
1229
1230LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1231 return DoShift(Token::SHL, instr);
1232}
1233
1234
1235LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1236 return DoBit(Token::BIT_AND, instr);
1237}
1238
1239
1240LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1241 ASSERT(instr->value()->representation().IsInteger32());
1242 ASSERT(instr->representation().IsInteger32());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001243 return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001244}
1245
1246
1247LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1248 return DoBit(Token::BIT_OR, instr);
1249}
1250
1251
1252LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1253 return DoBit(Token::BIT_XOR, instr);
1254}
1255
1256
1257LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1258 if (instr->representation().IsDouble()) {
1259 return DoArithmeticD(Token::DIV, instr);
1260 } else if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001261 // TODO(1042) The fixed register allocation
Ben Murdoch8b112d22011-06-08 16:22:53 +01001262 // is needed because we call TypeRecordingBinaryOpStub from
Ben Murdochb8e0da22011-05-16 14:20:40 +01001263 // the generated code, which requires registers r0
1264 // and r1 to be used. We should remove that
1265 // when we provide a native implementation.
Steve Block1e0659c2011-05-24 12:43:12 +01001266 LOperand* dividend = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001267 LOperand* divisor = UseFixed(instr->right(), r1);
1268 return AssignEnvironment(AssignPointerMap(
Steve Block1e0659c2011-05-24 12:43:12 +01001269 DefineFixed(new LDivI(dividend, divisor), r0)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001270 } else {
1271 return DoArithmeticT(Token::DIV, instr);
1272 }
1273}
1274
1275
1276LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1277 if (instr->representation().IsInteger32()) {
1278 ASSERT(instr->left()->representation().IsInteger32());
1279 ASSERT(instr->right()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01001280
1281 LModI* mod;
1282 if (instr->HasPowerOf2Divisor()) {
1283 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1284 LOperand* value = UseRegisterAtStart(instr->left());
1285 mod = new LModI(value, UseOrConstant(instr->right()));
1286 } else {
1287 LOperand* dividend = UseRegister(instr->left());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001288 LOperand* divisor = UseRegister(instr->right());
Steve Block44f0eee2011-05-26 01:26:41 +01001289 mod = new LModI(dividend,
1290 divisor,
1291 TempRegister(),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001292 FixedTemp(d10),
1293 FixedTemp(d11));
Steve Block44f0eee2011-05-26 01:26:41 +01001294 }
1295
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001296 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1297 instr->CheckFlag(HValue::kCanBeDivByZero)) {
1298 return AssignEnvironment(DefineAsRegister(mod));
1299 } else {
1300 return DefineAsRegister(mod);
1301 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001302 } else if (instr->representation().IsTagged()) {
1303 return DoArithmeticT(Token::MOD, instr);
1304 } else {
1305 ASSERT(instr->representation().IsDouble());
1306 // We call a C function for double modulo. It can't trigger a GC.
1307 // We need to use fixed result register for the call.
1308 // TODO(fschneider): Allow any register as input registers.
1309 LOperand* left = UseFixedDouble(instr->left(), d1);
1310 LOperand* right = UseFixedDouble(instr->right(), d2);
1311 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
1312 return MarkAsCall(DefineFixedDouble(result, d1), instr);
1313 }
1314}
1315
1316
1317LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1318 if (instr->representation().IsInteger32()) {
1319 ASSERT(instr->left()->representation().IsInteger32());
1320 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001321 LOperand* left;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001322 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1323 LOperand* temp = NULL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001324 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1325 (instr->CheckFlag(HValue::kCanOverflow) ||
1326 !right->IsConstantOperand())) {
1327 left = UseRegister(instr->LeastConstantOperand());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001328 temp = TempRegister();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001329 } else {
1330 left = UseRegisterAtStart(instr->LeastConstantOperand());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001331 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001332 return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp)));
1333
Ben Murdochb0fe1622011-05-05 13:52:32 +01001334 } else if (instr->representation().IsDouble()) {
1335 return DoArithmeticD(Token::MUL, instr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001336
Ben Murdochb0fe1622011-05-05 13:52:32 +01001337 } else {
1338 return DoArithmeticT(Token::MUL, instr);
1339 }
1340}
1341
1342
1343LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1344 if (instr->representation().IsInteger32()) {
1345 ASSERT(instr->left()->representation().IsInteger32());
1346 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001347 LOperand* left = UseRegisterAtStart(instr->left());
1348 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001349 LSubI* sub = new LSubI(left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001350 LInstruction* result = DefineAsRegister(sub);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001351 if (instr->CheckFlag(HValue::kCanOverflow)) {
1352 result = AssignEnvironment(result);
1353 }
1354 return result;
1355 } else if (instr->representation().IsDouble()) {
1356 return DoArithmeticD(Token::SUB, instr);
1357 } else {
1358 return DoArithmeticT(Token::SUB, instr);
1359 }
1360}
1361
1362
1363LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1364 if (instr->representation().IsInteger32()) {
1365 ASSERT(instr->left()->representation().IsInteger32());
1366 ASSERT(instr->right()->representation().IsInteger32());
1367 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1368 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1369 LAddI* add = new LAddI(left, right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001370 LInstruction* result = DefineAsRegister(add);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001371 if (instr->CheckFlag(HValue::kCanOverflow)) {
1372 result = AssignEnvironment(result);
1373 }
1374 return result;
1375 } else if (instr->representation().IsDouble()) {
1376 return DoArithmeticD(Token::ADD, instr);
1377 } else {
1378 ASSERT(instr->representation().IsTagged());
1379 return DoArithmeticT(Token::ADD, instr);
1380 }
1381}
1382
1383
1384LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001385 ASSERT(instr->representation().IsDouble());
1386 // We call a C function for double power. It can't trigger a GC.
1387 // We need to use fixed result register for the call.
1388 Representation exponent_type = instr->right()->representation();
1389 ASSERT(instr->left()->representation().IsDouble());
1390 LOperand* left = UseFixedDouble(instr->left(), d1);
1391 LOperand* right = exponent_type.IsDouble() ?
1392 UseFixedDouble(instr->right(), d2) :
1393 UseFixed(instr->right(), r0);
1394 LPower* result = new LPower(left, right);
1395 return MarkAsCall(DefineFixedDouble(result, d3),
1396 instr,
1397 CAN_DEOPTIMIZE_EAGERLY);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001398}
1399
1400
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001401LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001402 Token::Value op = instr->token();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001403 ASSERT(instr->left()->representation().IsTagged());
1404 ASSERT(instr->right()->representation().IsTagged());
1405 bool reversed = (op == Token::GT || op == Token::LTE);
1406 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1407 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
1408 LCmpT* result = new LCmpT(left, right);
1409 return MarkAsCall(DefineFixed(result, r0), instr);
1410}
1411
1412
1413LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1414 HCompareIDAndBranch* instr) {
1415 Representation r = instr->GetInputRepresentation();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001416 if (r.IsInteger32()) {
1417 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001418 ASSERT(instr->right()->representation().IsInteger32());
1419 LOperand* left = UseRegisterAtStart(instr->left());
Steve Block1e0659c2011-05-24 12:43:12 +01001420 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001421 return new LCmpIDAndBranch(left, right);
1422 } else {
1423 ASSERT(r.IsDouble());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001424 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001425 ASSERT(instr->right()->representation().IsDouble());
1426 LOperand* left = UseRegisterAtStart(instr->left());
1427 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001428 return new LCmpIDAndBranch(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001429 }
1430}
1431
1432
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001433LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1434 HCompareObjectEqAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001435 LOperand* left = UseRegisterAtStart(instr->left());
1436 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001437 return new LCmpObjectEqAndBranch(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001438}
1439
1440
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001441LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1442 HCompareConstantEqAndBranch* instr) {
1443 return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value()));
Ben Murdoch257744e2011-11-30 15:57:28 +00001444}
1445
1446
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001447LInstruction* LChunkBuilder::DoIsNullAndBranch(HIsNullAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001448 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001449 return new LIsNullAndBranch(UseRegisterAtStart(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001450}
1451
1452
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001453LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001454 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001455 LOperand* temp = TempRegister();
1456 return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001457}
1458
1459
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001460LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001461 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001462 return new LIsSmiAndBranch(Use(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001463}
1464
1465
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001466LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1467 HIsUndetectableAndBranch* instr) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001468 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001469 return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()),
1470 TempRegister());
Ben Murdoch257744e2011-11-30 15:57:28 +00001471}
1472
1473
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001474LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1475 HHasInstanceTypeAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001476 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001477 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001478}
1479
1480
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001481LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1482 HGetCachedArrayIndex* instr) {
1483 ASSERT(instr->value()->representation().IsTagged());
1484 LOperand* value = UseRegisterAtStart(instr->value());
1485
1486 return DefineAsRegister(new LGetCachedArrayIndex(value));
1487}
1488
1489
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001490LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1491 HHasCachedArrayIndexAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001492 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001493 return new LHasCachedArrayIndexAndBranch(
1494 UseRegisterAtStart(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001495}
1496
1497
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001498LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1499 HClassOfTestAndBranch* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001500 ASSERT(instr->value()->representation().IsTagged());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001501 return new LClassOfTestAndBranch(UseTempRegister(instr->value()),
1502 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001503}
1504
1505
Steve Block9fac8402011-05-12 15:51:54 +01001506LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1507 LOperand* array = UseRegisterAtStart(instr->value());
1508 return DefineAsRegister(new LJSArrayLength(array));
1509}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001510
Ben Murdochb0fe1622011-05-05 13:52:32 +01001511
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001512LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1513 HFixedArrayBaseLength* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001514 LOperand* array = UseRegisterAtStart(instr->value());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001515 return DefineAsRegister(new LFixedArrayBaseLength(array));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001516}
1517
1518
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001519LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1520 LOperand* object = UseRegisterAtStart(instr->value());
1521 return DefineAsRegister(new LElementsKind(object));
1522}
1523
1524
Ben Murdochb0fe1622011-05-05 13:52:32 +01001525LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1526 LOperand* object = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001527 LValueOf* result = new LValueOf(object, TempRegister());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001528 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001529}
1530
1531
1532LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1533 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001534 UseRegister(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001535}
1536
1537
Steve Block1e0659c2011-05-24 12:43:12 +01001538LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1539 // The control instruction marking the end of a block that completed
1540 // abruptly (e.g., threw an exception). There is nothing specific to do.
1541 return NULL;
1542}
1543
1544
Ben Murdochb0fe1622011-05-05 13:52:32 +01001545LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1546 LOperand* value = UseFixed(instr->value(), r0);
1547 return MarkAsCall(new LThrow(value), instr);
1548}
1549
1550
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001551LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1552 return NULL;
1553}
1554
1555
Ben Murdoch257744e2011-11-30 15:57:28 +00001556LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1557 // All HForceRepresentation instructions should be eliminated in the
1558 // representation change phase of Hydrogen.
1559 UNREACHABLE();
1560 return NULL;
1561}
1562
1563
Ben Murdochb0fe1622011-05-05 13:52:32 +01001564LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1565 Representation from = instr->from();
1566 Representation to = instr->to();
1567 if (from.IsTagged()) {
1568 if (to.IsDouble()) {
1569 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001570 LNumberUntagD* res = new LNumberUntagD(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001571 return AssignEnvironment(DefineAsRegister(res));
1572 } else {
1573 ASSERT(to.IsInteger32());
1574 LOperand* value = UseRegister(instr->value());
1575 bool needs_check = !instr->value()->type().IsSmi();
1576 LInstruction* res = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001577 if (!needs_check) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001578 res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
Steve Block44f0eee2011-05-26 01:26:41 +01001579 } else {
1580 LOperand* temp1 = TempRegister();
1581 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1582 : NULL;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001583 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
Steve Block44f0eee2011-05-26 01:26:41 +01001584 : NULL;
1585 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001586 res = AssignEnvironment(res);
1587 }
1588 return res;
1589 }
1590 } else if (from.IsDouble()) {
1591 if (to.IsTagged()) {
1592 LOperand* value = UseRegister(instr->value());
1593 LOperand* temp1 = TempRegister();
1594 LOperand* temp2 = TempRegister();
1595
1596 // Make sure that the temp and result_temp registers are
1597 // different.
1598 LUnallocated* result_temp = TempRegister();
Steve Block1e0659c2011-05-24 12:43:12 +01001599 LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001600 Define(result, result_temp);
1601 return AssignPointerMap(result);
1602 } else {
1603 ASSERT(to.IsInteger32());
1604 LOperand* value = UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001605 LDoubleToI* res =
1606 new LDoubleToI(value,
1607 TempRegister(),
1608 instr->CanTruncateToInt32() ? TempRegister() : NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001609 return AssignEnvironment(DefineAsRegister(res));
1610 }
1611 } else if (from.IsInteger32()) {
1612 if (to.IsTagged()) {
1613 HValue* val = instr->value();
1614 LOperand* value = UseRegister(val);
1615 if (val->HasRange() && val->range()->IsInSmiRange()) {
1616 return DefineSameAsFirst(new LSmiTag(value));
1617 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001618 LNumberTagI* result = new LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001619 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1620 }
1621 } else {
1622 ASSERT(to.IsDouble());
1623 LOperand* value = Use(instr->value());
1624 return DefineAsRegister(new LInteger32ToDouble(value));
1625 }
1626 }
1627 UNREACHABLE();
1628 return NULL;
1629}
1630
1631
1632LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1633 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001634 return AssignEnvironment(new LCheckNonSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001635}
1636
1637
1638LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1639 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001640 LInstruction* result = new LCheckInstanceType(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001641 return AssignEnvironment(result);
1642}
1643
1644
1645LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001646 LOperand* temp1 = TempRegister();
1647 LOperand* temp2 = TempRegister();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001648 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001649 return AssignEnvironment(result);
1650}
1651
1652
1653LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1654 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001655 return AssignEnvironment(new LCheckSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001656}
1657
1658
1659LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1660 LOperand* value = UseRegisterAtStart(instr->value());
1661 return AssignEnvironment(new LCheckFunction(value));
1662}
1663
1664
1665LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1666 LOperand* value = UseRegisterAtStart(instr->value());
1667 LInstruction* result = new LCheckMap(value);
1668 return AssignEnvironment(result);
1669}
1670
1671
Ben Murdoch257744e2011-11-30 15:57:28 +00001672LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1673 HValue* value = instr->value();
1674 Representation input_rep = value->representation();
1675 LOperand* reg = UseRegister(value);
1676 if (input_rep.IsDouble()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001677 return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11)));
Ben Murdoch257744e2011-11-30 15:57:28 +00001678 } else if (input_rep.IsInteger32()) {
1679 return DefineAsRegister(new LClampIToUint8(reg));
1680 } else {
1681 ASSERT(input_rep.IsTagged());
1682 // Register allocator doesn't (yet) support allocation of double
1683 // temps. Reserve d1 explicitly.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001684 LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11));
Ben Murdoch257744e2011-11-30 15:57:28 +00001685 return AssignEnvironment(DefineAsRegister(result));
1686 }
1687}
1688
1689
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001690LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) {
1691 HValue* value = instr->value();
1692 Representation input_rep = value->representation();
1693 LOperand* reg = UseRegister(value);
1694 if (input_rep.IsDouble()) {
1695 LOperand* temp1 = TempRegister();
1696 LOperand* temp2 = TempRegister();
1697 LDoubleToI* res = new LDoubleToI(reg, temp1, temp2);
1698 return AssignEnvironment(DefineAsRegister(res));
1699 } else if (input_rep.IsInteger32()) {
1700 // Canonicalization should already have removed the hydrogen instruction in
1701 // this case, since it is a noop.
1702 UNREACHABLE();
1703 return NULL;
1704 } else {
1705 ASSERT(input_rep.IsTagged());
1706 LOperand* temp1 = TempRegister();
1707 LOperand* temp2 = TempRegister();
1708 LOperand* temp3 = FixedTemp(d11);
1709 LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3);
1710 return AssignEnvironment(DefineSameAsFirst(res));
1711 }
1712}
1713
1714
Ben Murdochb0fe1622011-05-05 13:52:32 +01001715LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1716 return new LReturn(UseFixed(instr->value(), r0));
1717}
1718
1719
1720LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1721 Representation r = instr->representation();
1722 if (r.IsInteger32()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001723 return DefineAsRegister(new LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001724 } else if (r.IsDouble()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001725 return DefineAsRegister(new LConstantD);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001726 } else if (r.IsTagged()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001727 return DefineAsRegister(new LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001728 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001729 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001730 return NULL;
1731 }
1732}
1733
1734
Ben Murdoch8b112d22011-06-08 16:22:53 +01001735LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1736 LLoadGlobalCell* result = new LLoadGlobalCell;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001737 return instr->check_hole_value()
1738 ? AssignEnvironment(DefineAsRegister(result))
1739 : DefineAsRegister(result);
1740}
1741
1742
Ben Murdoch8b112d22011-06-08 16:22:53 +01001743LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1744 LOperand* global_object = UseFixed(instr->global_object(), r0);
1745 LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
1746 return MarkAsCall(DefineFixed(result, r0), instr);
1747}
1748
1749
1750LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001751 if (instr->check_hole_value()) {
1752 LOperand* temp = TempRegister();
1753 LOperand* value = UseRegister(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001754 return AssignEnvironment(new LStoreGlobalCell(value, temp));
Steve Block1e0659c2011-05-24 12:43:12 +01001755 } else {
1756 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001757 return new LStoreGlobalCell(value, NULL);
Steve Block1e0659c2011-05-24 12:43:12 +01001758 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001759}
1760
1761
Ben Murdoch8b112d22011-06-08 16:22:53 +01001762LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1763 LOperand* global_object = UseFixed(instr->global_object(), r1);
1764 LOperand* value = UseFixed(instr->value(), r0);
1765 LStoreGlobalGeneric* result =
1766 new LStoreGlobalGeneric(global_object, value);
1767 return MarkAsCall(result, instr);
1768}
1769
1770
Ben Murdochb8e0da22011-05-16 14:20:40 +01001771LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001772 LOperand* context = UseRegisterAtStart(instr->value());
1773 return DefineAsRegister(new LLoadContextSlot(context));
1774}
1775
1776
1777LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001778 LOperand* context;
Steve Block1e0659c2011-05-24 12:43:12 +01001779 LOperand* value;
1780 if (instr->NeedsWriteBarrier()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001781 context = UseTempRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001782 value = UseTempRegister(instr->value());
1783 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001784 context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001785 value = UseRegister(instr->value());
1786 }
1787 return new LStoreContextSlot(context, value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001788}
1789
1790
Ben Murdochb0fe1622011-05-05 13:52:32 +01001791LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1792 return DefineAsRegister(
1793 new LLoadNamedField(UseRegisterAtStart(instr->object())));
1794}
1795
1796
Steve Block44f0eee2011-05-26 01:26:41 +01001797LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1798 HLoadNamedFieldPolymorphic* instr) {
1799 ASSERT(instr->representation().IsTagged());
1800 if (instr->need_generic()) {
1801 LOperand* obj = UseFixed(instr->object(), r0);
1802 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1803 return MarkAsCall(DefineFixed(result, r0), instr);
1804 } else {
1805 LOperand* obj = UseRegisterAtStart(instr->object());
1806 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1807 return AssignEnvironment(DefineAsRegister(result));
1808 }
1809}
1810
1811
Ben Murdochb0fe1622011-05-05 13:52:32 +01001812LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1813 LOperand* object = UseFixed(instr->object(), r0);
1814 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
1815 return MarkAsCall(result, instr);
1816}
1817
1818
Steve Block9fac8402011-05-12 15:51:54 +01001819LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1820 HLoadFunctionPrototype* instr) {
1821 return AssignEnvironment(DefineAsRegister(
1822 new LLoadFunctionPrototype(UseRegister(instr->function()))));
1823}
1824
1825
Ben Murdochb0fe1622011-05-05 13:52:32 +01001826LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1827 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001828 return DefineAsRegister(new LLoadElements(input));
1829}
1830
1831
Steve Block44f0eee2011-05-26 01:26:41 +01001832LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1833 HLoadExternalArrayPointer* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001834 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001835 return DefineAsRegister(new LLoadExternalArrayPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001836}
1837
1838
1839LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1840 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001841 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001842 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001843 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001844 LOperand* key = UseRegisterAtStart(instr->key());
Steve Block1e0659c2011-05-24 12:43:12 +01001845 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001846 return AssignEnvironment(DefineAsRegister(result));
1847}
1848
1849
1850LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
1851 HLoadKeyedFastDoubleElement* instr) {
1852 ASSERT(instr->representation().IsDouble());
1853 ASSERT(instr->key()->representation().IsInteger32());
1854 LOperand* elements = UseTempRegister(instr->elements());
1855 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1856 LLoadKeyedFastDoubleElement* result =
1857 new LLoadKeyedFastDoubleElement(elements, key);
1858 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001859}
1860
1861
Steve Block44f0eee2011-05-26 01:26:41 +01001862LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1863 HLoadKeyedSpecializedArrayElement* instr) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001864 ElementsKind elements_kind = instr->elements_kind();
Ben Murdoch8b112d22011-06-08 16:22:53 +01001865 Representation representation(instr->representation());
Ben Murdoch257744e2011-11-30 15:57:28 +00001866 ASSERT(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001867 (representation.IsInteger32() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00001868 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1869 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001870 (representation.IsDouble() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00001871 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1872 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
Steve Block1e0659c2011-05-24 12:43:12 +01001873 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001874 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch257744e2011-11-30 15:57:28 +00001875 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001876 LLoadKeyedSpecializedArrayElement* result =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001877 new LLoadKeyedSpecializedArrayElement(external_pointer, key);
1878 LInstruction* load_instr = DefineAsRegister(result);
1879 // An unsigned int array load might overflow and cause a deopt, make sure it
1880 // has an environment.
Ben Murdoch589d6972011-11-30 16:04:58 +00001881 return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) ?
Ben Murdoch8b112d22011-06-08 16:22:53 +01001882 AssignEnvironment(load_instr) : load_instr;
Steve Block1e0659c2011-05-24 12:43:12 +01001883}
1884
1885
Ben Murdochb0fe1622011-05-05 13:52:32 +01001886LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1887 LOperand* object = UseFixed(instr->object(), r1);
1888 LOperand* key = UseFixed(instr->key(), r0);
1889
1890 LInstruction* result =
1891 DefineFixed(new LLoadKeyedGeneric(object, key), r0);
1892 return MarkAsCall(result, instr);
1893}
1894
1895
1896LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1897 HStoreKeyedFastElement* instr) {
1898 bool needs_write_barrier = instr->NeedsWriteBarrier();
1899 ASSERT(instr->value()->representation().IsTagged());
1900 ASSERT(instr->object()->representation().IsTagged());
1901 ASSERT(instr->key()->representation().IsInteger32());
1902
1903 LOperand* obj = UseTempRegister(instr->object());
1904 LOperand* val = needs_write_barrier
1905 ? UseTempRegister(instr->value())
1906 : UseRegisterAtStart(instr->value());
1907 LOperand* key = needs_write_barrier
1908 ? UseTempRegister(instr->key())
1909 : UseRegisterOrConstantAtStart(instr->key());
1910
1911 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1912}
1913
1914
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001915LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
1916 HStoreKeyedFastDoubleElement* instr) {
1917 ASSERT(instr->value()->representation().IsDouble());
1918 ASSERT(instr->elements()->representation().IsTagged());
1919 ASSERT(instr->key()->representation().IsInteger32());
1920
1921 LOperand* elements = UseRegisterAtStart(instr->elements());
1922 LOperand* val = UseTempRegister(instr->value());
1923 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1924
1925 return new LStoreKeyedFastDoubleElement(elements, key, val);
1926}
1927
1928
Steve Block44f0eee2011-05-26 01:26:41 +01001929LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1930 HStoreKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001931 Representation representation(instr->value()->representation());
Ben Murdoch589d6972011-11-30 16:04:58 +00001932 ElementsKind elements_kind = instr->elements_kind();
Ben Murdoch257744e2011-11-30 15:57:28 +00001933 ASSERT(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001934 (representation.IsInteger32() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00001935 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1936 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001937 (representation.IsDouble() &&
Ben Murdoch589d6972011-11-30 16:04:58 +00001938 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1939 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
Steve Block44f0eee2011-05-26 01:26:41 +01001940 ASSERT(instr->external_pointer()->representation().IsExternal());
1941 ASSERT(instr->key()->representation().IsInteger32());
1942
1943 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001944 bool val_is_temp_register =
Ben Murdoch589d6972011-11-30 16:04:58 +00001945 elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
1946 elements_kind == EXTERNAL_FLOAT_ELEMENTS;
Ben Murdoch8b112d22011-06-08 16:22:53 +01001947 LOperand* val = val_is_temp_register
1948 ? UseTempRegister(instr->value())
1949 : UseRegister(instr->value());
Ben Murdoch257744e2011-11-30 15:57:28 +00001950 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001951
1952 return new LStoreKeyedSpecializedArrayElement(external_pointer,
1953 key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01001954 val);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001955}
1956
1957
Ben Murdochb0fe1622011-05-05 13:52:32 +01001958LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1959 LOperand* obj = UseFixed(instr->object(), r2);
1960 LOperand* key = UseFixed(instr->key(), r1);
1961 LOperand* val = UseFixed(instr->value(), r0);
1962
1963 ASSERT(instr->object()->representation().IsTagged());
1964 ASSERT(instr->key()->representation().IsTagged());
1965 ASSERT(instr->value()->representation().IsTagged());
1966
1967 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1968}
1969
1970
1971LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001972 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001973
1974 LOperand* obj = needs_write_barrier
1975 ? UseTempRegister(instr->object())
1976 : UseRegisterAtStart(instr->object());
1977
1978 LOperand* val = needs_write_barrier
1979 ? UseTempRegister(instr->value())
1980 : UseRegister(instr->value());
1981
Ben Murdochb8e0da22011-05-16 14:20:40 +01001982 return new LStoreNamedField(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001983}
1984
1985
1986LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1987 LOperand* obj = UseFixed(instr->object(), r1);
1988 LOperand* val = UseFixed(instr->value(), r0);
1989
Ben Murdochb8e0da22011-05-16 14:20:40 +01001990 LInstruction* result = new LStoreNamedGeneric(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001991 return MarkAsCall(result, instr);
1992}
1993
1994
Ben Murdoch257744e2011-11-30 15:57:28 +00001995LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1996 LOperand* left = UseRegisterAtStart(instr->left());
1997 LOperand* right = UseRegisterAtStart(instr->right());
1998 return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr);
1999}
2000
2001
Steve Block1e0659c2011-05-24 12:43:12 +01002002LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002003 LOperand* string = UseTempRegister(instr->string());
2004 LOperand* index = UseTempRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01002005 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
2006 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2007}
2008
2009
Steve Block44f0eee2011-05-26 01:26:41 +01002010LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2011 LOperand* char_code = UseRegister(instr->value());
2012 LStringCharFromCode* result = new LStringCharFromCode(char_code);
2013 return AssignPointerMap(DefineAsRegister(result));
2014}
2015
2016
Steve Block1e0659c2011-05-24 12:43:12 +01002017LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2018 LOperand* string = UseRegisterAtStart(instr->value());
2019 return DefineAsRegister(new LStringLength(string));
2020}
2021
2022
Ben Murdochb0fe1622011-05-05 13:52:32 +01002023LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2024 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
2025}
2026
2027
2028LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2029 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
2030}
2031
2032
2033LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2034 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
2035}
2036
2037
2038LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2039 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
2040}
2041
2042
2043LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002044 LOperand* object = UseFixed(instr->object(), r0);
2045 LOperand* key = UseFixed(instr->key(), r1);
2046 LDeleteProperty* result = new LDeleteProperty(object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002047 return MarkAsCall(DefineFixed(result, r0), instr);
2048}
2049
2050
2051LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2052 allocator_->MarkAsOsrEntry();
2053 current_block_->last_environment()->set_ast_id(instr->ast_id());
2054 return AssignEnvironment(new LOsrEntry);
2055}
2056
2057
2058LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2059 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2060 return DefineAsSpilled(new LParameter, spill_index);
2061}
2062
2063
2064LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2065 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +01002066 if (spill_index > LUnallocated::kMaxFixedIndex) {
2067 Abort("Too many spill slots needed for OSR");
2068 spill_index = 0;
2069 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002070 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
2071}
2072
2073
2074LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2075 argument_count_ -= instr->argument_count();
2076 return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
2077}
2078
2079
2080LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002081 // There are no real uses of the arguments object.
2082 // arguments.length and element access are supported directly on
2083 // stack arguments, and any real arguments object use causes a bailout.
2084 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002085 return NULL;
2086}
2087
2088
2089LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2090 LOperand* arguments = UseRegister(instr->arguments());
2091 LOperand* length = UseTempRegister(instr->length());
Ben Murdoch086aeea2011-05-13 15:57:08 +01002092 LOperand* index = UseRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01002093 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2094 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002095}
2096
2097
Steve Block44f0eee2011-05-26 01:26:41 +01002098LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2099 LOperand* object = UseFixed(instr->value(), r0);
2100 LToFastProperties* result = new LToFastProperties(object);
2101 return MarkAsCall(DefineFixed(result, r0), instr);
2102}
2103
2104
Ben Murdochb0fe1622011-05-05 13:52:32 +01002105LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002106 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002107 return MarkAsCall(DefineFixed(result, r0), instr);
2108}
2109
2110
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002111LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2112 return new LTypeofIsAndBranch(UseTempRegister(instr->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002113}
2114
Steve Block1e0659c2011-05-24 12:43:12 +01002115
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002116LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2117 HIsConstructCallAndBranch* instr) {
2118 return new LIsConstructCallAndBranch(TempRegister());
Steve Block1e0659c2011-05-24 12:43:12 +01002119}
2120
2121
Ben Murdochb0fe1622011-05-05 13:52:32 +01002122LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2123 HEnvironment* env = current_block_->last_environment();
2124 ASSERT(env != NULL);
2125
2126 env->set_ast_id(instr->ast_id());
2127
2128 env->Drop(instr->pop_count());
2129 for (int i = 0; i < instr->values()->length(); ++i) {
2130 HValue* value = instr->values()->at(i);
2131 if (instr->HasAssignedIndexAt(i)) {
2132 env->Bind(instr->GetAssignedIndexAt(i), value);
2133 } else {
2134 env->Push(value);
2135 }
2136 }
2137
Ben Murdochb0fe1622011-05-05 13:52:32 +01002138 // If there is an instruction pending deoptimization environment create a
2139 // lazy bailout instruction to capture the environment.
2140 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2141 LInstruction* result = new LLazyBailout;
2142 result = AssignEnvironment(result);
Steve Block1e0659c2011-05-24 12:43:12 +01002143 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002144 set_deoptimization_environment(result->environment());
2145 ClearInstructionPendingDeoptimizationEnvironment();
2146 return result;
2147 }
2148
2149 return NULL;
2150}
2151
2152
2153LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002154 if (instr->is_function_entry()) {
2155 return MarkAsCall(new LStackCheck, instr);
2156 } else {
2157 ASSERT(instr->is_backwards_branch());
2158 return AssignEnvironment(AssignPointerMap(new LStackCheck));
2159 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002160}
2161
2162
2163LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2164 HEnvironment* outer = current_block_->last_environment();
2165 HConstant* undefined = graph()->GetConstantUndefined();
2166 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2167 instr->function(),
Ben Murdoch257744e2011-11-30 15:57:28 +00002168 undefined,
2169 instr->call_kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002170 current_block_->UpdateEnvironment(inner);
2171 chunk_->AddInlinedClosure(instr->closure());
2172 return NULL;
2173}
2174
2175
2176LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2177 HEnvironment* outer = current_block_->last_environment()->outer();
2178 current_block_->UpdateEnvironment(outer);
2179 return NULL;
2180}
2181
2182
Ben Murdoch257744e2011-11-30 15:57:28 +00002183LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2184 LOperand* key = UseRegisterAtStart(instr->key());
2185 LOperand* object = UseRegisterAtStart(instr->object());
2186 LIn* result = new LIn(key, object);
2187 return MarkAsCall(DefineFixed(result, r0), instr);
2188}
2189
2190
Ben Murdochb0fe1622011-05-05 13:52:32 +01002191} } // namespace v8::internal