blob: efd226eae5aca180556ce76b4610c01d1203f5e1 [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() {
Steve Block053d10c2011-06-13 19:13:29 +010064 // Call instructions can use only fixed registers as
65 // temporaries and outputs because all registers
66 // are blocked by the calling convention.
67 // Inputs must use a fixed register.
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()) {
Steve Block053d10c2011-06-13 19:13:29 +010072 LOperand* operand = it.Next();
73 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
74 !LUnallocated::cast(operand)->HasRegisterPolicy());
Steve Block1e0659c2011-05-24 12:43:12 +010075 }
76 for (TempIterator it(this); it.HasNext(); it.Advance()) {
Steve Block053d10c2011-06-13 19:13:29 +010077 LOperand* operand = it.Next();
78 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
79 !LUnallocated::cast(operand)->HasRegisterPolicy());
Steve Block1e0659c2011-05-24 12:43:12 +010080 }
81}
82#endif
83
84
Ben Murdochb0fe1622011-05-05 13:52:32 +010085void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
86 LOperand* spill_operand) {
87 ASSERT(spill_operand->IsDoubleStackSlot());
88 ASSERT(double_register_spills_[allocation_index] == NULL);
89 double_register_spills_[allocation_index] = spill_operand;
90}
91
92
Steve Block1e0659c2011-05-24 12:43:12 +010093void LInstruction::PrintTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +010094 stream->Add("%s ", this->Mnemonic());
Steve Block1e0659c2011-05-24 12:43:12 +010095
96 PrintOutputOperandTo(stream);
97
Ben Murdochb0fe1622011-05-05 13:52:32 +010098 PrintDataTo(stream);
99
100 if (HasEnvironment()) {
101 stream->Add(" ");
102 environment()->PrintTo(stream);
103 }
104
105 if (HasPointerMap()) {
106 stream->Add(" ");
107 pointer_map()->PrintTo(stream);
108 }
109}
110
111
Steve Block1e0659c2011-05-24 12:43:12 +0100112template<int R, int I, int T>
113void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
114 stream->Add("= ");
115 inputs_.PrintOperandsTo(stream);
116}
117
118
119template<int R, int I, int T>
120void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
121 results_.PrintOperandsTo(stream);
122}
123
124
125template<typename T, int N>
126void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
127 for (int i = 0; i < N; i++) {
128 if (i > 0) stream->Add(" ");
129 elems_[i]->PrintTo(stream);
130 }
131}
132
133
134void LLabel::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100135 LGap::PrintDataTo(stream);
136 LLabel* rep = replacement();
137 if (rep != NULL) {
138 stream->Add(" Dead block replaced with B%d", rep->block_id());
139 }
140}
141
142
Ben Murdochb0fe1622011-05-05 13:52:32 +0100143bool LGap::IsRedundant() const {
144 for (int i = 0; i < 4; i++) {
145 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
146 return false;
147 }
148 }
149
150 return true;
151}
152
153
154void LGap::PrintDataTo(StringStream* stream) const {
155 for (int i = 0; i < 4; i++) {
156 stream->Add("(");
157 if (parallel_moves_[i] != NULL) {
158 parallel_moves_[i]->PrintDataTo(stream);
159 }
160 stream->Add(") ");
161 }
162}
163
164
165const char* LArithmeticD::Mnemonic() const {
166 switch (op()) {
167 case Token::ADD: return "add-d";
168 case Token::SUB: return "sub-d";
169 case Token::MUL: return "mul-d";
170 case Token::DIV: return "div-d";
171 case Token::MOD: return "mod-d";
172 default:
173 UNREACHABLE();
174 return NULL;
175 }
176}
177
178
179const char* LArithmeticT::Mnemonic() const {
180 switch (op()) {
181 case Token::ADD: return "add-t";
182 case Token::SUB: return "sub-t";
183 case Token::MUL: return "mul-t";
184 case Token::MOD: return "mod-t";
185 case Token::DIV: return "div-t";
Steve Block1e0659c2011-05-24 12:43:12 +0100186 case Token::BIT_AND: return "bit-and-t";
187 case Token::BIT_OR: return "bit-or-t";
188 case Token::BIT_XOR: return "bit-xor-t";
189 case Token::SHL: return "shl-t";
190 case Token::SAR: return "sar-t";
191 case Token::SHR: return "shr-t";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100192 default:
193 UNREACHABLE();
194 return NULL;
195 }
196}
197
198
Steve Block1e0659c2011-05-24 12:43:12 +0100199void LGoto::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100200 stream->Add("B%d", block_id());
201}
202
203
Steve Block1e0659c2011-05-24 12:43:12 +0100204void LBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100205 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
Steve Block1e0659c2011-05-24 12:43:12 +0100206 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100207}
208
209
Steve Block1e0659c2011-05-24 12:43:12 +0100210void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100211 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100212 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100213 stream->Add(" %s ", Token::String(op()));
Steve Block1e0659c2011-05-24 12:43:12 +0100214 InputAt(1)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100215 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
216}
217
218
Steve Block1e0659c2011-05-24 12:43:12 +0100219void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100221 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100222 stream->Add(is_strict() ? " === null" : " == null");
223 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
224}
225
226
Steve Block1e0659c2011-05-24 12:43:12 +0100227void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100228 stream->Add("if is_object(");
Steve Block1e0659c2011-05-24 12:43:12 +0100229 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100230 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
231}
232
233
Steve Block1e0659c2011-05-24 12:43:12 +0100234void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235 stream->Add("if is_smi(");
Steve Block1e0659c2011-05-24 12:43:12 +0100236 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100237 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
238}
239
240
Steve Block1e0659c2011-05-24 12:43:12 +0100241void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100242 stream->Add("if has_instance_type(");
Steve Block1e0659c2011-05-24 12:43:12 +0100243 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100244 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
245}
246
247
Steve Block1e0659c2011-05-24 12:43:12 +0100248void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100249 stream->Add("if has_cached_array_index(");
Steve Block1e0659c2011-05-24 12:43:12 +0100250 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100251 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
252}
253
254
Steve Block1e0659c2011-05-24 12:43:12 +0100255void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100256 stream->Add("if class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100257 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100258 stream->Add(", \"%o\") then B%d else B%d",
259 *hydrogen()->class_name(),
260 true_block_id(),
261 false_block_id());
262}
263
264
Steve Block1e0659c2011-05-24 12:43:12 +0100265void LTypeofIs::PrintDataTo(StringStream* stream) {
266 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100267 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
268}
269
270
Steve Block1e0659c2011-05-24 12:43:12 +0100271void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100272 stream->Add("if typeof ");
Steve Block1e0659c2011-05-24 12:43:12 +0100273 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100274 stream->Add(" == \"%s\" then B%d else B%d",
275 *hydrogen()->type_literal()->ToCString(),
276 true_block_id(), false_block_id());
277}
278
279
Steve Block1e0659c2011-05-24 12:43:12 +0100280void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100281 stream->Add("#%d / ", arity());
282}
283
284
Steve Block1e0659c2011-05-24 12:43:12 +0100285void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100286 stream->Add("/%s ", hydrogen()->OpName());
Steve Block1e0659c2011-05-24 12:43:12 +0100287 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100288}
289
290
Ben Murdochb8e0da22011-05-16 14:20:40 +0100291void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100292 InputAt(0)->PrintTo(stream);
293 stream->Add("[%d]", slot_index());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100294}
295
296
Steve Block1e0659c2011-05-24 12:43:12 +0100297void LStoreContextSlot::PrintDataTo(StringStream* stream) {
298 InputAt(0)->PrintTo(stream);
299 stream->Add("[%d] <- ", slot_index());
300 InputAt(1)->PrintTo(stream);
301}
302
303
304void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100305 stream->Add("[r2] #%d / ", arity());
306}
307
308
Steve Block1e0659c2011-05-24 12:43:12 +0100309void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100310 SmartPointer<char> name_string = name()->ToCString();
311 stream->Add("%s #%d / ", *name_string, arity());
312}
313
314
Steve Block1e0659c2011-05-24 12:43:12 +0100315void LCallGlobal::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 LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100322 stream->Add("#%d / ", arity());
323}
324
325
Steve Block1e0659c2011-05-24 12:43:12 +0100326void LCallNew::PrintDataTo(StringStream* stream) {
327 stream->Add("= ");
328 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100329 stream->Add(" #%d / ", arity());
330}
331
332
Steve Block1e0659c2011-05-24 12:43:12 +0100333void LClassOfTest::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100334 stream->Add("= class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100335 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100336 stream->Add(", \"%o\")", *hydrogen()->class_name());
337}
338
339
Steve Block1e0659c2011-05-24 12:43:12 +0100340void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100341 arguments()->PrintTo(stream);
342
343 stream->Add(" length ");
344 length()->PrintTo(stream);
345
346 stream->Add(" index ");
347 index()->PrintTo(stream);
348}
349
350
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100351void LStoreNamedField::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100352 object()->PrintTo(stream);
353 stream->Add(".");
354 stream->Add(*String::cast(*name())->ToCString());
355 stream->Add(" <- ");
356 value()->PrintTo(stream);
357}
358
359
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100360void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
361 object()->PrintTo(stream);
362 stream->Add(".");
363 stream->Add(*String::cast(*name())->ToCString());
364 stream->Add(" <- ");
365 value()->PrintTo(stream);
366}
367
368
369void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100370 object()->PrintTo(stream);
371 stream->Add("[");
372 key()->PrintTo(stream);
373 stream->Add("] <- ");
374 value()->PrintTo(stream);
375}
376
377
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100378void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
379 object()->PrintTo(stream);
380 stream->Add("[");
381 key()->PrintTo(stream);
382 stream->Add("] <- ");
383 value()->PrintTo(stream);
384}
385
386
387LChunk::LChunk(CompilationInfo* info, HGraph* graph)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100388 : spill_slot_count_(0),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100389 info_(info),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100390 graph_(graph),
391 instructions_(32),
392 pointer_maps_(8),
393 inlined_closures_(1) {
394}
395
396
Ben Murdochb0fe1622011-05-05 13:52:32 +0100397int LChunk::GetNextSpillIndex(bool is_double) {
398 // Skip a slot if for a double-width slot.
399 if (is_double) spill_slot_count_++;
400 return spill_slot_count_++;
401}
402
403
404LOperand* LChunk::GetNextSpillSlot(bool is_double) {
405 int index = GetNextSpillIndex(is_double);
406 if (is_double) {
407 return LDoubleStackSlot::Create(index);
408 } else {
409 return LStackSlot::Create(index);
410 }
411}
412
413
414void LChunk::MarkEmptyBlocks() {
415 HPhase phase("Mark empty blocks", this);
416 for (int i = 0; i < graph()->blocks()->length(); ++i) {
417 HBasicBlock* block = graph()->blocks()->at(i);
418 int first = block->first_instruction_index();
419 int last = block->last_instruction_index();
420 LInstruction* first_instr = instructions()->at(first);
421 LInstruction* last_instr = instructions()->at(last);
422
423 LLabel* label = LLabel::cast(first_instr);
424 if (last_instr->IsGoto()) {
425 LGoto* goto_instr = LGoto::cast(last_instr);
426 if (!goto_instr->include_stack_check() &&
427 label->IsRedundant() &&
428 !label->is_loop_header()) {
429 bool can_eliminate = true;
430 for (int i = first + 1; i < last && can_eliminate; ++i) {
431 LInstruction* cur = instructions()->at(i);
432 if (cur->IsGap()) {
433 LGap* gap = LGap::cast(cur);
434 if (!gap->IsRedundant()) {
435 can_eliminate = false;
436 }
437 } else {
438 can_eliminate = false;
439 }
440 }
441
442 if (can_eliminate) {
443 label->set_replacement(GetLabel(goto_instr->block_id()));
444 }
445 }
446 }
447 }
448}
449
450
Steve Block1e0659c2011-05-24 12:43:12 +0100451void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100452 LGap* gap = new LGap(block);
453 int index = -1;
454 if (instr->IsControl()) {
455 instructions_.Add(gap);
456 index = instructions_.length();
457 instructions_.Add(instr);
458 } else {
459 index = instructions_.length();
460 instructions_.Add(instr);
461 instructions_.Add(gap);
462 }
463 if (instr->HasPointerMap()) {
464 pointer_maps_.Add(instr->pointer_map());
465 instr->pointer_map()->set_lithium_position(index);
466 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100467}
468
469
470LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
471 return LConstantOperand::Create(constant->id());
472}
473
474
475int LChunk::GetParameterStackSlot(int index) const {
476 // The receiver is at index 0, the first parameter at index 1, so we
477 // shift all parameter indexes down by the number of parameters, and
478 // make sure they end up negative so they are distinguishable from
479 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100480 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100481 ASSERT(result < 0);
482 return result;
483}
484
485// A parameter relative to ebp in the arguments stub.
486int LChunk::ParameterAt(int index) {
487 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100488 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100489 kPointerSize;
490}
491
492
493LGap* LChunk::GetGapAt(int index) const {
494 return LGap::cast(instructions_[index]);
495}
496
497
498bool LChunk::IsGapAt(int index) const {
499 return instructions_[index]->IsGap();
500}
501
502
503int LChunk::NearestGapPos(int index) const {
504 while (!IsGapAt(index)) index--;
505 return index;
506}
507
508
509void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
510 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
511}
512
513
Ben Murdochb0fe1622011-05-05 13:52:32 +0100514Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
515 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
516}
517
518
519Representation LChunk::LookupLiteralRepresentation(
520 LConstantOperand* operand) const {
521 return graph_->LookupValue(operand->index())->representation();
522}
523
524
525LChunk* LChunkBuilder::Build() {
526 ASSERT(is_unused());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100527 chunk_ = new LChunk(info(), graph());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100528 HPhase phase("Building chunk", chunk_);
529 status_ = BUILDING;
530 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
531 for (int i = 0; i < blocks->length(); i++) {
532 HBasicBlock* next = NULL;
533 if (i < blocks->length() - 1) next = blocks->at(i + 1);
534 DoBasicBlock(blocks->at(i), next);
535 if (is_aborted()) return NULL;
536 }
537 status_ = DONE;
538 return chunk_;
539}
540
541
542void LChunkBuilder::Abort(const char* format, ...) {
543 if (FLAG_trace_bailout) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100544 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
545 PrintF("Aborting LChunk building in @\"%s\": ", *name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100546 va_list arguments;
547 va_start(arguments, format);
548 OS::VPrint(format, arguments);
549 va_end(arguments);
550 PrintF("\n");
551 }
552 status_ = ABORTED;
553}
554
555
556LRegister* LChunkBuilder::ToOperand(Register reg) {
557 return LRegister::Create(Register::ToAllocationIndex(reg));
558}
559
560
561LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
562 return new LUnallocated(LUnallocated::FIXED_REGISTER,
563 Register::ToAllocationIndex(reg));
564}
565
566
567LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
568 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
569 DoubleRegister::ToAllocationIndex(reg));
570}
571
572
573LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
574 return Use(value, ToUnallocated(fixed_register));
575}
576
577
578LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
579 return Use(value, ToUnallocated(reg));
580}
581
582
583LOperand* LChunkBuilder::UseRegister(HValue* value) {
584 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
585}
586
587
588LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
589 return Use(value,
590 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
591 LUnallocated::USED_AT_START));
592}
593
594
595LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
596 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
597}
598
599
600LOperand* LChunkBuilder::Use(HValue* value) {
601 return Use(value, new LUnallocated(LUnallocated::NONE));
602}
603
604
605LOperand* LChunkBuilder::UseAtStart(HValue* value) {
606 return Use(value, new LUnallocated(LUnallocated::NONE,
607 LUnallocated::USED_AT_START));
608}
609
610
611LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
612 return value->IsConstant()
613 ? chunk_->DefineConstantOperand(HConstant::cast(value))
614 : Use(value);
615}
616
617
618LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
619 return value->IsConstant()
620 ? chunk_->DefineConstantOperand(HConstant::cast(value))
621 : UseAtStart(value);
622}
623
624
625LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
626 return value->IsConstant()
627 ? chunk_->DefineConstantOperand(HConstant::cast(value))
628 : UseRegister(value);
629}
630
631
632LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
633 return value->IsConstant()
634 ? chunk_->DefineConstantOperand(HConstant::cast(value))
635 : UseRegisterAtStart(value);
636}
637
638
Ben Murdochb8e0da22011-05-16 14:20:40 +0100639LOperand* LChunkBuilder::UseAny(HValue* value) {
640 return value->IsConstant()
641 ? chunk_->DefineConstantOperand(HConstant::cast(value))
642 : Use(value, new LUnallocated(LUnallocated::ANY));
643}
644
645
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
647 if (value->EmitAtUses()) {
648 HInstruction* instr = HInstruction::cast(value);
649 VisitInstruction(instr);
650 }
651 allocator_->RecordUse(value, operand);
652 return operand;
653}
654
655
Steve Block1e0659c2011-05-24 12:43:12 +0100656template<int I, int T>
657LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
658 LUnallocated* result) {
659 allocator_->RecordDefinition(current_instruction_, result);
660 instr->set_result(result);
661 return instr;
662}
663
664
665template<int I, int T>
666LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667 return Define(instr, new LUnallocated(LUnallocated::NONE));
668}
669
670
Steve Block1e0659c2011-05-24 12:43:12 +0100671template<int I, int T>
672LInstruction* LChunkBuilder::DefineAsRegister(
673 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
675}
676
677
Steve Block1e0659c2011-05-24 12:43:12 +0100678template<int I, int T>
679LInstruction* LChunkBuilder::DefineAsSpilled(
680 LTemplateInstruction<1, I, T>* instr, int index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100681 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
682}
683
684
Steve Block1e0659c2011-05-24 12:43:12 +0100685template<int I, int T>
686LInstruction* LChunkBuilder::DefineSameAsFirst(
687 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100688 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
689}
690
691
Steve Block1e0659c2011-05-24 12:43:12 +0100692template<int I, int T>
693LInstruction* LChunkBuilder::DefineFixed(
694 LTemplateInstruction<1, I, T>* instr, Register reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100695 return Define(instr, ToUnallocated(reg));
696}
697
698
Steve Block1e0659c2011-05-24 12:43:12 +0100699template<int I, int T>
700LInstruction* LChunkBuilder::DefineFixedDouble(
701 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100702 return Define(instr, ToUnallocated(reg));
703}
704
705
706LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
707 HEnvironment* hydrogen_env = current_block_->last_environment();
708 instr->set_environment(CreateEnvironment(hydrogen_env));
709 return instr;
710}
711
712
713LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
714 LInstruction* instr, int ast_id) {
Steve Block1e0659c2011-05-24 12:43:12 +0100715 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100716 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
Steve Block1e0659c2011-05-24 12:43:12 +0100717 instruction_pending_deoptimization_environment_ = instr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718 pending_deoptimization_ast_id_ = ast_id;
719 return instr;
720}
721
722
723void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
Steve Block1e0659c2011-05-24 12:43:12 +0100724 instruction_pending_deoptimization_environment_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100725 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
726}
727
728
729LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
730 HInstruction* hinstr,
731 CanDeoptimize can_deoptimize) {
Steve Block1e0659c2011-05-24 12:43:12 +0100732#ifdef DEBUG
733 instr->VerifyCall();
734#endif
735 instr->MarkAsCall();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100736 instr = AssignPointerMap(instr);
737
738 if (hinstr->HasSideEffects()) {
739 ASSERT(hinstr->next()->IsSimulate());
740 HSimulate* sim = HSimulate::cast(hinstr->next());
741 instr = SetInstructionPendingDeoptimizationEnvironment(
742 instr, sim->ast_id());
743 }
744
745 // If instruction does not have side-effects lazy deoptimization
746 // after the call will try to deoptimize to the point before the call.
747 // Thus we still need to attach environment to this call even if
748 // call sequence can not deoptimize eagerly.
749 bool needs_environment =
750 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
751 if (needs_environment && !instr->HasEnvironment()) {
752 instr = AssignEnvironment(instr);
753 }
754
755 return instr;
756}
757
758
Steve Block1e0659c2011-05-24 12:43:12 +0100759LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
760 instr->MarkAsSaveDoubles();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100761 return instr;
762}
763
764
Steve Block1e0659c2011-05-24 12:43:12 +0100765LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
766 ASSERT(!instr->HasPointerMap());
767 instr->set_pointer_map(new LPointerMap(position_));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100768 return instr;
769}
770
771
Ben Murdochb0fe1622011-05-05 13:52:32 +0100772LUnallocated* LChunkBuilder::TempRegister() {
773 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
774 allocator_->RecordTemporary(operand);
775 return operand;
776}
777
778
779LOperand* LChunkBuilder::FixedTemp(Register reg) {
780 LUnallocated* operand = ToUnallocated(reg);
781 allocator_->RecordTemporary(operand);
782 return operand;
783}
784
785
786LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
787 LUnallocated* operand = ToUnallocated(reg);
788 allocator_->RecordTemporary(operand);
789 return operand;
790}
791
792
793LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
794 return new LLabel(instr->block());
795}
796
797
798LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
799 return AssignEnvironment(new LDeoptimize);
800}
801
802
803LInstruction* LChunkBuilder::DoBit(Token::Value op,
804 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100805 if (instr->representation().IsInteger32()) {
806 ASSERT(instr->left()->representation().IsInteger32());
807 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100808
Steve Block1e0659c2011-05-24 12:43:12 +0100809 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
810 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
811 return DefineSameAsFirst(new LBitI(op, left, right));
812 } else {
813 ASSERT(instr->representation().IsTagged());
814 ASSERT(instr->left()->representation().IsTagged());
815 ASSERT(instr->right()->representation().IsTagged());
816
817 LOperand* left = UseFixed(instr->left(), r1);
818 LOperand* right = UseFixed(instr->right(), r0);
819 LArithmeticT* result = new LArithmeticT(op, left, right);
820 return MarkAsCall(DefineFixed(result, r0), instr);
821 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100822}
823
824
825LInstruction* LChunkBuilder::DoShift(Token::Value op,
826 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100827 if (instr->representation().IsTagged()) {
828 ASSERT(instr->left()->representation().IsTagged());
829 ASSERT(instr->right()->representation().IsTagged());
830
831 LOperand* left = UseFixed(instr->left(), r1);
832 LOperand* right = UseFixed(instr->right(), r0);
833 LArithmeticT* result = new LArithmeticT(op, left, right);
834 return MarkAsCall(DefineFixed(result, r0), instr);
835 }
836
Ben Murdochb0fe1622011-05-05 13:52:32 +0100837 ASSERT(instr->representation().IsInteger32());
838 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
839 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
840 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
841
842 HValue* right_value = instr->OperandAt(1);
843 LOperand* right = NULL;
844 int constant_value = 0;
845 if (right_value->IsConstant()) {
846 HConstant* constant = HConstant::cast(right_value);
847 right = chunk_->DefineConstantOperand(constant);
848 constant_value = constant->Integer32Value() & 0x1f;
849 } else {
850 right = UseRegister(right_value);
851 }
852
853 // Shift operations can only deoptimize if we do a logical shift
854 // by 0 and the result cannot be truncated to int32.
855 bool can_deopt = (op == Token::SHR && constant_value == 0);
856 if (can_deopt) {
857 bool can_truncate = true;
858 for (int i = 0; i < instr->uses()->length(); i++) {
859 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
860 can_truncate = false;
861 break;
862 }
863 }
864 can_deopt = !can_truncate;
865 }
866
867 LInstruction* result =
868 DefineSameAsFirst(new LShiftI(op, left, right, can_deopt));
869 if (can_deopt) AssignEnvironment(result);
870 return result;
871}
872
873
874LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
875 HArithmeticBinaryOperation* instr) {
876 ASSERT(instr->representation().IsDouble());
877 ASSERT(instr->left()->representation().IsDouble());
878 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100879 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100880 LOperand* left = UseRegisterAtStart(instr->left());
881 LOperand* right = UseRegisterAtStart(instr->right());
882 LArithmeticD* result = new LArithmeticD(op, left, right);
883 return DefineSameAsFirst(result);
884}
885
886
887LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
888 HArithmeticBinaryOperation* instr) {
889 ASSERT(op == Token::ADD ||
890 op == Token::DIV ||
891 op == Token::MOD ||
892 op == Token::MUL ||
893 op == Token::SUB);
894 HValue* left = instr->left();
895 HValue* right = instr->right();
896 ASSERT(left->representation().IsTagged());
897 ASSERT(right->representation().IsTagged());
898 LOperand* left_operand = UseFixed(left, r1);
899 LOperand* right_operand = UseFixed(right, r0);
Steve Block1e0659c2011-05-24 12:43:12 +0100900 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100901 return MarkAsCall(DefineFixed(result, r0), instr);
902}
903
Steve Block1e0659c2011-05-24 12:43:12 +0100904
Ben Murdochb0fe1622011-05-05 13:52:32 +0100905void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
906 ASSERT(is_building());
907 current_block_ = block;
908 next_block_ = next_block;
909 if (block->IsStartBlock()) {
910 block->UpdateEnvironment(graph_->start_environment());
911 argument_count_ = 0;
912 } else if (block->predecessors()->length() == 1) {
913 // We have a single predecessor => copy environment and outgoing
914 // argument count from the predecessor.
915 ASSERT(block->phis()->length() == 0);
916 HBasicBlock* pred = block->predecessors()->at(0);
917 HEnvironment* last_environment = pred->last_environment();
918 ASSERT(last_environment != NULL);
919 // Only copy the environment, if it is later used again.
920 if (pred->end()->SecondSuccessor() == NULL) {
921 ASSERT(pred->end()->FirstSuccessor() == block);
922 } else {
923 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
924 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
925 last_environment = last_environment->Copy();
926 }
927 }
928 block->UpdateEnvironment(last_environment);
929 ASSERT(pred->argument_count() >= 0);
930 argument_count_ = pred->argument_count();
931 } else {
932 // We are at a state join => process phis.
933 HBasicBlock* pred = block->predecessors()->at(0);
934 // No need to copy the environment, it cannot be used later.
935 HEnvironment* last_environment = pred->last_environment();
936 for (int i = 0; i < block->phis()->length(); ++i) {
937 HPhi* phi = block->phis()->at(i);
938 last_environment->SetValueAt(phi->merged_index(), phi);
939 }
940 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
941 last_environment->SetValueAt(block->deleted_phis()->at(i),
942 graph_->GetConstantUndefined());
943 }
944 block->UpdateEnvironment(last_environment);
945 // Pick up the outgoing argument count of one of the predecessors.
946 argument_count_ = pred->argument_count();
947 }
948 HInstruction* current = block->first();
949 int start = chunk_->instructions()->length();
950 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100951 // Code for constants in registers is generated lazily.
952 if (!current->EmitAtUses()) {
953 VisitInstruction(current);
954 }
955 current = current->next();
956 }
957 int end = chunk_->instructions()->length() - 1;
958 if (end >= start) {
959 block->set_first_instruction_index(start);
960 block->set_last_instruction_index(end);
961 }
962 block->set_argument_count(argument_count_);
963 next_block_ = NULL;
964 current_block_ = NULL;
965}
966
967
968void LChunkBuilder::VisitInstruction(HInstruction* current) {
969 HInstruction* old_current = current_instruction_;
970 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100971 if (current->has_position()) position_ = current->position();
972 LInstruction* instr = current->CompileToLithium(this);
973
974 if (instr != NULL) {
975 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
976 instr = AssignPointerMap(instr);
977 }
978 if (FLAG_stress_environments && !instr->HasEnvironment()) {
979 instr = AssignEnvironment(instr);
980 }
Steve Block1e0659c2011-05-24 12:43:12 +0100981 if (current->IsTest() && !instr->IsGoto()) {
982 ASSERT(instr->IsControl());
983 HTest* test = HTest::cast(current);
984 instr->set_hydrogen_value(test->value());
985 HBasicBlock* first = test->FirstSuccessor();
986 HBasicBlock* second = test->SecondSuccessor();
987 ASSERT(first != NULL && second != NULL);
988 instr->SetBranchTargets(first->block_id(), second->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100989 } else {
990 instr->set_hydrogen_value(current);
991 }
992
Steve Block1e0659c2011-05-24 12:43:12 +0100993 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100994 }
995 current_instruction_ = old_current;
996}
997
998
Ben Murdochb0fe1622011-05-05 13:52:32 +0100999LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
1000 if (hydrogen_env == NULL) return NULL;
1001
1002 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1003 int ast_id = hydrogen_env->ast_id();
1004 ASSERT(ast_id != AstNode::kNoNumber);
Steve Block9fac8402011-05-12 15:51:54 +01001005 int value_count = hydrogen_env->length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001006 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1007 ast_id,
1008 hydrogen_env->parameter_count(),
1009 argument_count_,
1010 value_count,
1011 outer);
1012 int argument_index = 0;
1013 for (int i = 0; i < value_count; ++i) {
1014 HValue* value = hydrogen_env->values()->at(i);
1015 LOperand* op = NULL;
1016 if (value->IsArgumentsObject()) {
1017 op = NULL;
1018 } else if (value->IsPushArgument()) {
1019 op = new LArgument(argument_index++);
1020 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001021 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001022 }
1023 result->AddValue(op, value->representation());
1024 }
1025
1026 return result;
1027}
1028
1029
1030LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1031 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(),
1032 instr->include_stack_check());
1033 if (instr->include_stack_check()) result = AssignPointerMap(result);
1034 return result;
1035}
1036
1037
Steve Block1e0659c2011-05-24 12:43:12 +01001038LInstruction* LChunkBuilder::DoTest(HTest* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001039 HValue* v = instr->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001040 if (v->EmitAtUses()) {
1041 if (v->IsClassOfTest()) {
1042 HClassOfTest* compare = HClassOfTest::cast(v);
1043 ASSERT(compare->value()->representation().IsTagged());
1044
1045 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
Steve Block1e0659c2011-05-24 12:43:12 +01001046 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001047 } else if (v->IsCompare()) {
1048 HCompare* compare = HCompare::cast(v);
1049 Token::Value op = compare->token();
1050 HValue* left = compare->left();
1051 HValue* right = compare->right();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001052 Representation r = compare->GetInputRepresentation();
1053 if (r.IsInteger32()) {
1054 ASSERT(left->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001055 ASSERT(right->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001056 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001057 UseRegisterAtStart(right));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001058 } else if (r.IsDouble()) {
1059 ASSERT(left->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001060 ASSERT(right->representation().IsDouble());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001061 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001062 UseRegisterAtStart(right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001063 } else {
1064 ASSERT(left->representation().IsTagged());
1065 ASSERT(right->representation().IsTagged());
1066 bool reversed = op == Token::GT || op == Token::LTE;
1067 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1);
1068 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0);
1069 LInstruction* result = new LCmpTAndBranch(left_operand,
Steve Block1e0659c2011-05-24 12:43:12 +01001070 right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001071 return MarkAsCall(result, instr);
1072 }
1073 } else if (v->IsIsSmi()) {
1074 HIsSmi* compare = HIsSmi::cast(v);
1075 ASSERT(compare->value()->representation().IsTagged());
1076
Steve Block1e0659c2011-05-24 12:43:12 +01001077 return new LIsSmiAndBranch(Use(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001078 } else if (v->IsHasInstanceType()) {
1079 HHasInstanceType* compare = HHasInstanceType::cast(v);
1080 ASSERT(compare->value()->representation().IsTagged());
Steve Block1e0659c2011-05-24 12:43:12 +01001081 return new LHasInstanceTypeAndBranch(
1082 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001083 } else if (v->IsHasCachedArrayIndex()) {
1084 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1085 ASSERT(compare->value()->representation().IsTagged());
1086
1087 return new LHasCachedArrayIndexAndBranch(
Steve Block1e0659c2011-05-24 12:43:12 +01001088 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001089 } else if (v->IsIsNull()) {
1090 HIsNull* compare = HIsNull::cast(v);
1091 ASSERT(compare->value()->representation().IsTagged());
1092
Steve Block1e0659c2011-05-24 12:43:12 +01001093 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001094 } else if (v->IsIsObject()) {
1095 HIsObject* compare = HIsObject::cast(v);
1096 ASSERT(compare->value()->representation().IsTagged());
1097
Steve Block1e0659c2011-05-24 12:43:12 +01001098 LOperand* temp = TempRegister();
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +01001099 return new LIsObjectAndBranch(UseRegister(compare->value()), temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001100 } else if (v->IsCompareJSObjectEq()) {
1101 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1102 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
Steve Block1e0659c2011-05-24 12:43:12 +01001103 UseRegisterAtStart(compare->right()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001104 } else if (v->IsInstanceOf()) {
1105 HInstanceOf* instance_of = HInstanceOf::cast(v);
1106 LInstruction* result =
Steve Block1e0659c2011-05-24 12:43:12 +01001107 new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0),
1108 UseFixed(instance_of->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001109 return MarkAsCall(result, instr);
1110 } else if (v->IsTypeofIs()) {
1111 HTypeofIs* typeof_is = HTypeofIs::cast(v);
Steve Block1e0659c2011-05-24 12:43:12 +01001112 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1113 } else if (v->IsIsConstructCall()) {
1114 return new LIsConstructCallAndBranch(TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001115 } else {
1116 if (v->IsConstant()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001117 if (HConstant::cast(v)->ToBoolean()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001118 return new LGoto(instr->FirstSuccessor()->block_id());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001119 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001120 return new LGoto(instr->SecondSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001121 }
1122 }
1123 Abort("Undefined compare before branch");
1124 return NULL;
1125 }
1126 }
Steve Block1e0659c2011-05-24 12:43:12 +01001127 return new LBranch(UseRegisterAtStart(v));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001128}
1129
1130
Steve Block1e0659c2011-05-24 12:43:12 +01001131LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001132 ASSERT(instr->value()->representation().IsTagged());
1133 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block9fac8402011-05-12 15:51:54 +01001134 LOperand* temp = TempRegister();
1135 return new LCmpMapAndBranch(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001136}
1137
1138
1139LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001140 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001141}
1142
1143
1144LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1145 return DefineAsRegister(new LArgumentsElements);
1146}
1147
1148
1149LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001150 LInstanceOf* result =
Steve Block9fac8402011-05-12 15:51:54 +01001151 new LInstanceOf(UseFixed(instr->left(), r0),
1152 UseFixed(instr->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001153 return MarkAsCall(DefineFixed(result, r0), instr);
1154}
1155
1156
Ben Murdoch086aeea2011-05-13 15:57:08 +01001157LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1158 HInstanceOfKnownGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001159 LInstanceOfKnownGlobal* result =
1160 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001161 return MarkAsCall(DefineFixed(result, r0), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001162}
1163
1164
Ben Murdochb0fe1622011-05-05 13:52:32 +01001165LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1166 LOperand* function = UseFixed(instr->function(), r1);
1167 LOperand* receiver = UseFixed(instr->receiver(), r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001168 LOperand* length = UseFixed(instr->length(), r2);
1169 LOperand* elements = UseFixed(instr->elements(), r3);
1170 LApplyArguments* result = new LApplyArguments(function,
1171 receiver,
1172 length,
1173 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001174 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1175}
1176
1177
1178LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1179 ++argument_count_;
1180 LOperand* argument = Use(instr->argument());
1181 return new LPushArgument(argument);
1182}
1183
1184
Steve Block1e0659c2011-05-24 12:43:12 +01001185LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1186 return DefineAsRegister(new LContext);
1187}
1188
1189
1190LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1191 LOperand* context = UseRegisterAtStart(instr->value());
1192 return DefineAsRegister(new LOuterContext(context));
1193}
1194
1195
Ben Murdochb0fe1622011-05-05 13:52:32 +01001196LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001197 LOperand* context = UseRegisterAtStart(instr->value());
1198 return DefineAsRegister(new LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001199}
1200
1201
1202LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001203 LOperand* global_object = UseRegisterAtStart(instr->value());
1204 return DefineAsRegister(new LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001205}
1206
1207
1208LInstruction* LChunkBuilder::DoCallConstantFunction(
1209 HCallConstantFunction* instr) {
1210 argument_count_ -= instr->argument_count();
1211 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
1212}
1213
1214
1215LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1216 BuiltinFunctionId op = instr->op();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001217 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1218 LOperand* input = UseFixedDouble(instr->value(), d2);
1219 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
1220 return MarkAsCall(DefineFixedDouble(result, d2), instr);
1221 } else {
1222 LOperand* input = UseRegisterAtStart(instr->value());
1223 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1224 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1225 switch (op) {
1226 case kMathAbs:
1227 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1228 case kMathFloor:
1229 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1230 case kMathSqrt:
1231 return DefineSameAsFirst(result);
1232 case kMathRound:
1233 return AssignEnvironment(DefineAsRegister(result));
1234 case kMathPowHalf:
Steve Block44f0eee2011-05-26 01:26:41 +01001235 return DefineSameAsFirst(result);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001236 default:
1237 UNREACHABLE();
1238 return NULL;
1239 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001240 }
1241}
1242
1243
1244LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1245 ASSERT(instr->key()->representation().IsTagged());
1246 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001247 LOperand* key = UseFixed(instr->key(), r2);
1248 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001249}
1250
1251
1252LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1253 argument_count_ -= instr->argument_count();
1254 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
1255}
1256
1257
1258LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1259 argument_count_ -= instr->argument_count();
1260 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
1261}
1262
1263
1264LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1265 argument_count_ -= instr->argument_count();
1266 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
1267}
1268
1269
1270LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1271 LOperand* constructor = UseFixed(instr->constructor(), r1);
1272 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001273 LCallNew* result = new LCallNew(constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001274 return MarkAsCall(DefineFixed(result, r0), instr);
1275}
1276
1277
1278LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1279 argument_count_ -= instr->argument_count();
1280 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
1281}
1282
1283
1284LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1285 argument_count_ -= instr->argument_count();
1286 return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
1287}
1288
1289
1290LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1291 return DoShift(Token::SHR, instr);
1292}
1293
1294
1295LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1296 return DoShift(Token::SAR, instr);
1297}
1298
1299
1300LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1301 return DoShift(Token::SHL, instr);
1302}
1303
1304
1305LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1306 return DoBit(Token::BIT_AND, instr);
1307}
1308
1309
1310LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1311 ASSERT(instr->value()->representation().IsInteger32());
1312 ASSERT(instr->representation().IsInteger32());
1313 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value())));
1314}
1315
1316
1317LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1318 return DoBit(Token::BIT_OR, instr);
1319}
1320
1321
1322LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1323 return DoBit(Token::BIT_XOR, instr);
1324}
1325
1326
1327LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1328 if (instr->representation().IsDouble()) {
1329 return DoArithmeticD(Token::DIV, instr);
1330 } else if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001331 // TODO(1042) The fixed register allocation
Ben Murdoch8b112d22011-06-08 16:22:53 +01001332 // is needed because we call TypeRecordingBinaryOpStub from
Ben Murdochb8e0da22011-05-16 14:20:40 +01001333 // the generated code, which requires registers r0
1334 // and r1 to be used. We should remove that
1335 // when we provide a native implementation.
Steve Block1e0659c2011-05-24 12:43:12 +01001336 LOperand* dividend = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001337 LOperand* divisor = UseFixed(instr->right(), r1);
1338 return AssignEnvironment(AssignPointerMap(
Steve Block1e0659c2011-05-24 12:43:12 +01001339 DefineFixed(new LDivI(dividend, divisor), r0)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001340 } else {
1341 return DoArithmeticT(Token::DIV, instr);
1342 }
1343}
1344
1345
1346LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1347 if (instr->representation().IsInteger32()) {
1348 ASSERT(instr->left()->representation().IsInteger32());
1349 ASSERT(instr->right()->representation().IsInteger32());
Steve Block44f0eee2011-05-26 01:26:41 +01001350
1351 LModI* mod;
1352 if (instr->HasPowerOf2Divisor()) {
1353 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1354 LOperand* value = UseRegisterAtStart(instr->left());
1355 mod = new LModI(value, UseOrConstant(instr->right()));
1356 } else {
1357 LOperand* dividend = UseRegister(instr->left());
1358 LOperand* divisor = UseRegisterAtStart(instr->right());
1359 mod = new LModI(dividend,
1360 divisor,
1361 TempRegister(),
1362 FixedTemp(d1),
1363 FixedTemp(d2));
1364 }
1365
1366 return AssignEnvironment(DefineSameAsFirst(mod));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001367 } else if (instr->representation().IsTagged()) {
1368 return DoArithmeticT(Token::MOD, instr);
1369 } else {
1370 ASSERT(instr->representation().IsDouble());
1371 // We call a C function for double modulo. It can't trigger a GC.
1372 // We need to use fixed result register for the call.
1373 // TODO(fschneider): Allow any register as input registers.
1374 LOperand* left = UseFixedDouble(instr->left(), d1);
1375 LOperand* right = UseFixedDouble(instr->right(), d2);
1376 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
1377 return MarkAsCall(DefineFixedDouble(result, d1), instr);
1378 }
1379}
1380
1381
1382LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1383 if (instr->representation().IsInteger32()) {
1384 ASSERT(instr->left()->representation().IsInteger32());
1385 ASSERT(instr->right()->representation().IsInteger32());
1386 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1387 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1388 LOperand* temp = NULL;
1389 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1390 temp = TempRegister();
1391 }
1392 LMulI* mul = new LMulI(left, right, temp);
1393 return AssignEnvironment(DefineSameAsFirst(mul));
1394 } else if (instr->representation().IsDouble()) {
1395 return DoArithmeticD(Token::MUL, instr);
1396 } else {
1397 return DoArithmeticT(Token::MUL, instr);
1398 }
1399}
1400
1401
1402LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1403 if (instr->representation().IsInteger32()) {
1404 ASSERT(instr->left()->representation().IsInteger32());
1405 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001406 LOperand* left = UseRegisterAtStart(instr->left());
1407 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001408 LSubI* sub = new LSubI(left, right);
1409 LInstruction* result = DefineSameAsFirst(sub);
1410 if (instr->CheckFlag(HValue::kCanOverflow)) {
1411 result = AssignEnvironment(result);
1412 }
1413 return result;
1414 } else if (instr->representation().IsDouble()) {
1415 return DoArithmeticD(Token::SUB, instr);
1416 } else {
1417 return DoArithmeticT(Token::SUB, instr);
1418 }
1419}
1420
1421
1422LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1423 if (instr->representation().IsInteger32()) {
1424 ASSERT(instr->left()->representation().IsInteger32());
1425 ASSERT(instr->right()->representation().IsInteger32());
1426 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1427 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1428 LAddI* add = new LAddI(left, right);
1429 LInstruction* result = DefineSameAsFirst(add);
1430 if (instr->CheckFlag(HValue::kCanOverflow)) {
1431 result = AssignEnvironment(result);
1432 }
1433 return result;
1434 } else if (instr->representation().IsDouble()) {
1435 return DoArithmeticD(Token::ADD, instr);
1436 } else {
1437 ASSERT(instr->representation().IsTagged());
1438 return DoArithmeticT(Token::ADD, instr);
1439 }
1440}
1441
1442
1443LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001444 ASSERT(instr->representation().IsDouble());
1445 // We call a C function for double power. It can't trigger a GC.
1446 // We need to use fixed result register for the call.
1447 Representation exponent_type = instr->right()->representation();
1448 ASSERT(instr->left()->representation().IsDouble());
1449 LOperand* left = UseFixedDouble(instr->left(), d1);
1450 LOperand* right = exponent_type.IsDouble() ?
1451 UseFixedDouble(instr->right(), d2) :
1452 UseFixed(instr->right(), r0);
1453 LPower* result = new LPower(left, right);
1454 return MarkAsCall(DefineFixedDouble(result, d3),
1455 instr,
1456 CAN_DEOPTIMIZE_EAGERLY);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001457}
1458
1459
1460LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1461 Token::Value op = instr->token();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001462 Representation r = instr->GetInputRepresentation();
1463 if (r.IsInteger32()) {
1464 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001465 ASSERT(instr->right()->representation().IsInteger32());
1466 LOperand* left = UseRegisterAtStart(instr->left());
Steve Block1e0659c2011-05-24 12:43:12 +01001467 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001468 return DefineAsRegister(new LCmpID(left, right));
1469 } else if (r.IsDouble()) {
1470 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001471 ASSERT(instr->right()->representation().IsDouble());
1472 LOperand* left = UseRegisterAtStart(instr->left());
1473 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001474 return DefineAsRegister(new LCmpID(left, right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001475 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001476 ASSERT(instr->left()->representation().IsTagged());
1477 ASSERT(instr->right()->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001478 bool reversed = (op == Token::GT || op == Token::LTE);
1479 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1480 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001481 LCmpT* result = new LCmpT(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001482 return MarkAsCall(DefineFixed(result, r0), instr);
1483 }
1484}
1485
1486
1487LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1488 HCompareJSObjectEq* instr) {
1489 LOperand* left = UseRegisterAtStart(instr->left());
1490 LOperand* right = UseRegisterAtStart(instr->right());
Steve Block1e0659c2011-05-24 12:43:12 +01001491 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001492 return DefineAsRegister(result);
1493}
1494
1495
1496LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1497 ASSERT(instr->value()->representation().IsTagged());
1498 LOperand* value = UseRegisterAtStart(instr->value());
1499
Ben Murdochb8e0da22011-05-16 14:20:40 +01001500 return DefineAsRegister(new LIsNull(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001501}
1502
1503
1504LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1505 ASSERT(instr->value()->representation().IsTagged());
1506 LOperand* value = UseRegisterAtStart(instr->value());
1507
Steve Block1e0659c2011-05-24 12:43:12 +01001508 return DefineAsRegister(new LIsObject(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001509}
1510
1511
1512LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1513 ASSERT(instr->value()->representation().IsTagged());
1514 LOperand* value = UseAtStart(instr->value());
1515
1516 return DefineAsRegister(new LIsSmi(value));
1517}
1518
1519
1520LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1521 ASSERT(instr->value()->representation().IsTagged());
1522 LOperand* value = UseRegisterAtStart(instr->value());
1523
1524 return DefineAsRegister(new LHasInstanceType(value));
1525}
1526
1527
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001528LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1529 HGetCachedArrayIndex* instr) {
1530 ASSERT(instr->value()->representation().IsTagged());
1531 LOperand* value = UseRegisterAtStart(instr->value());
1532
1533 return DefineAsRegister(new LGetCachedArrayIndex(value));
1534}
1535
1536
Ben Murdochb0fe1622011-05-05 13:52:32 +01001537LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1538 HHasCachedArrayIndex* instr) {
1539 ASSERT(instr->value()->representation().IsTagged());
1540 LOperand* value = UseRegister(instr->value());
1541
1542 return DefineAsRegister(new LHasCachedArrayIndex(value));
1543}
1544
1545
1546LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1547 ASSERT(instr->value()->representation().IsTagged());
1548 LOperand* value = UseTempRegister(instr->value());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001549 return DefineSameAsFirst(new LClassOfTest(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001550}
1551
1552
Steve Block9fac8402011-05-12 15:51:54 +01001553LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1554 LOperand* array = UseRegisterAtStart(instr->value());
1555 return DefineAsRegister(new LJSArrayLength(array));
1556}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001557
Ben Murdochb0fe1622011-05-05 13:52:32 +01001558
Steve Block44f0eee2011-05-26 01:26:41 +01001559LInstruction* LChunkBuilder::DoExternalArrayLength(
1560 HExternalArrayLength* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001561 LOperand* array = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001562 return DefineAsRegister(new LExternalArrayLength(array));
Steve Block1e0659c2011-05-24 12:43:12 +01001563}
1564
1565
Steve Block9fac8402011-05-12 15:51:54 +01001566LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1567 LOperand* array = UseRegisterAtStart(instr->value());
1568 return DefineAsRegister(new LFixedArrayLength(array));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001569}
1570
1571
1572LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1573 LOperand* object = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001574 LValueOf* result = new LValueOf(object, TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001575 return AssignEnvironment(DefineSameAsFirst(result));
1576}
1577
1578
1579LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1580 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001581 UseRegister(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001582}
1583
1584
Steve Block1e0659c2011-05-24 12:43:12 +01001585LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1586 // The control instruction marking the end of a block that completed
1587 // abruptly (e.g., threw an exception). There is nothing specific to do.
1588 return NULL;
1589}
1590
1591
Ben Murdochb0fe1622011-05-05 13:52:32 +01001592LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1593 LOperand* value = UseFixed(instr->value(), r0);
1594 return MarkAsCall(new LThrow(value), instr);
1595}
1596
1597
1598LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1599 Representation from = instr->from();
1600 Representation to = instr->to();
1601 if (from.IsTagged()) {
1602 if (to.IsDouble()) {
1603 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001604 LNumberUntagD* res = new LNumberUntagD(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001605 return AssignEnvironment(DefineAsRegister(res));
1606 } else {
1607 ASSERT(to.IsInteger32());
1608 LOperand* value = UseRegister(instr->value());
1609 bool needs_check = !instr->value()->type().IsSmi();
1610 LInstruction* res = NULL;
Steve Block44f0eee2011-05-26 01:26:41 +01001611 if (!needs_check) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001612 res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
Steve Block44f0eee2011-05-26 01:26:41 +01001613 } else {
1614 LOperand* temp1 = TempRegister();
1615 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
1616 : NULL;
1617 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3)
1618 : NULL;
1619 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001620 res = AssignEnvironment(res);
1621 }
1622 return res;
1623 }
1624 } else if (from.IsDouble()) {
1625 if (to.IsTagged()) {
1626 LOperand* value = UseRegister(instr->value());
1627 LOperand* temp1 = TempRegister();
1628 LOperand* temp2 = TempRegister();
1629
1630 // Make sure that the temp and result_temp registers are
1631 // different.
1632 LUnallocated* result_temp = TempRegister();
Steve Block1e0659c2011-05-24 12:43:12 +01001633 LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001634 Define(result, result_temp);
1635 return AssignPointerMap(result);
1636 } else {
1637 ASSERT(to.IsInteger32());
1638 LOperand* value = UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001639 LDoubleToI* res =
1640 new LDoubleToI(value,
1641 TempRegister(),
1642 instr->CanTruncateToInt32() ? TempRegister() : NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001643 return AssignEnvironment(DefineAsRegister(res));
1644 }
1645 } else if (from.IsInteger32()) {
1646 if (to.IsTagged()) {
1647 HValue* val = instr->value();
1648 LOperand* value = UseRegister(val);
1649 if (val->HasRange() && val->range()->IsInSmiRange()) {
1650 return DefineSameAsFirst(new LSmiTag(value));
1651 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001652 LNumberTagI* result = new LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001653 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1654 }
1655 } else {
1656 ASSERT(to.IsDouble());
1657 LOperand* value = Use(instr->value());
1658 return DefineAsRegister(new LInteger32ToDouble(value));
1659 }
1660 }
1661 UNREACHABLE();
1662 return NULL;
1663}
1664
1665
1666LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1667 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001668 return AssignEnvironment(new LCheckNonSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001669}
1670
1671
1672LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1673 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001674 LInstruction* result = new LCheckInstanceType(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001675 return AssignEnvironment(result);
1676}
1677
1678
1679LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001680 LOperand* temp1 = TempRegister();
1681 LOperand* temp2 = TempRegister();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001682 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001683 return AssignEnvironment(result);
1684}
1685
1686
1687LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1688 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001689 return AssignEnvironment(new LCheckSmi(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001690}
1691
1692
1693LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1694 LOperand* value = UseRegisterAtStart(instr->value());
1695 return AssignEnvironment(new LCheckFunction(value));
1696}
1697
1698
1699LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1700 LOperand* value = UseRegisterAtStart(instr->value());
1701 LInstruction* result = new LCheckMap(value);
1702 return AssignEnvironment(result);
1703}
1704
1705
1706LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1707 return new LReturn(UseFixed(instr->value(), r0));
1708}
1709
1710
1711LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1712 Representation r = instr->representation();
1713 if (r.IsInteger32()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001714 return DefineAsRegister(new LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001715 } else if (r.IsDouble()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001716 return DefineAsRegister(new LConstantD);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001717 } else if (r.IsTagged()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001718 return DefineAsRegister(new LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001719 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001720 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001721 return NULL;
1722 }
1723}
1724
1725
Ben Murdoch8b112d22011-06-08 16:22:53 +01001726LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1727 LLoadGlobalCell* result = new LLoadGlobalCell;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001728 return instr->check_hole_value()
1729 ? AssignEnvironment(DefineAsRegister(result))
1730 : DefineAsRegister(result);
1731}
1732
1733
Ben Murdoch8b112d22011-06-08 16:22:53 +01001734LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1735 LOperand* global_object = UseFixed(instr->global_object(), r0);
1736 LLoadGlobalGeneric* result = new LLoadGlobalGeneric(global_object);
1737 return MarkAsCall(DefineFixed(result, r0), instr);
1738}
1739
1740
1741LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001742 if (instr->check_hole_value()) {
1743 LOperand* temp = TempRegister();
1744 LOperand* value = UseRegister(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001745 return AssignEnvironment(new LStoreGlobalCell(value, temp));
Steve Block1e0659c2011-05-24 12:43:12 +01001746 } else {
1747 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001748 return new LStoreGlobalCell(value, NULL);
Steve Block1e0659c2011-05-24 12:43:12 +01001749 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001750}
1751
1752
Ben Murdoch8b112d22011-06-08 16:22:53 +01001753LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1754 LOperand* global_object = UseFixed(instr->global_object(), r1);
1755 LOperand* value = UseFixed(instr->value(), r0);
1756 LStoreGlobalGeneric* result =
1757 new LStoreGlobalGeneric(global_object, value);
1758 return MarkAsCall(result, instr);
1759}
1760
1761
Ben Murdochb8e0da22011-05-16 14:20:40 +01001762LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001763 LOperand* context = UseRegisterAtStart(instr->value());
1764 return DefineAsRegister(new LLoadContextSlot(context));
1765}
1766
1767
1768LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001769 LOperand* context;
Steve Block1e0659c2011-05-24 12:43:12 +01001770 LOperand* value;
1771 if (instr->NeedsWriteBarrier()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001772 context = UseTempRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001773 value = UseTempRegister(instr->value());
1774 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001775 context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001776 value = UseRegister(instr->value());
1777 }
1778 return new LStoreContextSlot(context, value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001779}
1780
1781
Ben Murdochb0fe1622011-05-05 13:52:32 +01001782LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1783 return DefineAsRegister(
1784 new LLoadNamedField(UseRegisterAtStart(instr->object())));
1785}
1786
1787
Steve Block44f0eee2011-05-26 01:26:41 +01001788LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
1789 HLoadNamedFieldPolymorphic* instr) {
1790 ASSERT(instr->representation().IsTagged());
1791 if (instr->need_generic()) {
1792 LOperand* obj = UseFixed(instr->object(), r0);
1793 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1794 return MarkAsCall(DefineFixed(result, r0), instr);
1795 } else {
1796 LOperand* obj = UseRegisterAtStart(instr->object());
1797 LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
1798 return AssignEnvironment(DefineAsRegister(result));
1799 }
1800}
1801
1802
Ben Murdochb0fe1622011-05-05 13:52:32 +01001803LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1804 LOperand* object = UseFixed(instr->object(), r0);
1805 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
1806 return MarkAsCall(result, instr);
1807}
1808
1809
Steve Block9fac8402011-05-12 15:51:54 +01001810LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1811 HLoadFunctionPrototype* instr) {
1812 return AssignEnvironment(DefineAsRegister(
1813 new LLoadFunctionPrototype(UseRegister(instr->function()))));
1814}
1815
1816
Ben Murdochb0fe1622011-05-05 13:52:32 +01001817LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1818 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001819 return DefineAsRegister(new LLoadElements(input));
1820}
1821
1822
Steve Block44f0eee2011-05-26 01:26:41 +01001823LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
1824 HLoadExternalArrayPointer* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001825 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001826 return DefineAsRegister(new LLoadExternalArrayPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001827}
1828
1829
1830LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1831 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001832 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001833 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001834 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001835 LOperand* key = UseRegisterAtStart(instr->key());
Steve Block1e0659c2011-05-24 12:43:12 +01001836 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001837 return AssignEnvironment(DefineSameAsFirst(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001838}
1839
1840
Steve Block44f0eee2011-05-26 01:26:41 +01001841LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
1842 HLoadKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001843 ExternalArrayType array_type = instr->array_type();
1844 Representation representation(instr->representation());
1845 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
1846 (representation.IsDouble() && array_type == kExternalFloatArray));
Steve Block1e0659c2011-05-24 12:43:12 +01001847 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001848 LOperand* external_pointer = UseRegister(instr->external_pointer());
1849 LOperand* key = UseRegister(instr->key());
Steve Block44f0eee2011-05-26 01:26:41 +01001850 LLoadKeyedSpecializedArrayElement* result =
Ben Murdoch8b112d22011-06-08 16:22:53 +01001851 new LLoadKeyedSpecializedArrayElement(external_pointer, key);
1852 LInstruction* load_instr = DefineAsRegister(result);
1853 // An unsigned int array load might overflow and cause a deopt, make sure it
1854 // has an environment.
1855 return (array_type == kExternalUnsignedIntArray) ?
1856 AssignEnvironment(load_instr) : load_instr;
Steve Block1e0659c2011-05-24 12:43:12 +01001857}
1858
1859
Ben Murdochb0fe1622011-05-05 13:52:32 +01001860LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1861 LOperand* object = UseFixed(instr->object(), r1);
1862 LOperand* key = UseFixed(instr->key(), r0);
1863
1864 LInstruction* result =
1865 DefineFixed(new LLoadKeyedGeneric(object, key), r0);
1866 return MarkAsCall(result, instr);
1867}
1868
1869
1870LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1871 HStoreKeyedFastElement* instr) {
1872 bool needs_write_barrier = instr->NeedsWriteBarrier();
1873 ASSERT(instr->value()->representation().IsTagged());
1874 ASSERT(instr->object()->representation().IsTagged());
1875 ASSERT(instr->key()->representation().IsInteger32());
1876
1877 LOperand* obj = UseTempRegister(instr->object());
1878 LOperand* val = needs_write_barrier
1879 ? UseTempRegister(instr->value())
1880 : UseRegisterAtStart(instr->value());
1881 LOperand* key = needs_write_barrier
1882 ? UseTempRegister(instr->key())
1883 : UseRegisterOrConstantAtStart(instr->key());
1884
1885 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1886}
1887
1888
Steve Block44f0eee2011-05-26 01:26:41 +01001889LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
1890 HStoreKeyedSpecializedArrayElement* instr) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01001891 Representation representation(instr->value()->representation());
1892 ExternalArrayType array_type = instr->array_type();
1893 ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
1894 (representation.IsDouble() && array_type == kExternalFloatArray));
Steve Block44f0eee2011-05-26 01:26:41 +01001895 ASSERT(instr->external_pointer()->representation().IsExternal());
1896 ASSERT(instr->key()->representation().IsInteger32());
1897
1898 LOperand* external_pointer = UseRegister(instr->external_pointer());
Ben Murdoch8b112d22011-06-08 16:22:53 +01001899 bool val_is_temp_register = array_type == kExternalPixelArray ||
1900 array_type == kExternalFloatArray;
1901 LOperand* val = val_is_temp_register
1902 ? UseTempRegister(instr->value())
1903 : UseRegister(instr->value());
Steve Block44f0eee2011-05-26 01:26:41 +01001904 LOperand* key = UseRegister(instr->key());
1905
1906 return new LStoreKeyedSpecializedArrayElement(external_pointer,
1907 key,
Ben Murdoch8b112d22011-06-08 16:22:53 +01001908 val);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001909}
1910
1911
Ben Murdochb0fe1622011-05-05 13:52:32 +01001912LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1913 LOperand* obj = UseFixed(instr->object(), r2);
1914 LOperand* key = UseFixed(instr->key(), r1);
1915 LOperand* val = UseFixed(instr->value(), r0);
1916
1917 ASSERT(instr->object()->representation().IsTagged());
1918 ASSERT(instr->key()->representation().IsTagged());
1919 ASSERT(instr->value()->representation().IsTagged());
1920
1921 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1922}
1923
1924
1925LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001926 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001927
1928 LOperand* obj = needs_write_barrier
1929 ? UseTempRegister(instr->object())
1930 : UseRegisterAtStart(instr->object());
1931
1932 LOperand* val = needs_write_barrier
1933 ? UseTempRegister(instr->value())
1934 : UseRegister(instr->value());
1935
Ben Murdochb8e0da22011-05-16 14:20:40 +01001936 return new LStoreNamedField(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001937}
1938
1939
1940LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1941 LOperand* obj = UseFixed(instr->object(), r1);
1942 LOperand* val = UseFixed(instr->value(), r0);
1943
Ben Murdochb8e0da22011-05-16 14:20:40 +01001944 LInstruction* result = new LStoreNamedGeneric(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001945 return MarkAsCall(result, instr);
1946}
1947
1948
Steve Block1e0659c2011-05-24 12:43:12 +01001949LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1950 LOperand* string = UseRegister(instr->string());
1951 LOperand* index = UseRegisterOrConstant(instr->index());
1952 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
1953 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1954}
1955
1956
Steve Block44f0eee2011-05-26 01:26:41 +01001957LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
1958 LOperand* char_code = UseRegister(instr->value());
1959 LStringCharFromCode* result = new LStringCharFromCode(char_code);
1960 return AssignPointerMap(DefineAsRegister(result));
1961}
1962
1963
Steve Block1e0659c2011-05-24 12:43:12 +01001964LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1965 LOperand* string = UseRegisterAtStart(instr->value());
1966 return DefineAsRegister(new LStringLength(string));
1967}
1968
1969
Ben Murdochb0fe1622011-05-05 13:52:32 +01001970LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1971 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
1972}
1973
1974
1975LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1976 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
1977}
1978
1979
1980LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1981 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
1982}
1983
1984
1985LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1986 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
1987}
1988
1989
1990LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001991 LOperand* object = UseFixed(instr->object(), r0);
1992 LOperand* key = UseFixed(instr->key(), r1);
1993 LDeleteProperty* result = new LDeleteProperty(object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001994 return MarkAsCall(DefineFixed(result, r0), instr);
1995}
1996
1997
1998LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1999 allocator_->MarkAsOsrEntry();
2000 current_block_->last_environment()->set_ast_id(instr->ast_id());
2001 return AssignEnvironment(new LOsrEntry);
2002}
2003
2004
2005LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2006 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2007 return DefineAsSpilled(new LParameter, spill_index);
2008}
2009
2010
2011LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2012 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +01002013 if (spill_index > LUnallocated::kMaxFixedIndex) {
2014 Abort("Too many spill slots needed for OSR");
2015 spill_index = 0;
2016 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002017 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
2018}
2019
2020
2021LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2022 argument_count_ -= instr->argument_count();
2023 return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
2024}
2025
2026
2027LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002028 // There are no real uses of the arguments object.
2029 // arguments.length and element access are supported directly on
2030 // stack arguments, and any real arguments object use causes a bailout.
2031 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002032 return NULL;
2033}
2034
2035
2036LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2037 LOperand* arguments = UseRegister(instr->arguments());
2038 LOperand* length = UseTempRegister(instr->length());
Ben Murdoch086aeea2011-05-13 15:57:08 +01002039 LOperand* index = UseRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01002040 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2041 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002042}
2043
2044
Steve Block44f0eee2011-05-26 01:26:41 +01002045LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2046 LOperand* object = UseFixed(instr->value(), r0);
2047 LToFastProperties* result = new LToFastProperties(object);
2048 return MarkAsCall(DefineFixed(result, r0), instr);
2049}
2050
2051
Ben Murdochb0fe1622011-05-05 13:52:32 +01002052LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01002053 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
Ben Murdochb0fe1622011-05-05 13:52:32 +01002054 return MarkAsCall(DefineFixed(result, r0), instr);
2055}
2056
2057
2058LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
2059 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
2060}
2061
Steve Block1e0659c2011-05-24 12:43:12 +01002062
2063LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
2064 return DefineAsRegister(new LIsConstructCall());
2065}
2066
2067
Ben Murdochb0fe1622011-05-05 13:52:32 +01002068LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2069 HEnvironment* env = current_block_->last_environment();
2070 ASSERT(env != NULL);
2071
2072 env->set_ast_id(instr->ast_id());
2073
2074 env->Drop(instr->pop_count());
2075 for (int i = 0; i < instr->values()->length(); ++i) {
2076 HValue* value = instr->values()->at(i);
2077 if (instr->HasAssignedIndexAt(i)) {
2078 env->Bind(instr->GetAssignedIndexAt(i), value);
2079 } else {
2080 env->Push(value);
2081 }
2082 }
2083
Ben Murdochb0fe1622011-05-05 13:52:32 +01002084 // If there is an instruction pending deoptimization environment create a
2085 // lazy bailout instruction to capture the environment.
2086 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2087 LInstruction* result = new LLazyBailout;
2088 result = AssignEnvironment(result);
Steve Block1e0659c2011-05-24 12:43:12 +01002089 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002090 set_deoptimization_environment(result->environment());
2091 ClearInstructionPendingDeoptimizationEnvironment();
2092 return result;
2093 }
2094
2095 return NULL;
2096}
2097
2098
2099LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2100 return MarkAsCall(new LStackCheck, instr);
2101}
2102
2103
2104LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2105 HEnvironment* outer = current_block_->last_environment();
2106 HConstant* undefined = graph()->GetConstantUndefined();
2107 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2108 instr->function(),
2109 false,
2110 undefined);
2111 current_block_->UpdateEnvironment(inner);
2112 chunk_->AddInlinedClosure(instr->closure());
2113 return NULL;
2114}
2115
2116
2117LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2118 HEnvironment* outer = current_block_->last_environment()->outer();
2119 current_block_->UpdateEnvironment(outer);
2120 return NULL;
2121}
2122
2123
Ben Murdochb0fe1622011-05-05 13:52:32 +01002124} } // namespace v8::internal