blob: faf640490b705a850e04dcbde83a91743694e9b3 [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 Murdoch8b112d22011-06-08 16:22:53 +010064 // 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 Murdoch8b112d22011-06-08 16:22:53 +010072 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 Murdoch8b112d22011-06-08 16:22:53 +010077 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
153void LGap::PrintDataTo(StringStream* stream) const {
154 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
Steve Block1e0659c2011-05-24 12:43:12 +0100240void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100241 stream->Add("if has_instance_type(");
Steve Block1e0659c2011-05-24 12:43:12 +0100242 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100243 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 LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248 stream->Add("if has_cached_array_index(");
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 LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255 stream->Add("if class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100256 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100257 stream->Add(", \"%o\") then B%d else B%d",
258 *hydrogen()->class_name(),
259 true_block_id(),
260 false_block_id());
261}
262
263
Steve Block1e0659c2011-05-24 12:43:12 +0100264void LTypeofIs::PrintDataTo(StringStream* stream) {
265 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
267}
268
269
Steve Block1e0659c2011-05-24 12:43:12 +0100270void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100271 stream->Add("if typeof ");
Steve Block1e0659c2011-05-24 12:43:12 +0100272 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100273 stream->Add(" == \"%s\" then B%d else B%d",
274 *hydrogen()->type_literal()->ToCString(),
275 true_block_id(), false_block_id());
276}
277
278
Steve Block1e0659c2011-05-24 12:43:12 +0100279void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100280 stream->Add("#%d / ", arity());
281}
282
283
Steve Block1e0659c2011-05-24 12:43:12 +0100284void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100285 stream->Add("/%s ", hydrogen()->OpName());
Steve Block1e0659c2011-05-24 12:43:12 +0100286 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100287}
288
289
Ben Murdochb8e0da22011-05-16 14:20:40 +0100290void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100291 InputAt(0)->PrintTo(stream);
292 stream->Add("[%d]", slot_index());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100293}
294
295
Steve Block1e0659c2011-05-24 12:43:12 +0100296void LStoreContextSlot::PrintDataTo(StringStream* stream) {
297 InputAt(0)->PrintTo(stream);
298 stream->Add("[%d] <- ", slot_index());
299 InputAt(1)->PrintTo(stream);
300}
301
302
Ben Murdoch8b112d22011-06-08 16:22:53 +0100303void LInvokeFunction::PrintDataTo(StringStream* stream) {
304 stream->Add("= ");
305 InputAt(0)->PrintTo(stream);
306 stream->Add(" #%d / ", arity());
307}
308
309
Steve Block1e0659c2011-05-24 12:43:12 +0100310void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100311 stream->Add("[r2] #%d / ", arity());
312}
313
314
Steve Block1e0659c2011-05-24 12:43:12 +0100315void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100316 SmartPointer<char> name_string = name()->ToCString();
317 stream->Add("%s #%d / ", *name_string, arity());
318}
319
320
Steve Block1e0659c2011-05-24 12:43:12 +0100321void LCallGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100322 SmartPointer<char> name_string = name()->ToCString();
323 stream->Add("%s #%d / ", *name_string, arity());
324}
325
326
Steve Block1e0659c2011-05-24 12:43:12 +0100327void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100328 stream->Add("#%d / ", arity());
329}
330
331
Steve Block1e0659c2011-05-24 12:43:12 +0100332void LCallNew::PrintDataTo(StringStream* stream) {
333 stream->Add("= ");
334 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100335 stream->Add(" #%d / ", arity());
336}
337
338
Steve Block1e0659c2011-05-24 12:43:12 +0100339void LClassOfTest::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100340 stream->Add("= class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100341 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100342 stream->Add(", \"%o\")", *hydrogen()->class_name());
343}
344
345
Steve Block1e0659c2011-05-24 12:43:12 +0100346void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100347 arguments()->PrintTo(stream);
348
349 stream->Add(" length ");
350 length()->PrintTo(stream);
351
352 stream->Add(" index ");
353 index()->PrintTo(stream);
354}
355
356
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100357void LStoreNamedField::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100358 object()->PrintTo(stream);
359 stream->Add(".");
360 stream->Add(*String::cast(*name())->ToCString());
361 stream->Add(" <- ");
362 value()->PrintTo(stream);
363}
364
365
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100366void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
367 object()->PrintTo(stream);
368 stream->Add(".");
369 stream->Add(*String::cast(*name())->ToCString());
370 stream->Add(" <- ");
371 value()->PrintTo(stream);
372}
373
374
375void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100376 object()->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);
432 if (!goto_instr->include_stack_check() &&
433 label->IsRedundant() &&
434 !label->is_loop_header()) {
435 bool can_eliminate = true;
436 for (int i = first + 1; i < last && can_eliminate; ++i) {
437 LInstruction* cur = instructions()->at(i);
438 if (cur->IsGap()) {
439 LGap* gap = LGap::cast(cur);
440 if (!gap->IsRedundant()) {
441 can_eliminate = false;
442 }
443 } else {
444 can_eliminate = false;
445 }
446 }
447
448 if (can_eliminate) {
449 label->set_replacement(GetLabel(goto_instr->block_id()));
450 }
451 }
452 }
453 }
454}
455
456
Steve Block1e0659c2011-05-24 12:43:12 +0100457void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100458 LGap* gap = new LGap(block);
459 int index = -1;
460 if (instr->IsControl()) {
461 instructions_.Add(gap);
462 index = instructions_.length();
463 instructions_.Add(instr);
464 } else {
465 index = instructions_.length();
466 instructions_.Add(instr);
467 instructions_.Add(gap);
468 }
469 if (instr->HasPointerMap()) {
470 pointer_maps_.Add(instr->pointer_map());
471 instr->pointer_map()->set_lithium_position(index);
472 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100473}
474
475
476LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
477 return LConstantOperand::Create(constant->id());
478}
479
480
481int LChunk::GetParameterStackSlot(int index) const {
482 // The receiver is at index 0, the first parameter at index 1, so we
483 // shift all parameter indexes down by the number of parameters, and
484 // make sure they end up negative so they are distinguishable from
485 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100486 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100487 ASSERT(result < 0);
488 return result;
489}
490
491// A parameter relative to ebp in the arguments stub.
492int LChunk::ParameterAt(int index) {
493 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100494 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100495 kPointerSize;
496}
497
498
499LGap* LChunk::GetGapAt(int index) const {
500 return LGap::cast(instructions_[index]);
501}
502
503
504bool LChunk::IsGapAt(int index) const {
505 return instructions_[index]->IsGap();
506}
507
508
509int LChunk::NearestGapPos(int index) const {
510 while (!IsGapAt(index)) index--;
511 return index;
512}
513
514
515void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
516 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
517}
518
519
Ben Murdochb0fe1622011-05-05 13:52:32 +0100520Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
521 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
522}
523
524
525Representation LChunk::LookupLiteralRepresentation(
526 LConstantOperand* operand) const {
527 return graph_->LookupValue(operand->index())->representation();
528}
529
530
531LChunk* LChunkBuilder::Build() {
532 ASSERT(is_unused());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100533 chunk_ = new LChunk(info(), graph());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100534 HPhase phase("Building chunk", chunk_);
535 status_ = BUILDING;
536 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
537 for (int i = 0; i < blocks->length(); i++) {
538 HBasicBlock* next = NULL;
539 if (i < blocks->length() - 1) next = blocks->at(i + 1);
540 DoBasicBlock(blocks->at(i), next);
541 if (is_aborted()) return NULL;
542 }
543 status_ = DONE;
544 return chunk_;
545}
546
547
548void LChunkBuilder::Abort(const char* format, ...) {
549 if (FLAG_trace_bailout) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100550 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
551 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();
714 instr->set_environment(CreateEnvironment(hydrogen_env));
715 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
804LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
805 return AssignEnvironment(new LDeoptimize);
806}
807
808
809LInstruction* LChunkBuilder::DoBit(Token::Value op,
810 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100811 if (instr->representation().IsInteger32()) {
812 ASSERT(instr->left()->representation().IsInteger32());
813 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100814
Steve Block1e0659c2011-05-24 12:43:12 +0100815 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
816 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
817 return DefineSameAsFirst(new LBitI(op, left, right));
818 } else {
819 ASSERT(instr->representation().IsTagged());
820 ASSERT(instr->left()->representation().IsTagged());
821 ASSERT(instr->right()->representation().IsTagged());
822
823 LOperand* left = UseFixed(instr->left(), r1);
824 LOperand* right = UseFixed(instr->right(), r0);
825 LArithmeticT* result = new LArithmeticT(op, left, right);
826 return MarkAsCall(DefineFixed(result, r0), instr);
827 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100828}
829
830
831LInstruction* LChunkBuilder::DoShift(Token::Value op,
832 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100833 if (instr->representation().IsTagged()) {
834 ASSERT(instr->left()->representation().IsTagged());
835 ASSERT(instr->right()->representation().IsTagged());
836
837 LOperand* left = UseFixed(instr->left(), r1);
838 LOperand* right = UseFixed(instr->right(), r0);
839 LArithmeticT* result = new LArithmeticT(op, left, right);
840 return MarkAsCall(DefineFixed(result, r0), instr);
841 }
842
Ben Murdochb0fe1622011-05-05 13:52:32 +0100843 ASSERT(instr->representation().IsInteger32());
844 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
845 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
846 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
847
848 HValue* right_value = instr->OperandAt(1);
849 LOperand* right = NULL;
850 int constant_value = 0;
851 if (right_value->IsConstant()) {
852 HConstant* constant = HConstant::cast(right_value);
853 right = chunk_->DefineConstantOperand(constant);
854 constant_value = constant->Integer32Value() & 0x1f;
855 } else {
856 right = UseRegister(right_value);
857 }
858
859 // Shift operations can only deoptimize if we do a logical shift
860 // by 0 and the result cannot be truncated to int32.
861 bool can_deopt = (op == Token::SHR && constant_value == 0);
862 if (can_deopt) {
863 bool can_truncate = true;
864 for (int i = 0; i < instr->uses()->length(); i++) {
865 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
866 can_truncate = false;
867 break;
868 }
869 }
870 can_deopt = !can_truncate;
871 }
872
873 LInstruction* result =
874 DefineSameAsFirst(new LShiftI(op, left, right, can_deopt));
875 if (can_deopt) AssignEnvironment(result);
876 return result;
877}
878
879
880LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
881 HArithmeticBinaryOperation* instr) {
882 ASSERT(instr->representation().IsDouble());
883 ASSERT(instr->left()->representation().IsDouble());
884 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100885 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100886 LOperand* left = UseRegisterAtStart(instr->left());
887 LOperand* right = UseRegisterAtStart(instr->right());
888 LArithmeticD* result = new LArithmeticD(op, left, right);
889 return DefineSameAsFirst(result);
890}
891
892
893LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
894 HArithmeticBinaryOperation* instr) {
895 ASSERT(op == Token::ADD ||
896 op == Token::DIV ||
897 op == Token::MOD ||
898 op == Token::MUL ||
899 op == Token::SUB);
900 HValue* left = instr->left();
901 HValue* right = instr->right();
902 ASSERT(left->representation().IsTagged());
903 ASSERT(right->representation().IsTagged());
904 LOperand* left_operand = UseFixed(left, r1);
905 LOperand* right_operand = UseFixed(right, r0);
Steve Block1e0659c2011-05-24 12:43:12 +0100906 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100907 return MarkAsCall(DefineFixed(result, r0), instr);
908}
909
Steve Block1e0659c2011-05-24 12:43:12 +0100910
Ben Murdochb0fe1622011-05-05 13:52:32 +0100911void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
912 ASSERT(is_building());
913 current_block_ = block;
914 next_block_ = next_block;
915 if (block->IsStartBlock()) {
916 block->UpdateEnvironment(graph_->start_environment());
917 argument_count_ = 0;
918 } else if (block->predecessors()->length() == 1) {
919 // We have a single predecessor => copy environment and outgoing
920 // argument count from the predecessor.
921 ASSERT(block->phis()->length() == 0);
922 HBasicBlock* pred = block->predecessors()->at(0);
923 HEnvironment* last_environment = pred->last_environment();
924 ASSERT(last_environment != NULL);
925 // Only copy the environment, if it is later used again.
926 if (pred->end()->SecondSuccessor() == NULL) {
927 ASSERT(pred->end()->FirstSuccessor() == block);
928 } else {
929 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
930 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
931 last_environment = last_environment->Copy();
932 }
933 }
934 block->UpdateEnvironment(last_environment);
935 ASSERT(pred->argument_count() >= 0);
936 argument_count_ = pred->argument_count();
937 } else {
938 // We are at a state join => process phis.
939 HBasicBlock* pred = block->predecessors()->at(0);
940 // No need to copy the environment, it cannot be used later.
941 HEnvironment* last_environment = pred->last_environment();
942 for (int i = 0; i < block->phis()->length(); ++i) {
943 HPhi* phi = block->phis()->at(i);
944 last_environment->SetValueAt(phi->merged_index(), phi);
945 }
946 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
947 last_environment->SetValueAt(block->deleted_phis()->at(i),
948 graph_->GetConstantUndefined());
949 }
950 block->UpdateEnvironment(last_environment);
951 // Pick up the outgoing argument count of one of the predecessors.
952 argument_count_ = pred->argument_count();
953 }
954 HInstruction* current = block->first();
955 int start = chunk_->instructions()->length();
956 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100957 // Code for constants in registers is generated lazily.
958 if (!current->EmitAtUses()) {
959 VisitInstruction(current);
960 }
961 current = current->next();
962 }
963 int end = chunk_->instructions()->length() - 1;
964 if (end >= start) {
965 block->set_first_instruction_index(start);
966 block->set_last_instruction_index(end);
967 }
968 block->set_argument_count(argument_count_);
969 next_block_ = NULL;
970 current_block_ = NULL;
971}
972
973
974void LChunkBuilder::VisitInstruction(HInstruction* current) {
975 HInstruction* old_current = current_instruction_;
976 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100977 if (current->has_position()) position_ = current->position();
978 LInstruction* instr = current->CompileToLithium(this);
979
980 if (instr != NULL) {
981 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
982 instr = AssignPointerMap(instr);
983 }
984 if (FLAG_stress_environments && !instr->HasEnvironment()) {
985 instr = AssignEnvironment(instr);
986 }
Steve Block1e0659c2011-05-24 12:43:12 +0100987 if (current->IsTest() && !instr->IsGoto()) {
988 ASSERT(instr->IsControl());
989 HTest* test = HTest::cast(current);
990 instr->set_hydrogen_value(test->value());
991 HBasicBlock* first = test->FirstSuccessor();
992 HBasicBlock* second = test->SecondSuccessor();
993 ASSERT(first != NULL && second != NULL);
994 instr->SetBranchTargets(first->block_id(), second->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100995 } else {
996 instr->set_hydrogen_value(current);
997 }
998
Steve Block1e0659c2011-05-24 12:43:12 +0100999 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001000 }
1001 current_instruction_ = old_current;
1002}
1003
1004
Ben Murdochb0fe1622011-05-05 13:52:32 +01001005LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
1006 if (hydrogen_env == NULL) return NULL;
1007
1008 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1009 int ast_id = hydrogen_env->ast_id();
1010 ASSERT(ast_id != AstNode::kNoNumber);
Steve Block9fac8402011-05-12 15:51:54 +01001011 int value_count = hydrogen_env->length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001012 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1013 ast_id,
1014 hydrogen_env->parameter_count(),
1015 argument_count_,
1016 value_count,
1017 outer);
1018 int argument_index = 0;
1019 for (int i = 0; i < value_count; ++i) {
1020 HValue* value = hydrogen_env->values()->at(i);
1021 LOperand* op = NULL;
1022 if (value->IsArgumentsObject()) {
1023 op = NULL;
1024 } else if (value->IsPushArgument()) {
1025 op = new LArgument(argument_index++);
1026 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001027 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001028 }
1029 result->AddValue(op, value->representation());
1030 }
1031
1032 return result;
1033}
1034
1035
1036LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1037 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(),
1038 instr->include_stack_check());
1039 if (instr->include_stack_check()) result = AssignPointerMap(result);
1040 return result;
1041}
1042
1043
Steve Block1e0659c2011-05-24 12:43:12 +01001044LInstruction* LChunkBuilder::DoTest(HTest* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001045 HValue* v = instr->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001046 if (v->EmitAtUses()) {
1047 if (v->IsClassOfTest()) {
1048 HClassOfTest* compare = HClassOfTest::cast(v);
1049 ASSERT(compare->value()->representation().IsTagged());
1050
1051 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
Steve Block1e0659c2011-05-24 12:43:12 +01001052 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001053 } else if (v->IsCompare()) {
1054 HCompare* compare = HCompare::cast(v);
1055 Token::Value op = compare->token();
1056 HValue* left = compare->left();
1057 HValue* right = compare->right();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001058 Representation r = compare->GetInputRepresentation();
1059 if (r.IsInteger32()) {
1060 ASSERT(left->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001061 ASSERT(right->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001062 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001063 UseRegisterAtStart(right));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001064 } else if (r.IsDouble()) {
1065 ASSERT(left->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001066 ASSERT(right->representation().IsDouble());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001067 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001068 UseRegisterAtStart(right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001069 } else {
1070 ASSERT(left->representation().IsTagged());
1071 ASSERT(right->representation().IsTagged());
1072 bool reversed = op == Token::GT || op == Token::LTE;
1073 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1);
1074 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0);
1075 LInstruction* result = new LCmpTAndBranch(left_operand,
Steve Block1e0659c2011-05-24 12:43:12 +01001076 right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001077 return MarkAsCall(result, instr);
1078 }
1079 } else if (v->IsIsSmi()) {
1080 HIsSmi* compare = HIsSmi::cast(v);
1081 ASSERT(compare->value()->representation().IsTagged());
1082
Steve Block1e0659c2011-05-24 12:43:12 +01001083 return new LIsSmiAndBranch(Use(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001084 } else if (v->IsHasInstanceType()) {
1085 HHasInstanceType* compare = HHasInstanceType::cast(v);
1086 ASSERT(compare->value()->representation().IsTagged());
Steve Block1e0659c2011-05-24 12:43:12 +01001087 return new LHasInstanceTypeAndBranch(
1088 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001089 } else if (v->IsHasCachedArrayIndex()) {
1090 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1091 ASSERT(compare->value()->representation().IsTagged());
1092
1093 return new LHasCachedArrayIndexAndBranch(
Steve Block1e0659c2011-05-24 12:43:12 +01001094 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001095 } else if (v->IsIsNull()) {
1096 HIsNull* compare = HIsNull::cast(v);
1097 ASSERT(compare->value()->representation().IsTagged());
1098
Steve Block1e0659c2011-05-24 12:43:12 +01001099 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001100 } else if (v->IsIsObject()) {
1101 HIsObject* compare = HIsObject::cast(v);
1102 ASSERT(compare->value()->representation().IsTagged());
1103
Steve Block1e0659c2011-05-24 12:43:12 +01001104 LOperand* temp = TempRegister();
1105 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001106 } else if (v->IsCompareJSObjectEq()) {
1107 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1108 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
Steve Block1e0659c2011-05-24 12:43:12 +01001109 UseRegisterAtStart(compare->right()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001110 } else if (v->IsInstanceOf()) {
1111 HInstanceOf* instance_of = HInstanceOf::cast(v);
1112 LInstruction* result =
Steve Block1e0659c2011-05-24 12:43:12 +01001113 new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0),
1114 UseFixed(instance_of->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001115 return MarkAsCall(result, instr);
1116 } else if (v->IsTypeofIs()) {
1117 HTypeofIs* typeof_is = HTypeofIs::cast(v);
Steve Block1e0659c2011-05-24 12:43:12 +01001118 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1119 } else if (v->IsIsConstructCall()) {
1120 return new LIsConstructCallAndBranch(TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001121 } else {
1122 if (v->IsConstant()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001123 if (HConstant::cast(v)->ToBoolean()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001124 return new LGoto(instr->FirstSuccessor()->block_id());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001125 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001126 return new LGoto(instr->SecondSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001127 }
1128 }
1129 Abort("Undefined compare before branch");
1130 return NULL;
1131 }
1132 }
Steve Block1e0659c2011-05-24 12:43:12 +01001133 return new LBranch(UseRegisterAtStart(v));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001134}
1135
1136
Steve Block1e0659c2011-05-24 12:43:12 +01001137LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001138 ASSERT(instr->value()->representation().IsTagged());
1139 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block9fac8402011-05-12 15:51:54 +01001140 LOperand* temp = TempRegister();
1141 return new LCmpMapAndBranch(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001142}
1143
1144
1145LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001146 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001147}
1148
1149
1150LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1151 return DefineAsRegister(new LArgumentsElements);
1152}
1153
1154
1155LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001156 LInstanceOf* result =
Steve Block9fac8402011-05-12 15:51:54 +01001157 new LInstanceOf(UseFixed(instr->left(), r0),
1158 UseFixed(instr->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001159 return MarkAsCall(DefineFixed(result, r0), instr);
1160}
1161
1162
Ben Murdoch086aeea2011-05-13 15:57:08 +01001163LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1164 HInstanceOfKnownGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001165 LInstanceOfKnownGlobal* result =
1166 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001167 return MarkAsCall(DefineFixed(result, r0), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001168}
1169
1170
Ben Murdochb0fe1622011-05-05 13:52:32 +01001171LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1172 LOperand* function = UseFixed(instr->function(), r1);
1173 LOperand* receiver = UseFixed(instr->receiver(), r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001174 LOperand* length = UseFixed(instr->length(), r2);
1175 LOperand* elements = UseFixed(instr->elements(), r3);
1176 LApplyArguments* result = new LApplyArguments(function,
1177 receiver,
1178 length,
1179 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001180 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1181}
1182
1183
1184LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1185 ++argument_count_;
1186 LOperand* argument = Use(instr->argument());
1187 return new LPushArgument(argument);
1188}
1189
1190
Steve Block1e0659c2011-05-24 12:43:12 +01001191LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1192 return DefineAsRegister(new LContext);
1193}
1194
1195
1196LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1197 LOperand* context = UseRegisterAtStart(instr->value());
1198 return DefineAsRegister(new LOuterContext(context));
1199}
1200
1201
Ben Murdochb0fe1622011-05-05 13:52:32 +01001202LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001203 LOperand* context = UseRegisterAtStart(instr->value());
1204 return DefineAsRegister(new LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001205}
1206
1207
1208LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001209 LOperand* global_object = UseRegisterAtStart(instr->value());
1210 return DefineAsRegister(new LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001211}
1212
1213
1214LInstruction* LChunkBuilder::DoCallConstantFunction(
1215 HCallConstantFunction* instr) {
1216 argument_count_ -= instr->argument_count();
1217 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
1218}
1219
1220
Ben Murdoch8b112d22011-06-08 16:22:53 +01001221LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1222 LOperand* function = UseFixed(instr->function(), r1);
1223 argument_count_ -= instr->argument_count();
1224 LInvokeFunction* result = new LInvokeFunction(function);
1225 return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1226}
1227
1228
Ben Murdochb0fe1622011-05-05 13:52:32 +01001229LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1230 BuiltinFunctionId op = instr->op();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001231 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1232 LOperand* input = UseFixedDouble(instr->value(), d2);
1233 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
1234 return MarkAsCall(DefineFixedDouble(result, d2), instr);
1235 } else {
1236 LOperand* input = UseRegisterAtStart(instr->value());
1237 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1238 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1239 switch (op) {
1240 case kMathAbs:
1241 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1242 case kMathFloor:
1243 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1244 case kMathSqrt:
1245 return DefineSameAsFirst(result);
1246 case kMathRound:
1247 return AssignEnvironment(DefineAsRegister(result));
1248 case kMathPowHalf:
Steve Block44f0eee2011-05-26 01:26:41 +01001249 return DefineSameAsFirst(result);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001250 default:
1251 UNREACHABLE();
1252 return NULL;
1253 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001254 }
1255}
1256
1257
1258LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1259 ASSERT(instr->key()->representation().IsTagged());
1260 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001261 LOperand* key = UseFixed(instr->key(), r2);
1262 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001263}
1264
1265
1266LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1267 argument_count_ -= instr->argument_count();
1268 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
1269}
1270
1271
1272LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1273 argument_count_ -= instr->argument_count();
1274 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
1275}
1276
1277
1278LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1279 argument_count_ -= instr->argument_count();
1280 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
1281}
1282
1283
1284LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1285 LOperand* constructor = UseFixed(instr->constructor(), r1);
1286 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001287 LCallNew* result = new LCallNew(constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001288 return MarkAsCall(DefineFixed(result, r0), instr);
1289}
1290
1291
1292LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1293 argument_count_ -= instr->argument_count();
1294 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
1295}
1296
1297
1298LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1299 argument_count_ -= instr->argument_count();
1300 return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
1301}
1302
1303
1304LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1305 return DoShift(Token::SHR, instr);
1306}
1307
1308
1309LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1310 return DoShift(Token::SAR, instr);
1311}
1312
1313
1314LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1315 return DoShift(Token::SHL, instr);
1316}
1317
1318
1319LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1320 return DoBit(Token::BIT_AND, instr);
1321}
1322
1323
1324LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1325 ASSERT(instr->value()->representation().IsInteger32());
1326 ASSERT(instr->representation().IsInteger32());
1327 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value())));
1328}
1329
1330
1331LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1332 return DoBit(Token::BIT_OR, instr);
1333}
1334
1335
1336LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1337 return DoBit(Token::BIT_XOR, instr);
1338}
1339
1340
1341LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1342 if (instr->representation().IsDouble()) {
1343 return DoArithmeticD(Token::DIV, instr);
1344 } else if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001345 // TODO(1042) The fixed register allocation
Ben Murdoch8b112d22011-06-08 16:22:53 +01001346 // is needed because we call TypeRecordingBinaryOpStub from
Ben Murdochb8e0da22011-05-16 14:20:40 +01001347 // the generated code, which requires registers r0
1348 // and r1 to be used. We should remove that
1349 // when we provide a native implementation.
Steve Block1e0659c2011-05-24 12:43:12 +01001350 LOperand* dividend = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001351 LOperand* divisor = UseFixed(instr->right(), r1);
1352 return AssignEnvironment(AssignPointerMap(
Steve Block1e0659c2011-05-24 12:43:12 +01001353 DefineFixed(new LDivI(dividend, divisor), r0)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001354 } else {
1355 return DoArithmeticT(Token::DIV, instr);
1356 }
1357}
1358
1359
1360LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1361 if (instr->representation().IsInteger32()) {
1362 ASSERT(instr->left()->representation().IsInteger32());
1363 ASSERT(instr->right()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01001364
1365 LModI* mod;
1366 if (instr->HasPowerOf2Divisor()) {
1367 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1368 LOperand* value = UseRegisterAtStart(instr->left());
1369 mod = new LModI(value, UseOrConstant(instr->right()));
1370 } else {
1371 LOperand* dividend = UseRegister(instr->left());
1372 LOperand* divisor = UseRegisterAtStart(instr->right());
1373 mod = new LModI(dividend,
1374 divisor,
1375 TempRegister(),
1376 FixedTemp(d1),
1377 FixedTemp(d2));
1378 }
1379
1380 return AssignEnvironment(DefineSameAsFirst(mod));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001381 } else if (instr->representation().IsTagged()) {
1382 return DoArithmeticT(Token::MOD, instr);
1383 } else {
1384 ASSERT(instr->representation().IsDouble());
1385 // We call a C function for double modulo. It can't trigger a GC.
1386 // We need to use fixed result register for the call.
1387 // TODO(fschneider): Allow any register as input registers.
1388 LOperand* left = UseFixedDouble(instr->left(), d1);
1389 LOperand* right = UseFixedDouble(instr->right(), d2);
1390 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
1391 return MarkAsCall(DefineFixedDouble(result, d1), instr);
1392 }
1393}
1394
1395
1396LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1397 if (instr->representation().IsInteger32()) {
1398 ASSERT(instr->left()->representation().IsInteger32());
1399 ASSERT(instr->right()->representation().IsInteger32());
1400 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1401 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1402 LOperand* temp = NULL;
1403 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1404 temp = TempRegister();
1405 }
1406 LMulI* mul = new LMulI(left, right, temp);
1407 return AssignEnvironment(DefineSameAsFirst(mul));
1408 } else if (instr->representation().IsDouble()) {
1409 return DoArithmeticD(Token::MUL, instr);
1410 } else {
1411 return DoArithmeticT(Token::MUL, instr);
1412 }
1413}
1414
1415
1416LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1417 if (instr->representation().IsInteger32()) {
1418 ASSERT(instr->left()->representation().IsInteger32());
1419 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001420 LOperand* left = UseRegisterAtStart(instr->left());
1421 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001422 LSubI* sub = new LSubI(left, right);
1423 LInstruction* result = DefineSameAsFirst(sub);
1424 if (instr->CheckFlag(HValue::kCanOverflow)) {
1425 result = AssignEnvironment(result);
1426 }
1427 return result;
1428 } else if (instr->representation().IsDouble()) {
1429 return DoArithmeticD(Token::SUB, instr);
1430 } else {
1431 return DoArithmeticT(Token::SUB, instr);
1432 }
1433}
1434
1435
1436LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1437 if (instr->representation().IsInteger32()) {
1438 ASSERT(instr->left()->representation().IsInteger32());
1439 ASSERT(instr->right()->representation().IsInteger32());
1440 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1441 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1442 LAddI* add = new LAddI(left, right);
1443 LInstruction* result = DefineSameAsFirst(add);
1444 if (instr->CheckFlag(HValue::kCanOverflow)) {
1445 result = AssignEnvironment(result);
1446 }
1447 return result;
1448 } else if (instr->representation().IsDouble()) {
1449 return DoArithmeticD(Token::ADD, instr);
1450 } else {
1451 ASSERT(instr->representation().IsTagged());
1452 return DoArithmeticT(Token::ADD, instr);
1453 }
1454}
1455
1456
1457LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001458 ASSERT(instr->representation().IsDouble());
1459 // We call a C function for double power. It can't trigger a GC.
1460 // We need to use fixed result register for the call.
1461 Representation exponent_type = instr->right()->representation();
1462 ASSERT(instr->left()->representation().IsDouble());
1463 LOperand* left = UseFixedDouble(instr->left(), d1);
1464 LOperand* right = exponent_type.IsDouble() ?
1465 UseFixedDouble(instr->right(), d2) :
1466 UseFixed(instr->right(), r0);
1467 LPower* result = new LPower(left, right);
1468 return MarkAsCall(DefineFixedDouble(result, d3),
1469 instr,
1470 CAN_DEOPTIMIZE_EAGERLY);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001471}
1472
1473
1474LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1475 Token::Value op = instr->token();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001476 Representation r = instr->GetInputRepresentation();
1477 if (r.IsInteger32()) {
1478 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001479 ASSERT(instr->right()->representation().IsInteger32());
1480 LOperand* left = UseRegisterAtStart(instr->left());
Steve Block1e0659c2011-05-24 12:43:12 +01001481 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001482 return DefineAsRegister(new LCmpID(left, right));
1483 } else if (r.IsDouble()) {
1484 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001485 ASSERT(instr->right()->representation().IsDouble());
1486 LOperand* left = UseRegisterAtStart(instr->left());
1487 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001488 return DefineAsRegister(new LCmpID(left, right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001489 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001490 ASSERT(instr->left()->representation().IsTagged());
1491 ASSERT(instr->right()->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001492 bool reversed = (op == Token::GT || op == Token::LTE);
1493 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1494 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001495 LCmpT* result = new LCmpT(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001496 return MarkAsCall(DefineFixed(result, r0), instr);
1497 }
1498}
1499
1500
1501LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1502 HCompareJSObjectEq* instr) {
1503 LOperand* left = UseRegisterAtStart(instr->left());
1504 LOperand* right = UseRegisterAtStart(instr->right());
Steve Block1e0659c2011-05-24 12:43:12 +01001505 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001506 return DefineAsRegister(result);
1507}
1508
1509
1510LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1511 ASSERT(instr->value()->representation().IsTagged());
1512 LOperand* value = UseRegisterAtStart(instr->value());
1513
Ben Murdochb8e0da22011-05-16 14:20:40 +01001514 return DefineAsRegister(new LIsNull(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001515}
1516
1517
1518LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1519 ASSERT(instr->value()->representation().IsTagged());
1520 LOperand* value = UseRegisterAtStart(instr->value());
1521
Steve Block1e0659c2011-05-24 12:43:12 +01001522 return DefineAsRegister(new LIsObject(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001523}
1524
1525
1526LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1527 ASSERT(instr->value()->representation().IsTagged());
1528 LOperand* value = UseAtStart(instr->value());
1529
1530 return DefineAsRegister(new LIsSmi(value));
1531}
1532
1533
1534LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1535 ASSERT(instr->value()->representation().IsTagged());
1536 LOperand* value = UseRegisterAtStart(instr->value());
1537
1538 return DefineAsRegister(new LHasInstanceType(value));
1539}
1540
1541
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001542LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1543 HGetCachedArrayIndex* instr) {
1544 ASSERT(instr->value()->representation().IsTagged());
1545 LOperand* value = UseRegisterAtStart(instr->value());
1546
1547 return DefineAsRegister(new LGetCachedArrayIndex(value));
1548}
1549
1550
Ben Murdochb0fe1622011-05-05 13:52:32 +01001551LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1552 HHasCachedArrayIndex* instr) {
1553 ASSERT(instr->value()->representation().IsTagged());
1554 LOperand* value = UseRegister(instr->value());
1555
1556 return DefineAsRegister(new LHasCachedArrayIndex(value));
1557}
1558
1559
1560LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1561 ASSERT(instr->value()->representation().IsTagged());
1562 LOperand* value = UseTempRegister(instr->value());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001563 return DefineSameAsFirst(new LClassOfTest(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001564}
1565
1566
Steve Block9fac8402011-05-12 15:51:54 +01001567LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1568 LOperand* array = UseRegisterAtStart(instr->value());
1569 return DefineAsRegister(new LJSArrayLength(array));
1570}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001571
Ben Murdochb0fe1622011-05-05 13:52:32 +01001572
Steve Block44f0eee2011-05-26 01:26:41 +01001573LInstruction* LChunkBuilder::DoExternalArrayLength(
1574 HExternalArrayLength* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001575 LOperand* array = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001576 return DefineAsRegister(new LExternalArrayLength(array));
Steve Block1e0659c2011-05-24 12:43:12 +01001577}
1578
1579
Steve Block9fac8402011-05-12 15:51:54 +01001580LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1581 LOperand* array = UseRegisterAtStart(instr->value());
1582 return DefineAsRegister(new LFixedArrayLength(array));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001583}
1584
1585
1586LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1587 LOperand* object = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001588 LValueOf* result = new LValueOf(object, TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001589 return AssignEnvironment(DefineSameAsFirst(result));
1590}
1591
1592
1593LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1594 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001595 UseRegister(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001596}
1597
1598
Steve Block1e0659c2011-05-24 12:43:12 +01001599LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1600 // The control instruction marking the end of a block that completed
1601 // abruptly (e.g., threw an exception). There is nothing specific to do.
1602 return NULL;
1603}
1604
1605
Ben Murdochb0fe1622011-05-05 13:52:32 +01001606LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1607 LOperand* value = UseFixed(instr->value(), r0);
1608 return MarkAsCall(new LThrow(value), instr);
1609}
1610
1611
1612LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1613 Representation from = instr->from();
1614 Representation to = instr->to();
1615 if (from.IsTagged()) {
1616 if (to.IsDouble()) {
1617 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001618 LNumberUntagD* res = new LNumberUntagD(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001619 return AssignEnvironment(DefineAsRegister(res));
1620 } else {
1621 ASSERT(to.IsInteger32());
1622 LOperand* value = UseRegister(instr->value());
1623 bool needs_check = !instr->value()->type().IsSmi();
1624 LInstruction* res = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001625 if (!needs_check) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001626 res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
Steve Block44f0eee2011-05-26 01:26:41 +01001627 } else {
1628 LOperand* temp1 = TempRegister();
1629 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1630 : NULL;
1631 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
1632 : NULL;
1633 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001634 res = AssignEnvironment(res);
1635 }
1636 return res;
1637 }
1638 } else if (from.IsDouble()) {
1639 if (to.IsTagged()) {
1640 LOperand* value = UseRegister(instr->value());
1641 LOperand* temp1 = TempRegister();
1642 LOperand* temp2 = TempRegister();
1643
1644 // Make sure that the temp and result_temp registers are
1645 // different.
1646 LUnallocated* result_temp = TempRegister();
Steve Block1e0659c2011-05-24 12:43:12 +01001647 LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001648 Define(result, result_temp);
1649 return AssignPointerMap(result);
1650 } else {
1651 ASSERT(to.IsInteger32());
1652 LOperand* value = UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001653 LDoubleToI* res =
1654 new LDoubleToI(value,
1655 TempRegister(),
1656 instr->CanTruncateToInt32() ? TempRegister() : NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001657 return AssignEnvironment(DefineAsRegister(res));
1658 }
1659 } else if (from.IsInteger32()) {
1660 if (to.IsTagged()) {
1661 HValue* val = instr->value();
1662 LOperand* value = UseRegister(val);
1663 if (val->HasRange() && val->range()->IsInSmiRange()) {
1664 return DefineSameAsFirst(new LSmiTag(value));
1665 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001666 LNumberTagI* result = new LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001667 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1668 }
1669 } else {
1670 ASSERT(to.IsDouble());
1671 LOperand* value = Use(instr->value());
1672 return DefineAsRegister(new LInteger32ToDouble(value));
1673 }
1674 }
1675 UNREACHABLE();
1676 return NULL;
1677}
1678
1679
1680LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1681 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001682 return AssignEnvironment(new LCheckNonSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001683}
1684
1685
1686LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1687 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001688 LInstruction* result = new LCheckInstanceType(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001689 return AssignEnvironment(result);
1690}
1691
1692
1693LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001694 LOperand* temp1 = TempRegister();
1695 LOperand* temp2 = TempRegister();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001696 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001697 return AssignEnvironment(result);
1698}
1699
1700
1701LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1702 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001703 return AssignEnvironment(new LCheckSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001704}
1705
1706
1707LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1708 LOperand* value = UseRegisterAtStart(instr->value());
1709 return AssignEnvironment(new LCheckFunction(value));
1710}
1711
1712
1713LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1714 LOperand* value = UseRegisterAtStart(instr->value());
1715 LInstruction* result = new LCheckMap(value);
1716 return AssignEnvironment(result);
1717}
1718
1719
1720LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1721 return new LReturn(UseFixed(instr->value(), r0));
1722}
1723
1724
1725LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1726 Representation r = instr->representation();
1727 if (r.IsInteger32()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001728 return DefineAsRegister(new LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001729 } else if (r.IsDouble()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001730 return DefineAsRegister(new LConstantD);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001731 } else if (r.IsTagged()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001732 return DefineAsRegister(new LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001733 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001734 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001735 return NULL;
1736 }
1737}
1738
1739
Ben Murdoch8b112d22011-06-08 16:22:53 +01001740LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1741 LLoadGlobalCell* result = new LLoadGlobalCell;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001742 return instr->check_hole_value()
1743 ? AssignEnvironment(DefineAsRegister(result))
1744 : DefineAsRegister(result);
1745}
1746
1747
Ben Murdoch8b112d22011-06-08 16:22:53 +01001748LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1749 LOperand* global_object = UseFixed(instr->global_object(), r0);
1750 LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
1751 return MarkAsCall(DefineFixed(result, r0), instr);
1752}
1753
1754
1755LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001756 if (instr->check_hole_value()) {
1757 LOperand* temp = TempRegister();
1758 LOperand* value = UseRegister(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001759 return AssignEnvironment(new LStoreGlobalCell(value, temp));
Steve Block1e0659c2011-05-24 12:43:12 +01001760 } else {
1761 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001762 return new LStoreGlobalCell(value, NULL);
Steve Block1e0659c2011-05-24 12:43:12 +01001763 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001764}
1765
1766
Ben Murdoch8b112d22011-06-08 16:22:53 +01001767LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1768 LOperand* global_object = UseFixed(instr->global_object(), r1);
1769 LOperand* value = UseFixed(instr->value(), r0);
1770 LStoreGlobalGeneric* result =
1771 new LStoreGlobalGeneric(global_object, value);
1772 return MarkAsCall(result, instr);
1773}
1774
1775
Ben Murdochb8e0da22011-05-16 14:20:40 +01001776LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001777 LOperand* context = UseRegisterAtStart(instr->value());
1778 return DefineAsRegister(new LLoadContextSlot(context));
1779}
1780
1781
1782LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001783 LOperand* context;
Steve Block1e0659c2011-05-24 12:43:12 +01001784 LOperand* value;
1785 if (instr->NeedsWriteBarrier()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001786 context = UseTempRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001787 value = UseTempRegister(instr->value());
1788 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001789 context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001790 value = UseRegister(instr->value());
1791 }
1792 return new LStoreContextSlot(context, value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001793}
1794
1795
Ben Murdochb0fe1622011-05-05 13:52:32 +01001796LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1797 return DefineAsRegister(
1798 new LLoadNamedField(UseRegisterAtStart(instr->object())));
1799}
1800
1801
Steve Block44f0eee2011-05-26 01:26:41 +01001802LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1803 HLoadNamedFieldPolymorphic* instr) {
1804 ASSERT(instr->representation().IsTagged());
1805 if (instr->need_generic()) {
1806 LOperand* obj = UseFixed(instr->object(), r0);
1807 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1808 return MarkAsCall(DefineFixed(result, r0), instr);
1809 } else {
1810 LOperand* obj = UseRegisterAtStart(instr->object());
1811 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1812 return AssignEnvironment(DefineAsRegister(result));
1813 }
1814}
1815
1816
Ben Murdochb0fe1622011-05-05 13:52:32 +01001817LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1818 LOperand* object = UseFixed(instr->object(), r0);
1819 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
1820 return MarkAsCall(result, instr);
1821}
1822
1823
Steve Block9fac8402011-05-12 15:51:54 +01001824LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1825 HLoadFunctionPrototype* instr) {
1826 return AssignEnvironment(DefineAsRegister(
1827 new LLoadFunctionPrototype(UseRegister(instr->function()))));
1828}
1829
1830
Ben Murdochb0fe1622011-05-05 13:52:32 +01001831LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1832 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001833 return DefineAsRegister(new LLoadElements(input));
1834}
1835
1836
Steve Block44f0eee2011-05-26 01:26:41 +01001837LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1838 HLoadExternalArrayPointer* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001839 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001840 return DefineAsRegister(new LLoadExternalArrayPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001841}
1842
1843
1844LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1845 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001846 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001847 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001848 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001849 LOperand* key = UseRegisterAtStart(instr->key());
Steve Block1e0659c2011-05-24 12:43:12 +01001850 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001851 return AssignEnvironment(DefineSameAsFirst(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001852}
1853
1854
Steve Block44f0eee2011-05-26 01:26:41 +01001855LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1856 HLoadKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001857 ExternalArrayType array_type = instr->array_type();
1858 Representation representation(instr->representation());
1859 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
1860 (representation.IsDouble() && array_type == kExternalFloatArray));
Steve Block1e0659c2011-05-24 12:43:12 +01001861 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001862 LOperand* external_pointer = UseRegister(instr->external_pointer());
1863 LOperand* key = UseRegister(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001864 LLoadKeyedSpecializedArrayElement* result =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001865 new LLoadKeyedSpecializedArrayElement(external_pointer, key);
1866 LInstruction* load_instr = DefineAsRegister(result);
1867 // An unsigned int array load might overflow and cause a deopt, make sure it
1868 // has an environment.
1869 return (array_type == kExternalUnsignedIntArray) ?
1870 AssignEnvironment(load_instr) : load_instr;
Steve Block1e0659c2011-05-24 12:43:12 +01001871}
1872
1873
Ben Murdochb0fe1622011-05-05 13:52:32 +01001874LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1875 LOperand* object = UseFixed(instr->object(), r1);
1876 LOperand* key = UseFixed(instr->key(), r0);
1877
1878 LInstruction* result =
1879 DefineFixed(new LLoadKeyedGeneric(object, key), r0);
1880 return MarkAsCall(result, instr);
1881}
1882
1883
1884LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1885 HStoreKeyedFastElement* instr) {
1886 bool needs_write_barrier = instr->NeedsWriteBarrier();
1887 ASSERT(instr->value()->representation().IsTagged());
1888 ASSERT(instr->object()->representation().IsTagged());
1889 ASSERT(instr->key()->representation().IsInteger32());
1890
1891 LOperand* obj = UseTempRegister(instr->object());
1892 LOperand* val = needs_write_barrier
1893 ? UseTempRegister(instr->value())
1894 : UseRegisterAtStart(instr->value());
1895 LOperand* key = needs_write_barrier
1896 ? UseTempRegister(instr->key())
1897 : UseRegisterOrConstantAtStart(instr->key());
1898
1899 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1900}
1901
1902
Steve Block44f0eee2011-05-26 01:26:41 +01001903LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1904 HStoreKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001905 Representation representation(instr->value()->representation());
1906 ExternalArrayType array_type = instr->array_type();
1907 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
1908 (representation.IsDouble() && array_type == kExternalFloatArray));
Steve Block44f0eee2011-05-26 01:26:41 +01001909 ASSERT(instr->external_pointer()->representation().IsExternal());
1910 ASSERT(instr->key()->representation().IsInteger32());
1911
1912 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001913 bool val_is_temp_register = array_type == kExternalPixelArray ||
1914 array_type == kExternalFloatArray;
1915 LOperand* val = val_is_temp_register
1916 ? UseTempRegister(instr->value())
1917 : UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001918 LOperand* key = UseRegister(instr->key());
1919
1920 return new LStoreKeyedSpecializedArrayElement(external_pointer,
1921 key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01001922 val);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001923}
1924
1925
Ben Murdochb0fe1622011-05-05 13:52:32 +01001926LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1927 LOperand* obj = UseFixed(instr->object(), r2);
1928 LOperand* key = UseFixed(instr->key(), r1);
1929 LOperand* val = UseFixed(instr->value(), r0);
1930
1931 ASSERT(instr->object()->representation().IsTagged());
1932 ASSERT(instr->key()->representation().IsTagged());
1933 ASSERT(instr->value()->representation().IsTagged());
1934
1935 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1936}
1937
1938
1939LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001940 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001941
1942 LOperand* obj = needs_write_barrier
1943 ? UseTempRegister(instr->object())
1944 : UseRegisterAtStart(instr->object());
1945
1946 LOperand* val = needs_write_barrier
1947 ? UseTempRegister(instr->value())
1948 : UseRegister(instr->value());
1949
Ben Murdochb8e0da22011-05-16 14:20:40 +01001950 return new LStoreNamedField(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001951}
1952
1953
1954LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1955 LOperand* obj = UseFixed(instr->object(), r1);
1956 LOperand* val = UseFixed(instr->value(), r0);
1957
Ben Murdochb8e0da22011-05-16 14:20:40 +01001958 LInstruction* result = new LStoreNamedGeneric(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001959 return MarkAsCall(result, instr);
1960}
1961
1962
Ben Murdoch8b112d22011-06-08 16:22:53 +01001963LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
1964 LOperand* left = UseRegisterAtStart(instr->left());
1965 LOperand* right = UseRegisterAtStart(instr->right());
1966 return MarkAsCall(DefineFixed(new LStringAdd(left, right), r0), instr);
1967}
1968
1969
Steve Block1e0659c2011-05-24 12:43:12 +01001970LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1971 LOperand* string = UseRegister(instr->string());
1972 LOperand* index = UseRegisterOrConstant(instr->index());
1973 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
1974 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1975}
1976
1977
Steve Block44f0eee2011-05-26 01:26:41 +01001978LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
1979 LOperand* char_code = UseRegister(instr->value());
1980 LStringCharFromCode* result = new LStringCharFromCode(char_code);
1981 return AssignPointerMap(DefineAsRegister(result));
1982}
1983
1984
Steve Block1e0659c2011-05-24 12:43:12 +01001985LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1986 LOperand* string = UseRegisterAtStart(instr->value());
1987 return DefineAsRegister(new LStringLength(string));
1988}
1989
1990
Ben Murdochb0fe1622011-05-05 13:52:32 +01001991LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1992 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
1993}
1994
1995
1996LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1997 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
1998}
1999
2000
2001LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
2002 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
2003}
2004
2005
2006LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
2007 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
2008}
2009
2010
2011LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002012 LOperand* object = UseFixed(instr->object(), r0);
2013 LOperand* key = UseFixed(instr->key(), r1);
2014 LDeleteProperty* result = new LDeleteProperty(object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002015 return MarkAsCall(DefineFixed(result, r0), instr);
2016}
2017
2018
2019LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
2020 allocator_->MarkAsOsrEntry();
2021 current_block_->last_environment()->set_ast_id(instr->ast_id());
2022 return AssignEnvironment(new LOsrEntry);
2023}
2024
2025
2026LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2027 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2028 return DefineAsSpilled(new LParameter, spill_index);
2029}
2030
2031
2032LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2033 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
2034 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
2035}
2036
2037
2038LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2039 argument_count_ -= instr->argument_count();
2040 return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
2041}
2042
2043
2044LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002045 // There are no real uses of the arguments object.
2046 // arguments.length and element access are supported directly on
2047 // stack arguments, and any real arguments object use causes a bailout.
2048 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002049 return NULL;
2050}
2051
2052
2053LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2054 LOperand* arguments = UseRegister(instr->arguments());
2055 LOperand* length = UseTempRegister(instr->length());
Ben Murdoch086aeea2011-05-13 15:57:08 +01002056 LOperand* index = UseRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01002057 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2058 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002059}
2060
2061
Steve Block44f0eee2011-05-26 01:26:41 +01002062LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2063 LOperand* object = UseFixed(instr->value(), r0);
2064 LToFastProperties* result = new LToFastProperties(object);
2065 return MarkAsCall(DefineFixed(result, r0), instr);
2066}
2067
2068
Ben Murdochb0fe1622011-05-05 13:52:32 +01002069LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002070 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002071 return MarkAsCall(DefineFixed(result, r0), instr);
2072}
2073
2074
2075LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
2076 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
2077}
2078
Steve Block1e0659c2011-05-24 12:43:12 +01002079
2080LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
2081 return DefineAsRegister(new LIsConstructCall());
2082}
2083
2084
Ben Murdochb0fe1622011-05-05 13:52:32 +01002085LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2086 HEnvironment* env = current_block_->last_environment();
2087 ASSERT(env != NULL);
2088
2089 env->set_ast_id(instr->ast_id());
2090
2091 env->Drop(instr->pop_count());
2092 for (int i = 0; i < instr->values()->length(); ++i) {
2093 HValue* value = instr->values()->at(i);
2094 if (instr->HasAssignedIndexAt(i)) {
2095 env->Bind(instr->GetAssignedIndexAt(i), value);
2096 } else {
2097 env->Push(value);
2098 }
2099 }
2100
Ben Murdochb0fe1622011-05-05 13:52:32 +01002101 // If there is an instruction pending deoptimization environment create a
2102 // lazy bailout instruction to capture the environment.
2103 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2104 LInstruction* result = new LLazyBailout;
2105 result = AssignEnvironment(result);
Steve Block1e0659c2011-05-24 12:43:12 +01002106 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002107 set_deoptimization_environment(result->environment());
2108 ClearInstructionPendingDeoptimizationEnvironment();
2109 return result;
2110 }
2111
2112 return NULL;
2113}
2114
2115
2116LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2117 return MarkAsCall(new LStackCheck, instr);
2118}
2119
2120
2121LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2122 HEnvironment* outer = current_block_->last_environment();
2123 HConstant* undefined = graph()->GetConstantUndefined();
2124 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2125 instr->function(),
2126 false,
2127 undefined);
2128 current_block_->UpdateEnvironment(inner);
2129 chunk_->AddInlinedClosure(instr->closure());
2130 return NULL;
2131}
2132
2133
2134LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2135 HEnvironment* outer = current_block_->last_environment()->outer();
2136 current_block_->UpdateEnvironment(outer);
2137 return NULL;
2138}
2139
2140
Ben Murdochb0fe1622011-05-05 13:52:32 +01002141} } // namespace v8::internal