blob: e32cd0c8fab9a7d3e37f4cb2943e3e7397d14be1 [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());
71 for (UseIterator it(this); it.HasNext(); it.Advance()) {
Ben Murdoch257744e2011-11-30 15:57:28 +000072 LUnallocated* operand = LUnallocated::cast(it.Next());
73 ASSERT(operand->HasFixedPolicy() ||
74 operand->IsUsedAtStart());
Steve Block1e0659c2011-05-24 12:43:12 +010075 }
76 for (TempIterator it(this); it.HasNext(); it.Advance()) {
Ben Murdoch257744e2011-11-30 15:57:28 +000077 LUnallocated* operand = LUnallocated::cast(it.Next());
78 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("= ");
114 inputs_.PrintOperandsTo(stream);
115}
116
117
118template<int R, int I, int T>
119void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
120 results_.PrintOperandsTo(stream);
121}
122
123
124template<typename T, int N>
125void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
126 for (int i = 0; i < N; i++) {
127 if (i > 0) stream->Add(" ");
128 elems_[i]->PrintTo(stream);
129 }
130}
131
132
133void LLabel::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134 LGap::PrintDataTo(stream);
135 LLabel* rep = replacement();
136 if (rep != NULL) {
137 stream->Add(" Dead block replaced with B%d", rep->block_id());
138 }
139}
140
141
Ben Murdochb0fe1622011-05-05 13:52:32 +0100142bool LGap::IsRedundant() const {
143 for (int i = 0; i < 4; i++) {
144 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
145 return false;
146 }
147 }
148
149 return true;
150}
151
152
Ben Murdoch257744e2011-11-30 15:57:28 +0000153void LGap::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100154 for (int i = 0; i < 4; i++) {
155 stream->Add("(");
156 if (parallel_moves_[i] != NULL) {
157 parallel_moves_[i]->PrintDataTo(stream);
158 }
159 stream->Add(") ");
160 }
161}
162
163
164const char* LArithmeticD::Mnemonic() const {
165 switch (op()) {
166 case Token::ADD: return "add-d";
167 case Token::SUB: return "sub-d";
168 case Token::MUL: return "mul-d";
169 case Token::DIV: return "div-d";
170 case Token::MOD: return "mod-d";
171 default:
172 UNREACHABLE();
173 return NULL;
174 }
175}
176
177
178const char* LArithmeticT::Mnemonic() const {
179 switch (op()) {
180 case Token::ADD: return "add-t";
181 case Token::SUB: return "sub-t";
182 case Token::MUL: return "mul-t";
183 case Token::MOD: return "mod-t";
184 case Token::DIV: return "div-t";
Steve Block1e0659c2011-05-24 12:43:12 +0100185 case Token::BIT_AND: return "bit-and-t";
186 case Token::BIT_OR: return "bit-or-t";
187 case Token::BIT_XOR: return "bit-xor-t";
188 case Token::SHL: return "shl-t";
189 case Token::SAR: return "sar-t";
190 case Token::SHR: return "shr-t";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100191 default:
192 UNREACHABLE();
193 return NULL;
194 }
195}
196
197
Steve Block1e0659c2011-05-24 12:43:12 +0100198void LGoto::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100199 stream->Add("B%d", block_id());
200}
201
202
Steve Block1e0659c2011-05-24 12:43:12 +0100203void LBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100204 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
Steve Block1e0659c2011-05-24 12:43:12 +0100205 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100206}
207
208
Steve Block1e0659c2011-05-24 12:43:12 +0100209void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100210 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100211 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100212 stream->Add(" %s ", Token::String(op()));
Steve Block1e0659c2011-05-24 12:43:12 +0100213 InputAt(1)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100214 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
215}
216
217
Steve Block1e0659c2011-05-24 12:43:12 +0100218void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100219 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100220 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100221 stream->Add(is_strict() ? " === null" : " == null");
222 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
223}
224
225
Steve Block1e0659c2011-05-24 12:43:12 +0100226void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100227 stream->Add("if is_object(");
Steve Block1e0659c2011-05-24 12:43:12 +0100228 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100229 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
230}
231
232
Steve Block1e0659c2011-05-24 12:43:12 +0100233void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100234 stream->Add("if is_smi(");
Steve Block1e0659c2011-05-24 12:43:12 +0100235 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100236 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
237}
238
239
Ben Murdoch257744e2011-11-30 15:57:28 +0000240void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
241 stream->Add("if is_undetectable(");
242 InputAt(0)->PrintTo(stream);
243 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
244}
245
246
Steve Block1e0659c2011-05-24 12:43:12 +0100247void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248 stream->Add("if has_instance_type(");
Steve Block1e0659c2011-05-24 12:43:12 +0100249 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100250 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
251}
252
253
Steve Block1e0659c2011-05-24 12:43:12 +0100254void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255 stream->Add("if has_cached_array_index(");
Steve Block1e0659c2011-05-24 12:43:12 +0100256 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100257 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
258}
259
260
Steve Block1e0659c2011-05-24 12:43:12 +0100261void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100262 stream->Add("if class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100263 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100264 stream->Add(", \"%o\") then B%d else B%d",
265 *hydrogen()->class_name(),
266 true_block_id(),
267 false_block_id());
268}
269
270
Steve Block1e0659c2011-05-24 12:43:12 +0100271void LTypeofIs::PrintDataTo(StringStream* stream) {
272 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100273 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
274}
275
276
Steve Block1e0659c2011-05-24 12:43:12 +0100277void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100278 stream->Add("if typeof ");
Steve Block1e0659c2011-05-24 12:43:12 +0100279 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100280 stream->Add(" == \"%s\" then B%d else B%d",
281 *hydrogen()->type_literal()->ToCString(),
282 true_block_id(), false_block_id());
283}
284
285
Steve Block1e0659c2011-05-24 12:43:12 +0100286void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100287 stream->Add("#%d / ", arity());
288}
289
290
Steve Block1e0659c2011-05-24 12:43:12 +0100291void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100292 stream->Add("/%s ", hydrogen()->OpName());
Steve Block1e0659c2011-05-24 12:43:12 +0100293 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100294}
295
296
Ben Murdochb8e0da22011-05-16 14:20:40 +0100297void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100298 InputAt(0)->PrintTo(stream);
299 stream->Add("[%d]", slot_index());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100300}
301
302
Steve Block1e0659c2011-05-24 12:43:12 +0100303void LStoreContextSlot::PrintDataTo(StringStream* stream) {
304 InputAt(0)->PrintTo(stream);
305 stream->Add("[%d] <- ", slot_index());
306 InputAt(1)->PrintTo(stream);
307}
308
309
Ben Murdoch257744e2011-11-30 15:57:28 +0000310void LInvokeFunction::PrintDataTo(StringStream* stream) {
311 stream->Add("= ");
312 InputAt(0)->PrintTo(stream);
313 stream->Add(" #%d / ", arity());
314}
315
316
Steve Block1e0659c2011-05-24 12:43:12 +0100317void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100318 stream->Add("[r2] #%d / ", arity());
319}
320
321
Steve Block1e0659c2011-05-24 12:43:12 +0100322void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100323 SmartPointer<char> name_string = name()->ToCString();
324 stream->Add("%s #%d / ", *name_string, arity());
325}
326
327
Steve Block1e0659c2011-05-24 12:43:12 +0100328void LCallGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100329 SmartPointer<char> name_string = name()->ToCString();
330 stream->Add("%s #%d / ", *name_string, arity());
331}
332
333
Steve Block1e0659c2011-05-24 12:43:12 +0100334void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100335 stream->Add("#%d / ", arity());
336}
337
338
Steve Block1e0659c2011-05-24 12:43:12 +0100339void LCallNew::PrintDataTo(StringStream* stream) {
340 stream->Add("= ");
341 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100342 stream->Add(" #%d / ", arity());
343}
344
345
Steve Block1e0659c2011-05-24 12:43:12 +0100346void LClassOfTest::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100347 stream->Add("= class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100348 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100349 stream->Add(", \"%o\")", *hydrogen()->class_name());
350}
351
352
Steve Block1e0659c2011-05-24 12:43:12 +0100353void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100354 arguments()->PrintTo(stream);
355
356 stream->Add(" length ");
357 length()->PrintTo(stream);
358
359 stream->Add(" index ");
360 index()->PrintTo(stream);
361}
362
363
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100364void LStoreNamedField::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100365 object()->PrintTo(stream);
366 stream->Add(".");
367 stream->Add(*String::cast(*name())->ToCString());
368 stream->Add(" <- ");
369 value()->PrintTo(stream);
370}
371
372
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100373void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
374 object()->PrintTo(stream);
375 stream->Add(".");
376 stream->Add(*String::cast(*name())->ToCString());
377 stream->Add(" <- ");
378 value()->PrintTo(stream);
379}
380
381
382void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100383 object()->PrintTo(stream);
384 stream->Add("[");
385 key()->PrintTo(stream);
386 stream->Add("] <- ");
387 value()->PrintTo(stream);
388}
389
390
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100391void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
392 object()->PrintTo(stream);
393 stream->Add("[");
394 key()->PrintTo(stream);
395 stream->Add("] <- ");
396 value()->PrintTo(stream);
397}
398
399
400LChunk::LChunk(CompilationInfo* info, HGraph* graph)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100401 : spill_slot_count_(0),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100402 info_(info),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100403 graph_(graph),
404 instructions_(32),
405 pointer_maps_(8),
406 inlined_closures_(1) {
407}
408
409
Ben Murdochb0fe1622011-05-05 13:52:32 +0100410int LChunk::GetNextSpillIndex(bool is_double) {
411 // Skip a slot if for a double-width slot.
412 if (is_double) spill_slot_count_++;
413 return spill_slot_count_++;
414}
415
416
417LOperand* LChunk::GetNextSpillSlot(bool is_double) {
418 int index = GetNextSpillIndex(is_double);
419 if (is_double) {
420 return LDoubleStackSlot::Create(index);
421 } else {
422 return LStackSlot::Create(index);
423 }
424}
425
426
427void LChunk::MarkEmptyBlocks() {
428 HPhase phase("Mark empty blocks", this);
429 for (int i = 0; i < graph()->blocks()->length(); ++i) {
430 HBasicBlock* block = graph()->blocks()->at(i);
431 int first = block->first_instruction_index();
432 int last = block->last_instruction_index();
433 LInstruction* first_instr = instructions()->at(first);
434 LInstruction* last_instr = instructions()->at(last);
435
436 LLabel* label = LLabel::cast(first_instr);
437 if (last_instr->IsGoto()) {
438 LGoto* goto_instr = LGoto::cast(last_instr);
439 if (!goto_instr->include_stack_check() &&
440 label->IsRedundant() &&
441 !label->is_loop_header()) {
442 bool can_eliminate = true;
443 for (int i = first + 1; i < last && can_eliminate; ++i) {
444 LInstruction* cur = instructions()->at(i);
445 if (cur->IsGap()) {
446 LGap* gap = LGap::cast(cur);
447 if (!gap->IsRedundant()) {
448 can_eliminate = false;
449 }
450 } else {
451 can_eliminate = false;
452 }
453 }
454
455 if (can_eliminate) {
456 label->set_replacement(GetLabel(goto_instr->block_id()));
457 }
458 }
459 }
460 }
461}
462
463
Steve Block1e0659c2011-05-24 12:43:12 +0100464void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000465 LInstructionGap* gap = new LInstructionGap(block);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100466 int index = -1;
467 if (instr->IsControl()) {
468 instructions_.Add(gap);
469 index = instructions_.length();
470 instructions_.Add(instr);
471 } else {
472 index = instructions_.length();
473 instructions_.Add(instr);
474 instructions_.Add(gap);
475 }
476 if (instr->HasPointerMap()) {
477 pointer_maps_.Add(instr->pointer_map());
478 instr->pointer_map()->set_lithium_position(index);
479 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480}
481
482
483LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
484 return LConstantOperand::Create(constant->id());
485}
486
487
488int LChunk::GetParameterStackSlot(int index) const {
489 // The receiver is at index 0, the first parameter at index 1, so we
490 // shift all parameter indexes down by the number of parameters, and
491 // make sure they end up negative so they are distinguishable from
492 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100493 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100494 ASSERT(result < 0);
495 return result;
496}
497
498// A parameter relative to ebp in the arguments stub.
499int LChunk::ParameterAt(int index) {
500 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100501 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100502 kPointerSize;
503}
504
505
506LGap* LChunk::GetGapAt(int index) const {
507 return LGap::cast(instructions_[index]);
508}
509
510
511bool LChunk::IsGapAt(int index) const {
512 return instructions_[index]->IsGap();
513}
514
515
516int LChunk::NearestGapPos(int index) const {
517 while (!IsGapAt(index)) index--;
518 return index;
519}
520
521
522void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
523 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
524}
525
526
Ben Murdochb0fe1622011-05-05 13:52:32 +0100527Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
528 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
529}
530
531
532Representation LChunk::LookupLiteralRepresentation(
533 LConstantOperand* operand) const {
534 return graph_->LookupValue(operand->index())->representation();
535}
536
537
538LChunk* LChunkBuilder::Build() {
539 ASSERT(is_unused());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100540 chunk_ = new LChunk(info(), graph());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100541 HPhase phase("Building chunk", chunk_);
542 status_ = BUILDING;
543 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
544 for (int i = 0; i < blocks->length(); i++) {
545 HBasicBlock* next = NULL;
546 if (i < blocks->length() - 1) next = blocks->at(i + 1);
547 DoBasicBlock(blocks->at(i), next);
548 if (is_aborted()) return NULL;
549 }
550 status_ = DONE;
551 return chunk_;
552}
553
554
555void LChunkBuilder::Abort(const char* format, ...) {
556 if (FLAG_trace_bailout) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100557 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
558 PrintF("Aborting LChunk building in @\"%s\": ", *name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100559 va_list arguments;
560 va_start(arguments, format);
561 OS::VPrint(format, arguments);
562 va_end(arguments);
563 PrintF("\n");
564 }
565 status_ = ABORTED;
566}
567
568
569LRegister* LChunkBuilder::ToOperand(Register reg) {
570 return LRegister::Create(Register::ToAllocationIndex(reg));
571}
572
573
574LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
575 return new LUnallocated(LUnallocated::FIXED_REGISTER,
576 Register::ToAllocationIndex(reg));
577}
578
579
580LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
581 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
582 DoubleRegister::ToAllocationIndex(reg));
583}
584
585
586LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
587 return Use(value, ToUnallocated(fixed_register));
588}
589
590
591LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
592 return Use(value, ToUnallocated(reg));
593}
594
595
596LOperand* LChunkBuilder::UseRegister(HValue* value) {
597 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
598}
599
600
601LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
602 return Use(value,
603 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
604 LUnallocated::USED_AT_START));
605}
606
607
608LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
609 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
610}
611
612
613LOperand* LChunkBuilder::Use(HValue* value) {
614 return Use(value, new LUnallocated(LUnallocated::NONE));
615}
616
617
618LOperand* LChunkBuilder::UseAtStart(HValue* value) {
619 return Use(value, new LUnallocated(LUnallocated::NONE,
620 LUnallocated::USED_AT_START));
621}
622
623
624LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
625 return value->IsConstant()
626 ? chunk_->DefineConstantOperand(HConstant::cast(value))
627 : Use(value);
628}
629
630
631LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
632 return value->IsConstant()
633 ? chunk_->DefineConstantOperand(HConstant::cast(value))
634 : UseAtStart(value);
635}
636
637
638LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
639 return value->IsConstant()
640 ? chunk_->DefineConstantOperand(HConstant::cast(value))
641 : UseRegister(value);
642}
643
644
645LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
646 return value->IsConstant()
647 ? chunk_->DefineConstantOperand(HConstant::cast(value))
648 : UseRegisterAtStart(value);
649}
650
651
Ben Murdochb8e0da22011-05-16 14:20:40 +0100652LOperand* LChunkBuilder::UseAny(HValue* value) {
653 return value->IsConstant()
654 ? chunk_->DefineConstantOperand(HConstant::cast(value))
655 : Use(value, new LUnallocated(LUnallocated::ANY));
656}
657
658
Ben Murdochb0fe1622011-05-05 13:52:32 +0100659LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
660 if (value->EmitAtUses()) {
661 HInstruction* instr = HInstruction::cast(value);
662 VisitInstruction(instr);
663 }
664 allocator_->RecordUse(value, operand);
665 return operand;
666}
667
668
Steve Block1e0659c2011-05-24 12:43:12 +0100669template<int I, int T>
670LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
671 LUnallocated* result) {
672 allocator_->RecordDefinition(current_instruction_, result);
673 instr->set_result(result);
674 return instr;
675}
676
677
678template<int I, int T>
679LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100680 return Define(instr, new LUnallocated(LUnallocated::NONE));
681}
682
683
Steve Block1e0659c2011-05-24 12:43:12 +0100684template<int I, int T>
685LInstruction* LChunkBuilder::DefineAsRegister(
686 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100687 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
688}
689
690
Steve Block1e0659c2011-05-24 12:43:12 +0100691template<int I, int T>
692LInstruction* LChunkBuilder::DefineAsSpilled(
693 LTemplateInstruction<1, I, T>* instr, int index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100694 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
695}
696
697
Steve Block1e0659c2011-05-24 12:43:12 +0100698template<int I, int T>
699LInstruction* LChunkBuilder::DefineSameAsFirst(
700 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100701 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
702}
703
704
Steve Block1e0659c2011-05-24 12:43:12 +0100705template<int I, int T>
706LInstruction* LChunkBuilder::DefineFixed(
707 LTemplateInstruction<1, I, T>* instr, Register reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100708 return Define(instr, ToUnallocated(reg));
709}
710
711
Steve Block1e0659c2011-05-24 12:43:12 +0100712template<int I, int T>
713LInstruction* LChunkBuilder::DefineFixedDouble(
714 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100715 return Define(instr, ToUnallocated(reg));
716}
717
718
719LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
720 HEnvironment* hydrogen_env = current_block_->last_environment();
721 instr->set_environment(CreateEnvironment(hydrogen_env));
722 return instr;
723}
724
725
726LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
727 LInstruction* instr, int ast_id) {
Steve Block1e0659c2011-05-24 12:43:12 +0100728 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100729 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
Steve Block1e0659c2011-05-24 12:43:12 +0100730 instruction_pending_deoptimization_environment_ = instr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100731 pending_deoptimization_ast_id_ = ast_id;
732 return instr;
733}
734
735
736void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
Steve Block1e0659c2011-05-24 12:43:12 +0100737 instruction_pending_deoptimization_environment_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100738 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
739}
740
741
742LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
743 HInstruction* hinstr,
744 CanDeoptimize can_deoptimize) {
Steve Block1e0659c2011-05-24 12:43:12 +0100745#ifdef DEBUG
746 instr->VerifyCall();
747#endif
748 instr->MarkAsCall();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100749 instr = AssignPointerMap(instr);
750
751 if (hinstr->HasSideEffects()) {
752 ASSERT(hinstr->next()->IsSimulate());
753 HSimulate* sim = HSimulate::cast(hinstr->next());
754 instr = SetInstructionPendingDeoptimizationEnvironment(
755 instr, sim->ast_id());
756 }
757
758 // If instruction does not have side-effects lazy deoptimization
759 // after the call will try to deoptimize to the point before the call.
760 // Thus we still need to attach environment to this call even if
761 // call sequence can not deoptimize eagerly.
762 bool needs_environment =
763 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
764 if (needs_environment && !instr->HasEnvironment()) {
765 instr = AssignEnvironment(instr);
766 }
767
768 return instr;
769}
770
771
Steve Block1e0659c2011-05-24 12:43:12 +0100772LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
773 instr->MarkAsSaveDoubles();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100774 return instr;
775}
776
777
Steve Block1e0659c2011-05-24 12:43:12 +0100778LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
779 ASSERT(!instr->HasPointerMap());
780 instr->set_pointer_map(new LPointerMap(position_));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100781 return instr;
782}
783
784
Ben Murdochb0fe1622011-05-05 13:52:32 +0100785LUnallocated* LChunkBuilder::TempRegister() {
786 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
787 allocator_->RecordTemporary(operand);
788 return operand;
789}
790
791
792LOperand* LChunkBuilder::FixedTemp(Register reg) {
793 LUnallocated* operand = ToUnallocated(reg);
794 allocator_->RecordTemporary(operand);
795 return operand;
796}
797
798
799LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
800 LUnallocated* operand = ToUnallocated(reg);
801 allocator_->RecordTemporary(operand);
802 return operand;
803}
804
805
806LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
807 return new LLabel(instr->block());
808}
809
810
811LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
812 return AssignEnvironment(new LDeoptimize);
813}
814
815
816LInstruction* LChunkBuilder::DoBit(Token::Value op,
817 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100818 if (instr->representation().IsInteger32()) {
819 ASSERT(instr->left()->representation().IsInteger32());
820 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100821
Steve Block1e0659c2011-05-24 12:43:12 +0100822 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
823 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
824 return DefineSameAsFirst(new LBitI(op, left, right));
825 } else {
826 ASSERT(instr->representation().IsTagged());
827 ASSERT(instr->left()->representation().IsTagged());
828 ASSERT(instr->right()->representation().IsTagged());
829
830 LOperand* left = UseFixed(instr->left(), r1);
831 LOperand* right = UseFixed(instr->right(), r0);
832 LArithmeticT* result = new LArithmeticT(op, left, right);
833 return MarkAsCall(DefineFixed(result, r0), instr);
834 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100835}
836
837
838LInstruction* LChunkBuilder::DoShift(Token::Value op,
839 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100840 if (instr->representation().IsTagged()) {
841 ASSERT(instr->left()->representation().IsTagged());
842 ASSERT(instr->right()->representation().IsTagged());
843
844 LOperand* left = UseFixed(instr->left(), r1);
845 LOperand* right = UseFixed(instr->right(), r0);
846 LArithmeticT* result = new LArithmeticT(op, left, right);
847 return MarkAsCall(DefineFixed(result, r0), instr);
848 }
849
Ben Murdochb0fe1622011-05-05 13:52:32 +0100850 ASSERT(instr->representation().IsInteger32());
851 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
852 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
853 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
854
855 HValue* right_value = instr->OperandAt(1);
856 LOperand* right = NULL;
857 int constant_value = 0;
858 if (right_value->IsConstant()) {
859 HConstant* constant = HConstant::cast(right_value);
860 right = chunk_->DefineConstantOperand(constant);
861 constant_value = constant->Integer32Value() & 0x1f;
862 } else {
863 right = UseRegister(right_value);
864 }
865
866 // Shift operations can only deoptimize if we do a logical shift
867 // by 0 and the result cannot be truncated to int32.
Ben Murdoch257744e2011-11-30 15:57:28 +0000868 bool may_deopt = (op == Token::SHR && constant_value == 0);
869 bool does_deopt = false;
870 if (may_deopt) {
871 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
872 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
873 does_deopt = true;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100874 break;
875 }
876 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100877 }
878
879 LInstruction* result =
Ben Murdoch257744e2011-11-30 15:57:28 +0000880 DefineSameAsFirst(new LShiftI(op, left, right, does_deopt));
881 return does_deopt ? AssignEnvironment(result) : result;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100882}
883
884
885LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
886 HArithmeticBinaryOperation* instr) {
887 ASSERT(instr->representation().IsDouble());
888 ASSERT(instr->left()->representation().IsDouble());
889 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100890 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100891 LOperand* left = UseRegisterAtStart(instr->left());
892 LOperand* right = UseRegisterAtStart(instr->right());
893 LArithmeticD* result = new LArithmeticD(op, left, right);
894 return DefineSameAsFirst(result);
895}
896
897
898LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
899 HArithmeticBinaryOperation* instr) {
900 ASSERT(op == Token::ADD ||
901 op == Token::DIV ||
902 op == Token::MOD ||
903 op == Token::MUL ||
904 op == Token::SUB);
905 HValue* left = instr->left();
906 HValue* right = instr->right();
907 ASSERT(left->representation().IsTagged());
908 ASSERT(right->representation().IsTagged());
909 LOperand* left_operand = UseFixed(left, r1);
910 LOperand* right_operand = UseFixed(right, r0);
Steve Block1e0659c2011-05-24 12:43:12 +0100911 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100912 return MarkAsCall(DefineFixed(result, r0), instr);
913}
914
Steve Block1e0659c2011-05-24 12:43:12 +0100915
Ben Murdochb0fe1622011-05-05 13:52:32 +0100916void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
917 ASSERT(is_building());
918 current_block_ = block;
919 next_block_ = next_block;
920 if (block->IsStartBlock()) {
921 block->UpdateEnvironment(graph_->start_environment());
922 argument_count_ = 0;
923 } else if (block->predecessors()->length() == 1) {
924 // We have a single predecessor => copy environment and outgoing
925 // argument count from the predecessor.
926 ASSERT(block->phis()->length() == 0);
927 HBasicBlock* pred = block->predecessors()->at(0);
928 HEnvironment* last_environment = pred->last_environment();
929 ASSERT(last_environment != NULL);
930 // Only copy the environment, if it is later used again.
931 if (pred->end()->SecondSuccessor() == NULL) {
932 ASSERT(pred->end()->FirstSuccessor() == block);
933 } else {
934 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
935 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
936 last_environment = last_environment->Copy();
937 }
938 }
939 block->UpdateEnvironment(last_environment);
940 ASSERT(pred->argument_count() >= 0);
941 argument_count_ = pred->argument_count();
942 } else {
943 // We are at a state join => process phis.
944 HBasicBlock* pred = block->predecessors()->at(0);
945 // No need to copy the environment, it cannot be used later.
946 HEnvironment* last_environment = pred->last_environment();
947 for (int i = 0; i < block->phis()->length(); ++i) {
948 HPhi* phi = block->phis()->at(i);
949 last_environment->SetValueAt(phi->merged_index(), phi);
950 }
951 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
952 last_environment->SetValueAt(block->deleted_phis()->at(i),
953 graph_->GetConstantUndefined());
954 }
955 block->UpdateEnvironment(last_environment);
956 // Pick up the outgoing argument count of one of the predecessors.
957 argument_count_ = pred->argument_count();
958 }
959 HInstruction* current = block->first();
960 int start = chunk_->instructions()->length();
961 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100962 // Code for constants in registers is generated lazily.
963 if (!current->EmitAtUses()) {
964 VisitInstruction(current);
965 }
966 current = current->next();
967 }
968 int end = chunk_->instructions()->length() - 1;
969 if (end >= start) {
970 block->set_first_instruction_index(start);
971 block->set_last_instruction_index(end);
972 }
973 block->set_argument_count(argument_count_);
974 next_block_ = NULL;
975 current_block_ = NULL;
976}
977
978
979void LChunkBuilder::VisitInstruction(HInstruction* current) {
980 HInstruction* old_current = current_instruction_;
981 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100982 if (current->has_position()) position_ = current->position();
983 LInstruction* instr = current->CompileToLithium(this);
984
985 if (instr != NULL) {
986 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
987 instr = AssignPointerMap(instr);
988 }
989 if (FLAG_stress_environments && !instr->HasEnvironment()) {
990 instr = AssignEnvironment(instr);
991 }
Steve Block1e0659c2011-05-24 12:43:12 +0100992 if (current->IsTest() && !instr->IsGoto()) {
993 ASSERT(instr->IsControl());
994 HTest* test = HTest::cast(current);
995 instr->set_hydrogen_value(test->value());
996 HBasicBlock* first = test->FirstSuccessor();
997 HBasicBlock* second = test->SecondSuccessor();
998 ASSERT(first != NULL && second != NULL);
999 instr->SetBranchTargets(first->block_id(), second->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001000 } else {
1001 instr->set_hydrogen_value(current);
1002 }
1003
Steve Block1e0659c2011-05-24 12:43:12 +01001004 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005 }
1006 current_instruction_ = old_current;
1007}
1008
1009
Ben Murdochb0fe1622011-05-05 13:52:32 +01001010LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
1011 if (hydrogen_env == NULL) return NULL;
1012
1013 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1014 int ast_id = hydrogen_env->ast_id();
1015 ASSERT(ast_id != AstNode::kNoNumber);
Steve Block9fac8402011-05-12 15:51:54 +01001016 int value_count = hydrogen_env->length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001017 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1018 ast_id,
1019 hydrogen_env->parameter_count(),
1020 argument_count_,
1021 value_count,
1022 outer);
1023 int argument_index = 0;
1024 for (int i = 0; i < value_count; ++i) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001025 if (hydrogen_env->is_special_index(i)) continue;
1026
Ben Murdochb0fe1622011-05-05 13:52:32 +01001027 HValue* value = hydrogen_env->values()->at(i);
1028 LOperand* op = NULL;
1029 if (value->IsArgumentsObject()) {
1030 op = NULL;
1031 } else if (value->IsPushArgument()) {
1032 op = new LArgument(argument_index++);
1033 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001034 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001035 }
1036 result->AddValue(op, value->representation());
1037 }
1038
1039 return result;
1040}
1041
1042
1043LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1044 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(),
1045 instr->include_stack_check());
1046 if (instr->include_stack_check()) result = AssignPointerMap(result);
1047 return result;
1048}
1049
1050
Steve Block1e0659c2011-05-24 12:43:12 +01001051LInstruction* LChunkBuilder::DoTest(HTest* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001052 HValue* v = instr->value();
Ben Murdoch257744e2011-11-30 15:57:28 +00001053 if (!v->EmitAtUses()) {
1054 return new LBranch(UseRegisterAtStart(v));
1055 } else if (v->IsClassOfTest()) {
1056 HClassOfTest* compare = HClassOfTest::cast(v);
1057 ASSERT(compare->value()->representation().IsTagged());
1058 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
1059 TempRegister());
1060 } else if (v->IsCompare()) {
1061 HCompare* compare = HCompare::cast(v);
1062 Token::Value op = compare->token();
1063 HValue* left = compare->left();
1064 HValue* right = compare->right();
1065 Representation r = compare->GetInputRepresentation();
1066 if (r.IsInteger32()) {
1067 ASSERT(left->representation().IsInteger32());
1068 ASSERT(right->representation().IsInteger32());
1069 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1070 UseRegisterAtStart(right));
1071 } else if (r.IsDouble()) {
1072 ASSERT(left->representation().IsDouble());
1073 ASSERT(right->representation().IsDouble());
1074 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1075 UseRegisterAtStart(right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001076 } else {
Ben Murdoch257744e2011-11-30 15:57:28 +00001077 ASSERT(left->representation().IsTagged());
1078 ASSERT(right->representation().IsTagged());
1079 bool reversed = op == Token::GT || op == Token::LTE;
1080 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1);
1081 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0);
1082 LInstruction* result = new LCmpTAndBranch(left_operand, right_operand);
1083 return MarkAsCall(result, instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001084 }
Ben Murdoch257744e2011-11-30 15:57:28 +00001085 } else if (v->IsIsSmi()) {
1086 HIsSmi* compare = HIsSmi::cast(v);
1087 ASSERT(compare->value()->representation().IsTagged());
1088 return new LIsSmiAndBranch(Use(compare->value()));
1089 } else if (v->IsIsUndetectable()) {
1090 HIsUndetectable* compare = HIsUndetectable::cast(v);
1091 ASSERT(compare->value()->representation().IsTagged());
1092 return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()),
1093 TempRegister());
1094 } else if (v->IsHasInstanceType()) {
1095 HHasInstanceType* compare = HHasInstanceType::cast(v);
1096 ASSERT(compare->value()->representation().IsTagged());
1097 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()));
1098 } else if (v->IsHasCachedArrayIndex()) {
1099 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1100 ASSERT(compare->value()->representation().IsTagged());
1101 return new LHasCachedArrayIndexAndBranch(
1102 UseRegisterAtStart(compare->value()));
1103 } else if (v->IsIsNull()) {
1104 HIsNull* compare = HIsNull::cast(v);
1105 ASSERT(compare->value()->representation().IsTagged());
1106 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()));
1107 } else if (v->IsIsObject()) {
1108 HIsObject* compare = HIsObject::cast(v);
1109 ASSERT(compare->value()->representation().IsTagged());
1110 LOperand* temp = TempRegister();
1111 return new LIsObjectAndBranch(UseRegister(compare->value()), temp);
1112 } else if (v->IsCompareJSObjectEq()) {
1113 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1114 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
1115 UseRegisterAtStart(compare->right()));
1116 } else if (v->IsCompareSymbolEq()) {
1117 HCompareSymbolEq* compare = HCompareSymbolEq::cast(v);
1118 return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()),
1119 UseRegisterAtStart(compare->right()));
1120 } else if (v->IsInstanceOf()) {
1121 HInstanceOf* instance_of = HInstanceOf::cast(v);
1122 LInstruction* result =
1123 new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0),
1124 UseFixed(instance_of->right(), r1));
1125 return MarkAsCall(result, instr);
1126 } else if (v->IsTypeofIs()) {
1127 HTypeofIs* typeof_is = HTypeofIs::cast(v);
1128 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1129 } else if (v->IsIsConstructCall()) {
1130 return new LIsConstructCallAndBranch(TempRegister());
1131 } else if (v->IsConstant()) {
1132 HBasicBlock* successor = HConstant::cast(v)->ToBoolean()
1133 ? instr->FirstSuccessor()
1134 : instr->SecondSuccessor();
1135 return new LGoto(successor->block_id());
1136 } else {
1137 Abort("Undefined compare before branch");
1138 return NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001139 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001140}
1141
1142
Ben Murdoch257744e2011-11-30 15:57:28 +00001143
Steve Block1e0659c2011-05-24 12:43:12 +01001144LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001145 ASSERT(instr->value()->representation().IsTagged());
1146 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block9fac8402011-05-12 15:51:54 +01001147 LOperand* temp = TempRegister();
1148 return new LCmpMapAndBranch(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001149}
1150
1151
1152LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001153 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001154}
1155
1156
1157LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1158 return DefineAsRegister(new LArgumentsElements);
1159}
1160
1161
1162LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001163 LInstanceOf* result =
Steve Block9fac8402011-05-12 15:51:54 +01001164 new LInstanceOf(UseFixed(instr->left(), r0),
1165 UseFixed(instr->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001166 return MarkAsCall(DefineFixed(result, r0), instr);
1167}
1168
1169
Ben Murdoch086aeea2011-05-13 15:57:08 +01001170LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1171 HInstanceOfKnownGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001172 LInstanceOfKnownGlobal* result =
1173 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001174 return MarkAsCall(DefineFixed(result, r0), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001175}
1176
1177
Ben Murdochb0fe1622011-05-05 13:52:32 +01001178LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1179 LOperand* function = UseFixed(instr->function(), r1);
1180 LOperand* receiver = UseFixed(instr->receiver(), r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001181 LOperand* length = UseFixed(instr->length(), r2);
1182 LOperand* elements = UseFixed(instr->elements(), r3);
1183 LApplyArguments* result = new LApplyArguments(function,
1184 receiver,
1185 length,
1186 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001187 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1188}
1189
1190
1191LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1192 ++argument_count_;
1193 LOperand* argument = Use(instr->argument());
1194 return new LPushArgument(argument);
1195}
1196
1197
Steve Block1e0659c2011-05-24 12:43:12 +01001198LInstruction* LChunkBuilder::DoContext(HContext* instr) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001199 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext);
Steve Block1e0659c2011-05-24 12:43:12 +01001200}
1201
1202
1203LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1204 LOperand* context = UseRegisterAtStart(instr->value());
1205 return DefineAsRegister(new LOuterContext(context));
1206}
1207
1208
Ben Murdochb0fe1622011-05-05 13:52:32 +01001209LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001210 LOperand* context = UseRegisterAtStart(instr->value());
1211 return DefineAsRegister(new LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001212}
1213
1214
1215LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001216 LOperand* global_object = UseRegisterAtStart(instr->value());
1217 return DefineAsRegister(new LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001218}
1219
1220
1221LInstruction* LChunkBuilder::DoCallConstantFunction(
1222 HCallConstantFunction* instr) {
1223 argument_count_ -= instr->argument_count();
1224 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
1225}
1226
1227
Ben Murdoch257744e2011-11-30 15:57:28 +00001228LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1229 LOperand* function = UseFixed(instr->function(), r1);
1230 argument_count_ -= instr->argument_count();
1231 LInvokeFunction* result = new LInvokeFunction(function);
1232 return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1233}
1234
1235
Ben Murdochb0fe1622011-05-05 13:52:32 +01001236LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1237 BuiltinFunctionId op = instr->op();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001238 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1239 LOperand* input = UseFixedDouble(instr->value(), d2);
1240 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
1241 return MarkAsCall(DefineFixedDouble(result, d2), instr);
1242 } else {
1243 LOperand* input = UseRegisterAtStart(instr->value());
1244 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1245 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1246 switch (op) {
1247 case kMathAbs:
1248 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1249 case kMathFloor:
1250 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1251 case kMathSqrt:
1252 return DefineSameAsFirst(result);
1253 case kMathRound:
1254 return AssignEnvironment(DefineAsRegister(result));
1255 case kMathPowHalf:
Steve Block44f0eee2011-05-26 01:26:41 +01001256 return DefineSameAsFirst(result);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001257 default:
1258 UNREACHABLE();
1259 return NULL;
1260 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001261 }
1262}
1263
1264
1265LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1266 ASSERT(instr->key()->representation().IsTagged());
1267 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001268 LOperand* key = UseFixed(instr->key(), r2);
1269 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001270}
1271
1272
1273LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1274 argument_count_ -= instr->argument_count();
1275 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
1276}
1277
1278
1279LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1280 argument_count_ -= instr->argument_count();
1281 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
1282}
1283
1284
1285LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1286 argument_count_ -= instr->argument_count();
1287 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
1288}
1289
1290
1291LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1292 LOperand* constructor = UseFixed(instr->constructor(), r1);
1293 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001294 LCallNew* result = new LCallNew(constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001295 return MarkAsCall(DefineFixed(result, r0), instr);
1296}
1297
1298
1299LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1300 argument_count_ -= instr->argument_count();
1301 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
1302}
1303
1304
1305LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1306 argument_count_ -= instr->argument_count();
1307 return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
1308}
1309
1310
1311LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1312 return DoShift(Token::SHR, instr);
1313}
1314
1315
1316LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1317 return DoShift(Token::SAR, instr);
1318}
1319
1320
1321LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1322 return DoShift(Token::SHL, instr);
1323}
1324
1325
1326LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1327 return DoBit(Token::BIT_AND, instr);
1328}
1329
1330
1331LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1332 ASSERT(instr->value()->representation().IsInteger32());
1333 ASSERT(instr->representation().IsInteger32());
1334 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value())));
1335}
1336
1337
1338LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1339 return DoBit(Token::BIT_OR, instr);
1340}
1341
1342
1343LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1344 return DoBit(Token::BIT_XOR, instr);
1345}
1346
1347
1348LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1349 if (instr->representation().IsDouble()) {
1350 return DoArithmeticD(Token::DIV, instr);
1351 } else if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001352 // TODO(1042) The fixed register allocation
Ben Murdoch8b112d22011-06-08 16:22:53 +01001353 // is needed because we call TypeRecordingBinaryOpStub from
Ben Murdochb8e0da22011-05-16 14:20:40 +01001354 // the generated code, which requires registers r0
1355 // and r1 to be used. We should remove that
1356 // when we provide a native implementation.
Steve Block1e0659c2011-05-24 12:43:12 +01001357 LOperand* dividend = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001358 LOperand* divisor = UseFixed(instr->right(), r1);
1359 return AssignEnvironment(AssignPointerMap(
Steve Block1e0659c2011-05-24 12:43:12 +01001360 DefineFixed(new LDivI(dividend, divisor), r0)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001361 } else {
1362 return DoArithmeticT(Token::DIV, instr);
1363 }
1364}
1365
1366
1367LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1368 if (instr->representation().IsInteger32()) {
1369 ASSERT(instr->left()->representation().IsInteger32());
1370 ASSERT(instr->right()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01001371
1372 LModI* mod;
1373 if (instr->HasPowerOf2Divisor()) {
1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1375 LOperand* value = UseRegisterAtStart(instr->left());
1376 mod = new LModI(value, UseOrConstant(instr->right()));
1377 } else {
1378 LOperand* dividend = UseRegister(instr->left());
1379 LOperand* divisor = UseRegisterAtStart(instr->right());
1380 mod = new LModI(dividend,
1381 divisor,
1382 TempRegister(),
1383 FixedTemp(d1),
1384 FixedTemp(d2));
1385 }
1386
1387 return AssignEnvironment(DefineSameAsFirst(mod));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001388 } else if (instr->representation().IsTagged()) {
1389 return DoArithmeticT(Token::MOD, instr);
1390 } else {
1391 ASSERT(instr->representation().IsDouble());
1392 // We call a C function for double modulo. It can't trigger a GC.
1393 // We need to use fixed result register for the call.
1394 // TODO(fschneider): Allow any register as input registers.
1395 LOperand* left = UseFixedDouble(instr->left(), d1);
1396 LOperand* right = UseFixedDouble(instr->right(), d2);
1397 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
1398 return MarkAsCall(DefineFixedDouble(result, d1), instr);
1399 }
1400}
1401
1402
1403LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1404 if (instr->representation().IsInteger32()) {
1405 ASSERT(instr->left()->representation().IsInteger32());
1406 ASSERT(instr->right()->representation().IsInteger32());
1407 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1408 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1409 LOperand* temp = NULL;
1410 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1411 temp = TempRegister();
1412 }
1413 LMulI* mul = new LMulI(left, right, temp);
1414 return AssignEnvironment(DefineSameAsFirst(mul));
1415 } else if (instr->representation().IsDouble()) {
1416 return DoArithmeticD(Token::MUL, instr);
1417 } else {
1418 return DoArithmeticT(Token::MUL, instr);
1419 }
1420}
1421
1422
1423LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1424 if (instr->representation().IsInteger32()) {
1425 ASSERT(instr->left()->representation().IsInteger32());
1426 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001427 LOperand* left = UseRegisterAtStart(instr->left());
1428 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001429 LSubI* sub = new LSubI(left, right);
1430 LInstruction* result = DefineSameAsFirst(sub);
1431 if (instr->CheckFlag(HValue::kCanOverflow)) {
1432 result = AssignEnvironment(result);
1433 }
1434 return result;
1435 } else if (instr->representation().IsDouble()) {
1436 return DoArithmeticD(Token::SUB, instr);
1437 } else {
1438 return DoArithmeticT(Token::SUB, instr);
1439 }
1440}
1441
1442
1443LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1444 if (instr->representation().IsInteger32()) {
1445 ASSERT(instr->left()->representation().IsInteger32());
1446 ASSERT(instr->right()->representation().IsInteger32());
1447 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1448 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1449 LAddI* add = new LAddI(left, right);
1450 LInstruction* result = DefineSameAsFirst(add);
1451 if (instr->CheckFlag(HValue::kCanOverflow)) {
1452 result = AssignEnvironment(result);
1453 }
1454 return result;
1455 } else if (instr->representation().IsDouble()) {
1456 return DoArithmeticD(Token::ADD, instr);
1457 } else {
1458 ASSERT(instr->representation().IsTagged());
1459 return DoArithmeticT(Token::ADD, instr);
1460 }
1461}
1462
1463
1464LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001465 ASSERT(instr->representation().IsDouble());
1466 // We call a C function for double power. It can't trigger a GC.
1467 // We need to use fixed result register for the call.
1468 Representation exponent_type = instr->right()->representation();
1469 ASSERT(instr->left()->representation().IsDouble());
1470 LOperand* left = UseFixedDouble(instr->left(), d1);
1471 LOperand* right = exponent_type.IsDouble() ?
1472 UseFixedDouble(instr->right(), d2) :
1473 UseFixed(instr->right(), r0);
1474 LPower* result = new LPower(left, right);
1475 return MarkAsCall(DefineFixedDouble(result, d3),
1476 instr,
1477 CAN_DEOPTIMIZE_EAGERLY);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001478}
1479
1480
1481LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1482 Token::Value op = instr->token();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001483 Representation r = instr->GetInputRepresentation();
1484 if (r.IsInteger32()) {
1485 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001486 ASSERT(instr->right()->representation().IsInteger32());
1487 LOperand* left = UseRegisterAtStart(instr->left());
Steve Block1e0659c2011-05-24 12:43:12 +01001488 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001489 return DefineAsRegister(new LCmpID(left, right));
1490 } else if (r.IsDouble()) {
1491 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001492 ASSERT(instr->right()->representation().IsDouble());
1493 LOperand* left = UseRegisterAtStart(instr->left());
1494 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001495 return DefineAsRegister(new LCmpID(left, right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001496 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001497 ASSERT(instr->left()->representation().IsTagged());
1498 ASSERT(instr->right()->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001499 bool reversed = (op == Token::GT || op == Token::LTE);
1500 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1501 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001502 LCmpT* result = new LCmpT(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001503 return MarkAsCall(DefineFixed(result, r0), instr);
1504 }
1505}
1506
1507
1508LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1509 HCompareJSObjectEq* instr) {
1510 LOperand* left = UseRegisterAtStart(instr->left());
1511 LOperand* right = UseRegisterAtStart(instr->right());
Steve Block1e0659c2011-05-24 12:43:12 +01001512 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001513 return DefineAsRegister(result);
1514}
1515
1516
Ben Murdoch257744e2011-11-30 15:57:28 +00001517LInstruction* LChunkBuilder::DoCompareSymbolEq(
1518 HCompareSymbolEq* instr) {
1519 LOperand* left = UseRegisterAtStart(instr->left());
1520 LOperand* right = UseRegisterAtStart(instr->right());
1521 LCmpSymbolEq* result = new LCmpSymbolEq(left, right);
1522 return DefineAsRegister(result);
1523}
1524
1525
Ben Murdochb0fe1622011-05-05 13:52:32 +01001526LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1527 ASSERT(instr->value()->representation().IsTagged());
1528 LOperand* value = UseRegisterAtStart(instr->value());
1529
Ben Murdochb8e0da22011-05-16 14:20:40 +01001530 return DefineAsRegister(new LIsNull(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001531}
1532
1533
1534LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1535 ASSERT(instr->value()->representation().IsTagged());
1536 LOperand* value = UseRegisterAtStart(instr->value());
1537
Steve Block1e0659c2011-05-24 12:43:12 +01001538 return DefineAsRegister(new LIsObject(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001539}
1540
1541
1542LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1543 ASSERT(instr->value()->representation().IsTagged());
1544 LOperand* value = UseAtStart(instr->value());
1545
1546 return DefineAsRegister(new LIsSmi(value));
1547}
1548
1549
Ben Murdoch257744e2011-11-30 15:57:28 +00001550LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) {
1551 ASSERT(instr->value()->representation().IsTagged());
1552 LOperand* value = UseRegisterAtStart(instr->value());
1553
1554 return DefineAsRegister(new LIsUndetectable(value));
1555}
1556
1557
Ben Murdochb0fe1622011-05-05 13:52:32 +01001558LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1559 ASSERT(instr->value()->representation().IsTagged());
1560 LOperand* value = UseRegisterAtStart(instr->value());
1561
1562 return DefineAsRegister(new LHasInstanceType(value));
1563}
1564
1565
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001566LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1567 HGetCachedArrayIndex* instr) {
1568 ASSERT(instr->value()->representation().IsTagged());
1569 LOperand* value = UseRegisterAtStart(instr->value());
1570
1571 return DefineAsRegister(new LGetCachedArrayIndex(value));
1572}
1573
1574
Ben Murdochb0fe1622011-05-05 13:52:32 +01001575LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1576 HHasCachedArrayIndex* instr) {
1577 ASSERT(instr->value()->representation().IsTagged());
1578 LOperand* value = UseRegister(instr->value());
1579
1580 return DefineAsRegister(new LHasCachedArrayIndex(value));
1581}
1582
1583
1584LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1585 ASSERT(instr->value()->representation().IsTagged());
1586 LOperand* value = UseTempRegister(instr->value());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001587 return DefineSameAsFirst(new LClassOfTest(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001588}
1589
1590
Steve Block9fac8402011-05-12 15:51:54 +01001591LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1592 LOperand* array = UseRegisterAtStart(instr->value());
1593 return DefineAsRegister(new LJSArrayLength(array));
1594}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001595
Ben Murdochb0fe1622011-05-05 13:52:32 +01001596
Steve Block44f0eee2011-05-26 01:26:41 +01001597LInstruction* LChunkBuilder::DoExternalArrayLength(
1598 HExternalArrayLength* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001599 LOperand* array = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001600 return DefineAsRegister(new LExternalArrayLength(array));
Steve Block1e0659c2011-05-24 12:43:12 +01001601}
1602
1603
Steve Block9fac8402011-05-12 15:51:54 +01001604LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1605 LOperand* array = UseRegisterAtStart(instr->value());
1606 return DefineAsRegister(new LFixedArrayLength(array));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001607}
1608
1609
1610LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1611 LOperand* object = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001612 LValueOf* result = new LValueOf(object, TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001613 return AssignEnvironment(DefineSameAsFirst(result));
1614}
1615
1616
1617LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1618 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001619 UseRegister(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001620}
1621
1622
Steve Block1e0659c2011-05-24 12:43:12 +01001623LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1624 // The control instruction marking the end of a block that completed
1625 // abruptly (e.g., threw an exception). There is nothing specific to do.
1626 return NULL;
1627}
1628
1629
Ben Murdochb0fe1622011-05-05 13:52:32 +01001630LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1631 LOperand* value = UseFixed(instr->value(), r0);
1632 return MarkAsCall(new LThrow(value), instr);
1633}
1634
1635
Ben Murdoch257744e2011-11-30 15:57:28 +00001636LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1637 // All HForceRepresentation instructions should be eliminated in the
1638 // representation change phase of Hydrogen.
1639 UNREACHABLE();
1640 return NULL;
1641}
1642
1643
Ben Murdochb0fe1622011-05-05 13:52:32 +01001644LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1645 Representation from = instr->from();
1646 Representation to = instr->to();
1647 if (from.IsTagged()) {
1648 if (to.IsDouble()) {
1649 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001650 LNumberUntagD* res = new LNumberUntagD(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001651 return AssignEnvironment(DefineAsRegister(res));
1652 } else {
1653 ASSERT(to.IsInteger32());
1654 LOperand* value = UseRegister(instr->value());
1655 bool needs_check = !instr->value()->type().IsSmi();
1656 LInstruction* res = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001657 if (!needs_check) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001658 res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
Steve Block44f0eee2011-05-26 01:26:41 +01001659 } else {
1660 LOperand* temp1 = TempRegister();
1661 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1662 : NULL;
1663 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
1664 : NULL;
1665 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001666 res = AssignEnvironment(res);
1667 }
1668 return res;
1669 }
1670 } else if (from.IsDouble()) {
1671 if (to.IsTagged()) {
1672 LOperand* value = UseRegister(instr->value());
1673 LOperand* temp1 = TempRegister();
1674 LOperand* temp2 = TempRegister();
1675
1676 // Make sure that the temp and result_temp registers are
1677 // different.
1678 LUnallocated* result_temp = TempRegister();
Steve Block1e0659c2011-05-24 12:43:12 +01001679 LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001680 Define(result, result_temp);
1681 return AssignPointerMap(result);
1682 } else {
1683 ASSERT(to.IsInteger32());
1684 LOperand* value = UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001685 LDoubleToI* res =
1686 new LDoubleToI(value,
1687 TempRegister(),
1688 instr->CanTruncateToInt32() ? TempRegister() : NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001689 return AssignEnvironment(DefineAsRegister(res));
1690 }
1691 } else if (from.IsInteger32()) {
1692 if (to.IsTagged()) {
1693 HValue* val = instr->value();
1694 LOperand* value = UseRegister(val);
1695 if (val->HasRange() && val->range()->IsInSmiRange()) {
1696 return DefineSameAsFirst(new LSmiTag(value));
1697 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001698 LNumberTagI* result = new LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001699 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1700 }
1701 } else {
1702 ASSERT(to.IsDouble());
1703 LOperand* value = Use(instr->value());
1704 return DefineAsRegister(new LInteger32ToDouble(value));
1705 }
1706 }
1707 UNREACHABLE();
1708 return NULL;
1709}
1710
1711
1712LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1713 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001714 return AssignEnvironment(new LCheckNonSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001715}
1716
1717
1718LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1719 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001720 LInstruction* result = new LCheckInstanceType(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001721 return AssignEnvironment(result);
1722}
1723
1724
1725LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001726 LOperand* temp1 = TempRegister();
1727 LOperand* temp2 = TempRegister();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001728 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001729 return AssignEnvironment(result);
1730}
1731
1732
1733LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1734 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001735 return AssignEnvironment(new LCheckSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001736}
1737
1738
1739LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1740 LOperand* value = UseRegisterAtStart(instr->value());
1741 return AssignEnvironment(new LCheckFunction(value));
1742}
1743
1744
1745LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1746 LOperand* value = UseRegisterAtStart(instr->value());
1747 LInstruction* result = new LCheckMap(value);
1748 return AssignEnvironment(result);
1749}
1750
1751
Ben Murdoch257744e2011-11-30 15:57:28 +00001752LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1753 HValue* value = instr->value();
1754 Representation input_rep = value->representation();
1755 LOperand* reg = UseRegister(value);
1756 if (input_rep.IsDouble()) {
1757 return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d1)));
1758 } else if (input_rep.IsInteger32()) {
1759 return DefineAsRegister(new LClampIToUint8(reg));
1760 } else {
1761 ASSERT(input_rep.IsTagged());
1762 // Register allocator doesn't (yet) support allocation of double
1763 // temps. Reserve d1 explicitly.
1764 LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d1));
1765 return AssignEnvironment(DefineAsRegister(result));
1766 }
1767}
1768
1769
Ben Murdochb0fe1622011-05-05 13:52:32 +01001770LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1771 return new LReturn(UseFixed(instr->value(), r0));
1772}
1773
1774
1775LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1776 Representation r = instr->representation();
1777 if (r.IsInteger32()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001778 return DefineAsRegister(new LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001779 } else if (r.IsDouble()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001780 return DefineAsRegister(new LConstantD);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001781 } else if (r.IsTagged()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001782 return DefineAsRegister(new LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001783 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001784 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001785 return NULL;
1786 }
1787}
1788
1789
Ben Murdoch8b112d22011-06-08 16:22:53 +01001790LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1791 LLoadGlobalCell* result = new LLoadGlobalCell;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001792 return instr->check_hole_value()
1793 ? AssignEnvironment(DefineAsRegister(result))
1794 : DefineAsRegister(result);
1795}
1796
1797
Ben Murdoch8b112d22011-06-08 16:22:53 +01001798LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1799 LOperand* global_object = UseFixed(instr->global_object(), r0);
1800 LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
1801 return MarkAsCall(DefineFixed(result, r0), instr);
1802}
1803
1804
1805LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001806 if (instr->check_hole_value()) {
1807 LOperand* temp = TempRegister();
1808 LOperand* value = UseRegister(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001809 return AssignEnvironment(new LStoreGlobalCell(value, temp));
Steve Block1e0659c2011-05-24 12:43:12 +01001810 } else {
1811 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001812 return new LStoreGlobalCell(value, NULL);
Steve Block1e0659c2011-05-24 12:43:12 +01001813 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001814}
1815
1816
Ben Murdoch8b112d22011-06-08 16:22:53 +01001817LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1818 LOperand* global_object = UseFixed(instr->global_object(), r1);
1819 LOperand* value = UseFixed(instr->value(), r0);
1820 LStoreGlobalGeneric* result =
1821 new LStoreGlobalGeneric(global_object, value);
1822 return MarkAsCall(result, instr);
1823}
1824
1825
Ben Murdochb8e0da22011-05-16 14:20:40 +01001826LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001827 LOperand* context = UseRegisterAtStart(instr->value());
1828 return DefineAsRegister(new LLoadContextSlot(context));
1829}
1830
1831
1832LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001833 LOperand* context;
Steve Block1e0659c2011-05-24 12:43:12 +01001834 LOperand* value;
1835 if (instr->NeedsWriteBarrier()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001836 context = UseTempRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001837 value = UseTempRegister(instr->value());
1838 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001839 context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001840 value = UseRegister(instr->value());
1841 }
1842 return new LStoreContextSlot(context, value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001843}
1844
1845
Ben Murdochb0fe1622011-05-05 13:52:32 +01001846LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1847 return DefineAsRegister(
1848 new LLoadNamedField(UseRegisterAtStart(instr->object())));
1849}
1850
1851
Steve Block44f0eee2011-05-26 01:26:41 +01001852LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1853 HLoadNamedFieldPolymorphic* instr) {
1854 ASSERT(instr->representation().IsTagged());
1855 if (instr->need_generic()) {
1856 LOperand* obj = UseFixed(instr->object(), r0);
1857 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1858 return MarkAsCall(DefineFixed(result, r0), instr);
1859 } else {
1860 LOperand* obj = UseRegisterAtStart(instr->object());
1861 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1862 return AssignEnvironment(DefineAsRegister(result));
1863 }
1864}
1865
1866
Ben Murdochb0fe1622011-05-05 13:52:32 +01001867LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1868 LOperand* object = UseFixed(instr->object(), r0);
1869 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
1870 return MarkAsCall(result, instr);
1871}
1872
1873
Steve Block9fac8402011-05-12 15:51:54 +01001874LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1875 HLoadFunctionPrototype* instr) {
1876 return AssignEnvironment(DefineAsRegister(
1877 new LLoadFunctionPrototype(UseRegister(instr->function()))));
1878}
1879
1880
Ben Murdochb0fe1622011-05-05 13:52:32 +01001881LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1882 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001883 return DefineAsRegister(new LLoadElements(input));
1884}
1885
1886
Steve Block44f0eee2011-05-26 01:26:41 +01001887LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1888 HLoadExternalArrayPointer* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001889 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001890 return DefineAsRegister(new LLoadExternalArrayPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001891}
1892
1893
1894LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1895 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001896 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001897 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001898 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001899 LOperand* key = UseRegisterAtStart(instr->key());
Steve Block1e0659c2011-05-24 12:43:12 +01001900 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001901 return AssignEnvironment(DefineSameAsFirst(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001902}
1903
1904
Steve Block44f0eee2011-05-26 01:26:41 +01001905LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1906 HLoadKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001907 ExternalArrayType array_type = instr->array_type();
1908 Representation representation(instr->representation());
Ben Murdoch257744e2011-11-30 15:57:28 +00001909 ASSERT(
1910 (representation.IsInteger32() && (array_type != kExternalFloatArray &&
1911 array_type != kExternalDoubleArray)) ||
1912 (representation.IsDouble() && (array_type == kExternalFloatArray ||
1913 array_type == kExternalDoubleArray)));
Steve Block1e0659c2011-05-24 12:43:12 +01001914 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001915 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch257744e2011-11-30 15:57:28 +00001916 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001917 LLoadKeyedSpecializedArrayElement* result =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001918 new LLoadKeyedSpecializedArrayElement(external_pointer, key);
1919 LInstruction* load_instr = DefineAsRegister(result);
1920 // An unsigned int array load might overflow and cause a deopt, make sure it
1921 // has an environment.
1922 return (array_type == kExternalUnsignedIntArray) ?
1923 AssignEnvironment(load_instr) : load_instr;
Steve Block1e0659c2011-05-24 12:43:12 +01001924}
1925
1926
Ben Murdochb0fe1622011-05-05 13:52:32 +01001927LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1928 LOperand* object = UseFixed(instr->object(), r1);
1929 LOperand* key = UseFixed(instr->key(), r0);
1930
1931 LInstruction* result =
1932 DefineFixed(new LLoadKeyedGeneric(object, key), r0);
1933 return MarkAsCall(result, instr);
1934}
1935
1936
1937LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1938 HStoreKeyedFastElement* instr) {
1939 bool needs_write_barrier = instr->NeedsWriteBarrier();
1940 ASSERT(instr->value()->representation().IsTagged());
1941 ASSERT(instr->object()->representation().IsTagged());
1942 ASSERT(instr->key()->representation().IsInteger32());
1943
1944 LOperand* obj = UseTempRegister(instr->object());
1945 LOperand* val = needs_write_barrier
1946 ? UseTempRegister(instr->value())
1947 : UseRegisterAtStart(instr->value());
1948 LOperand* key = needs_write_barrier
1949 ? UseTempRegister(instr->key())
1950 : UseRegisterOrConstantAtStart(instr->key());
1951
1952 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1953}
1954
1955
Steve Block44f0eee2011-05-26 01:26:41 +01001956LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1957 HStoreKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001958 Representation representation(instr->value()->representation());
1959 ExternalArrayType array_type = instr->array_type();
Ben Murdoch257744e2011-11-30 15:57:28 +00001960 ASSERT(
1961 (representation.IsInteger32() && (array_type != kExternalFloatArray &&
1962 array_type != kExternalDoubleArray)) ||
1963 (representation.IsDouble() && (array_type == kExternalFloatArray ||
1964 array_type == kExternalDoubleArray)));
Steve Block44f0eee2011-05-26 01:26:41 +01001965 ASSERT(instr->external_pointer()->representation().IsExternal());
1966 ASSERT(instr->key()->representation().IsInteger32());
1967
1968 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001969 bool val_is_temp_register = array_type == kExternalPixelArray ||
1970 array_type == kExternalFloatArray;
1971 LOperand* val = val_is_temp_register
1972 ? UseTempRegister(instr->value())
1973 : UseRegister(instr->value());
Ben Murdoch257744e2011-11-30 15:57:28 +00001974 LOperand* key = UseRegisterOrConstant(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001975
1976 return new LStoreKeyedSpecializedArrayElement(external_pointer,
1977 key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01001978 val);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001979}
1980
1981
Ben Murdochb0fe1622011-05-05 13:52:32 +01001982LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1983 LOperand* obj = UseFixed(instr->object(), r2);
1984 LOperand* key = UseFixed(instr->key(), r1);
1985 LOperand* val = UseFixed(instr->value(), r0);
1986
1987 ASSERT(instr->object()->representation().IsTagged());
1988 ASSERT(instr->key()->representation().IsTagged());
1989 ASSERT(instr->value()->representation().IsTagged());
1990
1991 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1992}
1993
1994
1995LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001996 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001997
1998 LOperand* obj = needs_write_barrier
1999 ? UseTempRegister(instr->object())
2000 : UseRegisterAtStart(instr->object());
2001
2002 LOperand* val = needs_write_barrier
2003 ? UseTempRegister(instr->value())
2004 : UseRegister(instr->value());
2005
Ben Murdochb8e0da22011-05-16 14:20:40 +01002006 return new LStoreNamedField(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002007}
2008
2009
2010LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2011 LOperand* obj = UseFixed(instr->object(), r1);
2012 LOperand* val = UseFixed(instr->value(), r0);
2013
Ben Murdochb8e0da22011-05-16 14:20:40 +01002014 LInstruction* result = new LStoreNamedGeneric(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002015 return MarkAsCall(result, instr);
2016}
2017
2018
Ben Murdoch257744e2011-11-30 15:57:28 +00002019LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2020 LOperand* left = UseRegisterAtStart(instr->left());
2021 LOperand* right = UseRegisterAtStart(instr->right());
2022 return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr);
2023}
2024
2025
Steve Block1e0659c2011-05-24 12:43:12 +01002026LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2027 LOperand* string = UseRegister(instr->string());
2028 LOperand* index = UseRegisterOrConstant(instr->index());
2029 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
2030 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2031}
2032
2033
Steve Block44f0eee2011-05-26 01:26:41 +01002034LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2035 LOperand* char_code = UseRegister(instr->value());
2036 LStringCharFromCode* result = new LStringCharFromCode(char_code);
2037 return AssignPointerMap(DefineAsRegister(result));
2038}
2039
2040
Steve Block1e0659c2011-05-24 12:43:12 +01002041LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2042 LOperand* string = UseRegisterAtStart(instr->value());
2043 return DefineAsRegister(new LStringLength(string));
2044}
2045
2046
Ben Murdochb0fe1622011-05-05 13:52:32 +01002047LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
2048 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
2049}
2050
2051
2052LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
2053 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
2054}
2055
2056
2057LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2058 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
2059}
2060
2061
2062LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2063 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
2064}
2065
2066
2067LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002068 LOperand* object = UseFixed(instr->object(), r0);
2069 LOperand* key = UseFixed(instr->key(), r1);
2070 LDeleteProperty* result = new LDeleteProperty(object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002071 return MarkAsCall(DefineFixed(result, r0), instr);
2072}
2073
2074
2075LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2076 allocator_->MarkAsOsrEntry();
2077 current_block_->last_environment()->set_ast_id(instr->ast_id());
2078 return AssignEnvironment(new LOsrEntry);
2079}
2080
2081
2082LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2083 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2084 return DefineAsSpilled(new LParameter, spill_index);
2085}
2086
2087
2088LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2089 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +01002090 if (spill_index > LUnallocated::kMaxFixedIndex) {
2091 Abort("Too many spill slots needed for OSR");
2092 spill_index = 0;
2093 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002094 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
2095}
2096
2097
2098LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2099 argument_count_ -= instr->argument_count();
2100 return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
2101}
2102
2103
2104LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002105 // There are no real uses of the arguments object.
2106 // arguments.length and element access are supported directly on
2107 // stack arguments, and any real arguments object use causes a bailout.
2108 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002109 return NULL;
2110}
2111
2112
2113LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2114 LOperand* arguments = UseRegister(instr->arguments());
2115 LOperand* length = UseTempRegister(instr->length());
Ben Murdoch086aeea2011-05-13 15:57:08 +01002116 LOperand* index = UseRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01002117 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2118 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002119}
2120
2121
Steve Block44f0eee2011-05-26 01:26:41 +01002122LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2123 LOperand* object = UseFixed(instr->value(), r0);
2124 LToFastProperties* result = new LToFastProperties(object);
2125 return MarkAsCall(DefineFixed(result, r0), instr);
2126}
2127
2128
Ben Murdochb0fe1622011-05-05 13:52:32 +01002129LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002130 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002131 return MarkAsCall(DefineFixed(result, r0), instr);
2132}
2133
2134
2135LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
2136 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
2137}
2138
Steve Block1e0659c2011-05-24 12:43:12 +01002139
2140LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
2141 return DefineAsRegister(new LIsConstructCall());
2142}
2143
2144
Ben Murdochb0fe1622011-05-05 13:52:32 +01002145LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2146 HEnvironment* env = current_block_->last_environment();
2147 ASSERT(env != NULL);
2148
2149 env->set_ast_id(instr->ast_id());
2150
2151 env->Drop(instr->pop_count());
2152 for (int i = 0; i < instr->values()->length(); ++i) {
2153 HValue* value = instr->values()->at(i);
2154 if (instr->HasAssignedIndexAt(i)) {
2155 env->Bind(instr->GetAssignedIndexAt(i), value);
2156 } else {
2157 env->Push(value);
2158 }
2159 }
2160
Ben Murdochb0fe1622011-05-05 13:52:32 +01002161 // If there is an instruction pending deoptimization environment create a
2162 // lazy bailout instruction to capture the environment.
2163 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2164 LInstruction* result = new LLazyBailout;
2165 result = AssignEnvironment(result);
Steve Block1e0659c2011-05-24 12:43:12 +01002166 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002167 set_deoptimization_environment(result->environment());
2168 ClearInstructionPendingDeoptimizationEnvironment();
2169 return result;
2170 }
2171
2172 return NULL;
2173}
2174
2175
2176LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2177 return MarkAsCall(new LStackCheck, instr);
2178}
2179
2180
2181LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2182 HEnvironment* outer = current_block_->last_environment();
2183 HConstant* undefined = graph()->GetConstantUndefined();
2184 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2185 instr->function(),
Ben Murdoch257744e2011-11-30 15:57:28 +00002186 HEnvironment::LITHIUM,
2187 undefined,
2188 instr->call_kind());
Ben Murdochb0fe1622011-05-05 13:52:32 +01002189 current_block_->UpdateEnvironment(inner);
2190 chunk_->AddInlinedClosure(instr->closure());
2191 return NULL;
2192}
2193
2194
2195LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2196 HEnvironment* outer = current_block_->last_environment()->outer();
2197 current_block_->UpdateEnvironment(outer);
2198 return NULL;
2199}
2200
2201
Ben Murdoch257744e2011-11-30 15:57:28 +00002202LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2203 LOperand* key = UseRegisterAtStart(instr->key());
2204 LOperand* object = UseRegisterAtStart(instr->object());
2205 LIn* result = new LIn(key, object);
2206 return MarkAsCall(DefineFixed(result, r0), instr);
2207}
2208
2209
Ben Murdochb0fe1622011-05-05 13:52:32 +01002210} } // namespace v8::internal