blob: 12b952d22643eda8e3b328853da673ef57a78934 [file] [log] [blame]
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// 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
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000028#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_X64)
31
ricow@chromium.org83aa5492011-02-07 12:42:56 +000032#include "lithium-allocator-inl.h"
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000033#include "x64/lithium-x64.h"
34#include "x64/lithium-codegen-x64.h"
35
36namespace v8 {
37namespace internal {
38
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000039#define DEFINE_COMPILE(type) \
40 void L##type::CompileToNative(LCodeGen* generator) { \
41 generator->Do##type(this); \
42 }
43LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
44#undef DEFINE_COMPILE
45
46LOsrEntry::LOsrEntry() {
47 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
48 register_spills_[i] = NULL;
49 }
50 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
51 double_register_spills_[i] = NULL;
52 }
53}
54
55
56void LOsrEntry::MarkSpilledRegister(int allocation_index,
57 LOperand* spill_operand) {
58 ASSERT(spill_operand->IsStackSlot());
59 ASSERT(register_spills_[allocation_index] == NULL);
60 register_spills_[allocation_index] = spill_operand;
61}
62
63
64void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
65 LOperand* spill_operand) {
66 ASSERT(spill_operand->IsDoubleStackSlot());
67 ASSERT(double_register_spills_[allocation_index] == NULL);
68 double_register_spills_[allocation_index] = spill_operand;
69}
70
71
ricow@chromium.org83aa5492011-02-07 12:42:56 +000072#ifdef DEBUG
73void LInstruction::VerifyCall() {
74 // Call instructions can use only fixed registers as
75 // temporaries and outputs because all registers
76 // are blocked by the calling convention.
77 // Inputs can use either fixed register or have a short lifetime (be
78 // used at start of the instruction).
79 ASSERT(Output() == NULL ||
80 LUnallocated::cast(Output())->HasFixedPolicy() ||
81 !LUnallocated::cast(Output())->HasRegisterPolicy());
82 for (UseIterator it(this); it.HasNext(); it.Advance()) {
83 LOperand* operand = it.Next();
84 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
85 LUnallocated::cast(operand)->IsUsedAtStart() ||
86 !LUnallocated::cast(operand)->HasRegisterPolicy());
87 }
88 for (TempIterator it(this); it.HasNext(); it.Advance()) {
89 LOperand* operand = it.Next();
90 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
91 !LUnallocated::cast(operand)->HasRegisterPolicy());
92 }
93}
94#endif
95
96
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000097void LInstruction::PrintTo(StringStream* stream) {
98 stream->Add("%s ", this->Mnemonic());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000099
100 PrintOutputOperandTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000101
102 PrintDataTo(stream);
103
104 if (HasEnvironment()) {
105 stream->Add(" ");
106 environment()->PrintTo(stream);
107 }
108
109 if (HasPointerMap()) {
110 stream->Add(" ");
111 pointer_map()->PrintTo(stream);
112 }
113}
114
115
116template<int R, int I, int T>
117void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000118 stream->Add("= ");
119 inputs_.PrintOperandsTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000120}
121
122
123template<int R, int I, int T>
124void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000125 results_.PrintOperandsTo(stream);
126}
127
128
129template<typename T, int N>
130void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
131 for (int i = 0; i < N; i++) {
132 if (i > 0) stream->Add(" ");
133 elems_[i]->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000134 }
135}
136
137
138void LLabel::PrintDataTo(StringStream* stream) {
139 LGap::PrintDataTo(stream);
140 LLabel* rep = replacement();
141 if (rep != NULL) {
142 stream->Add(" Dead block replaced with B%d", rep->block_id());
143 }
144}
145
146
147bool LGap::IsRedundant() const {
148 for (int i = 0; i < 4; i++) {
149 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
150 return false;
151 }
152 }
153
154 return true;
155}
156
157
158void LGap::PrintDataTo(StringStream* stream) {
159 for (int i = 0; i < 4; i++) {
160 stream->Add("(");
161 if (parallel_moves_[i] != NULL) {
162 parallel_moves_[i]->PrintDataTo(stream);
163 }
164 stream->Add(") ");
165 }
166}
167
168
169const char* LArithmeticD::Mnemonic() const {
170 switch (op()) {
171 case Token::ADD: return "add-d";
172 case Token::SUB: return "sub-d";
173 case Token::MUL: return "mul-d";
174 case Token::DIV: return "div-d";
175 case Token::MOD: return "mod-d";
176 default:
177 UNREACHABLE();
178 return NULL;
179 }
180}
181
182
183const char* LArithmeticT::Mnemonic() const {
184 switch (op()) {
185 case Token::ADD: return "add-t";
186 case Token::SUB: return "sub-t";
187 case Token::MUL: return "mul-t";
188 case Token::MOD: return "mod-t";
189 case Token::DIV: return "div-t";
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000190 case Token::BIT_AND: return "bit-and-t";
191 case Token::BIT_OR: return "bit-or-t";
192 case Token::BIT_XOR: return "bit-xor-t";
193 case Token::SHL: return "sal-t";
194 case Token::SAR: return "sar-t";
195 case Token::SHR: return "shr-t";
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000196 default:
197 UNREACHABLE();
198 return NULL;
199 }
200}
201
202
203void LGoto::PrintDataTo(StringStream* stream) {
204 stream->Add("B%d", block_id());
205}
206
207
208void LBranch::PrintDataTo(StringStream* stream) {
209 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000210 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000211}
212
213
214void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
215 stream->Add("if ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000216 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000217 stream->Add(" %s ", Token::String(op()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000218 InputAt(1)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000219 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
220}
221
222
223void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
224 stream->Add("if ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000225 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000226 stream->Add(is_strict() ? " === null" : " == null");
227 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
228}
229
230
231void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
232 stream->Add("if is_object(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000233 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000234 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
235}
236
237
238void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
239 stream->Add("if is_smi(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000240 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000241 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
242}
243
244
245void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
246 stream->Add("if has_instance_type(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000247 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000248 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
249}
250
251
252void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
253 stream->Add("if has_cached_array_index(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000254 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000255 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
256}
257
258
259void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
260 stream->Add("if class_of_test(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000261 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000262 stream->Add(", \"%o\") then B%d else B%d",
263 *hydrogen()->class_name(),
264 true_block_id(),
265 false_block_id());
266}
267
268
269void LTypeofIs::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000270 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000271 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
272}
273
274
275void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
276 stream->Add("if typeof ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000277 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000278 stream->Add(" == \"%s\" then B%d else B%d",
279 *hydrogen()->type_literal()->ToCString(),
280 true_block_id(), false_block_id());
281}
282
283
284void LCallConstantFunction::PrintDataTo(StringStream* stream) {
285 stream->Add("#%d / ", arity());
286}
287
288
289void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
290 stream->Add("/%s ", hydrogen()->OpName());
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000291 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000292}
293
294
295void LLoadContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000296 InputAt(0)->PrintTo(stream);
297 stream->Add("[%d]", slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000298}
299
300
301void LCallKeyed::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000302 stream->Add("[ecx] #%d / ", arity());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000303}
304
305
306void LCallNamed::PrintDataTo(StringStream* stream) {
307 SmartPointer<char> name_string = name()->ToCString();
308 stream->Add("%s #%d / ", *name_string, arity());
309}
310
311
312void LCallGlobal::PrintDataTo(StringStream* stream) {
313 SmartPointer<char> name_string = name()->ToCString();
314 stream->Add("%s #%d / ", *name_string, arity());
315}
316
317
318void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
319 stream->Add("#%d / ", arity());
320}
321
322
323void LCallNew::PrintDataTo(StringStream* stream) {
324 stream->Add("= ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000325 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000326 stream->Add(" #%d / ", arity());
327}
328
329
330void LClassOfTest::PrintDataTo(StringStream* stream) {
331 stream->Add("= class_of_test(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000332 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000333 stream->Add(", \"%o\")", *hydrogen()->class_name());
334}
335
336
337void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
338 arguments()->PrintTo(stream);
339
340 stream->Add(" length ");
341 length()->PrintTo(stream);
342
343 stream->Add(" index ");
344 index()->PrintTo(stream);
345}
346
347
348int LChunk::GetNextSpillIndex(bool is_double) {
349 return spill_slot_count_++;
350}
351
352
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000353LOperand* LChunk::GetNextSpillSlot(bool is_double) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000354 // All stack slots are Double stack slots on x64.
355 // Alternatively, at some point, start using half-size
356 // stack slots for int32 values.
357 int index = GetNextSpillIndex(is_double);
358 if (is_double) {
359 return LDoubleStackSlot::Create(index);
360 } else {
361 return LStackSlot::Create(index);
362 }
363}
364
365
366void LChunk::MarkEmptyBlocks() {
367 HPhase phase("Mark empty blocks", this);
368 for (int i = 0; i < graph()->blocks()->length(); ++i) {
369 HBasicBlock* block = graph()->blocks()->at(i);
370 int first = block->first_instruction_index();
371 int last = block->last_instruction_index();
372 LInstruction* first_instr = instructions()->at(first);
373 LInstruction* last_instr = instructions()->at(last);
374
375 LLabel* label = LLabel::cast(first_instr);
376 if (last_instr->IsGoto()) {
377 LGoto* goto_instr = LGoto::cast(last_instr);
378 if (!goto_instr->include_stack_check() &&
379 label->IsRedundant() &&
380 !label->is_loop_header()) {
381 bool can_eliminate = true;
382 for (int i = first + 1; i < last && can_eliminate; ++i) {
383 LInstruction* cur = instructions()->at(i);
384 if (cur->IsGap()) {
385 LGap* gap = LGap::cast(cur);
386 if (!gap->IsRedundant()) {
387 can_eliminate = false;
388 }
389 } else {
390 can_eliminate = false;
391 }
392 }
393
394 if (can_eliminate) {
395 label->set_replacement(GetLabel(goto_instr->block_id()));
396 }
397 }
398 }
399 }
400}
401
402
403void LStoreNamed::PrintDataTo(StringStream* stream) {
404 object()->PrintTo(stream);
405 stream->Add(".");
406 stream->Add(*String::cast(*name())->ToCString());
407 stream->Add(" <- ");
408 value()->PrintTo(stream);
409}
410
411
412void LStoreKeyed::PrintDataTo(StringStream* stream) {
413 object()->PrintTo(stream);
414 stream->Add("[");
415 key()->PrintTo(stream);
416 stream->Add("] <- ");
417 value()->PrintTo(stream);
418}
419
420
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000421void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000422 LGap* gap = new LGap(block);
423 int index = -1;
424 if (instr->IsControl()) {
425 instructions_.Add(gap);
426 index = instructions_.length();
427 instructions_.Add(instr);
428 } else {
429 index = instructions_.length();
430 instructions_.Add(instr);
431 instructions_.Add(gap);
432 }
433 if (instr->HasPointerMap()) {
434 pointer_maps_.Add(instr->pointer_map());
435 instr->pointer_map()->set_lithium_position(index);
436 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000437}
438
439
440LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
441 return LConstantOperand::Create(constant->id());
442}
443
444
445int LChunk::GetParameterStackSlot(int index) const {
446 // The receiver is at index 0, the first parameter at index 1, so we
447 // shift all parameter indexes down by the number of parameters, and
448 // make sure they end up negative so they are distinguishable from
449 // spill slots.
450 int result = index - graph()->info()->scope()->num_parameters() - 1;
451 ASSERT(result < 0);
452 return result;
453}
454
455// A parameter relative to ebp in the arguments stub.
456int LChunk::ParameterAt(int index) {
457 ASSERT(-1 <= index); // -1 is the receiver.
458 return (1 + graph()->info()->scope()->num_parameters() - index) *
459 kPointerSize;
460}
461
462
463LGap* LChunk::GetGapAt(int index) const {
464 return LGap::cast(instructions_[index]);
465}
466
467
468bool LChunk::IsGapAt(int index) const {
469 return instructions_[index]->IsGap();
470}
471
472
473int LChunk::NearestGapPos(int index) const {
474 while (!IsGapAt(index)) index--;
475 return index;
476}
477
478
479void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
480 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
481}
482
483
484Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
485 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
486}
487
488
489Representation LChunk::LookupLiteralRepresentation(
490 LConstantOperand* operand) const {
491 return graph_->LookupValue(operand->index())->representation();
492}
493
494
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000495LChunk* LChunkBuilder::Build() {
496 ASSERT(is_unused());
497 chunk_ = new LChunk(graph());
498 HPhase phase("Building chunk", chunk_);
499 status_ = BUILDING;
500 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
501 for (int i = 0; i < blocks->length(); i++) {
502 HBasicBlock* next = NULL;
503 if (i < blocks->length() - 1) next = blocks->at(i + 1);
504 DoBasicBlock(blocks->at(i), next);
505 if (is_aborted()) return NULL;
506 }
507 status_ = DONE;
508 return chunk_;
509}
510
511
512void LChunkBuilder::Abort(const char* format, ...) {
513 if (FLAG_trace_bailout) {
514 SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
515 PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
516 va_list arguments;
517 va_start(arguments, format);
518 OS::VPrint(format, arguments);
519 va_end(arguments);
520 PrintF("\n");
521 }
522 status_ = ABORTED;
523}
524
525
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000526LRegister* LChunkBuilder::ToOperand(Register reg) {
527 return LRegister::Create(Register::ToAllocationIndex(reg));
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000528}
529
530
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000531LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
532 return new LUnallocated(LUnallocated::FIXED_REGISTER,
533 Register::ToAllocationIndex(reg));
534}
535
536
537LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
538 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
539 XMMRegister::ToAllocationIndex(reg));
540}
541
542
543LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
544 return Use(value, ToUnallocated(fixed_register));
545}
546
547
548LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
549 return Use(value, ToUnallocated(reg));
550}
551
552
553LOperand* LChunkBuilder::UseRegister(HValue* value) {
554 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
555}
556
557
558LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
559 return Use(value,
560 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
561 LUnallocated::USED_AT_START));
562}
563
564
565LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
566 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
567}
568
569
570LOperand* LChunkBuilder::Use(HValue* value) {
571 return Use(value, new LUnallocated(LUnallocated::NONE));
572}
573
574
575LOperand* LChunkBuilder::UseAtStart(HValue* value) {
576 return Use(value, new LUnallocated(LUnallocated::NONE,
577 LUnallocated::USED_AT_START));
578}
579
580
581LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
582 return value->IsConstant()
583 ? chunk_->DefineConstantOperand(HConstant::cast(value))
584 : Use(value);
585}
586
587
588LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
589 return value->IsConstant()
590 ? chunk_->DefineConstantOperand(HConstant::cast(value))
591 : UseAtStart(value);
592}
593
594
595LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
596 return value->IsConstant()
597 ? chunk_->DefineConstantOperand(HConstant::cast(value))
598 : UseRegister(value);
599}
600
601
602LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
603 return value->IsConstant()
604 ? chunk_->DefineConstantOperand(HConstant::cast(value))
605 : UseRegisterAtStart(value);
606}
607
608
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000609LOperand* LChunkBuilder::UseAny(HValue* value) {
610 return value->IsConstant()
611 ? chunk_->DefineConstantOperand(HConstant::cast(value))
612 : Use(value, new LUnallocated(LUnallocated::ANY));
613}
614
615
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000616LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
617 if (value->EmitAtUses()) {
618 HInstruction* instr = HInstruction::cast(value);
619 VisitInstruction(instr);
620 }
621 allocator_->RecordUse(value, operand);
622 return operand;
623}
624
625
626template<int I, int T>
627LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
628 LUnallocated* result) {
629 allocator_->RecordDefinition(current_instruction_, result);
630 instr->set_result(result);
631 return instr;
632}
633
634
635template<int I, int T>
636LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
637 return Define(instr, new LUnallocated(LUnallocated::NONE));
638}
639
640
641template<int I, int T>
642LInstruction* LChunkBuilder::DefineAsRegister(
643 LTemplateInstruction<1, I, T>* instr) {
644 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
645}
646
647
648template<int I, int T>
649LInstruction* LChunkBuilder::DefineAsSpilled(
650 LTemplateInstruction<1, I, T>* instr,
651 int index) {
652 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
653}
654
655
656template<int I, int T>
657LInstruction* LChunkBuilder::DefineSameAsFirst(
658 LTemplateInstruction<1, I, T>* instr) {
659 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
660}
661
662
663template<int I, int T>
664LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
665 Register reg) {
666 return Define(instr, ToUnallocated(reg));
667}
668
669
670template<int I, int T>
671LInstruction* LChunkBuilder::DefineFixedDouble(
672 LTemplateInstruction<1, I, T>* instr,
673 XMMRegister reg) {
674 return Define(instr, ToUnallocated(reg));
675}
676
677
678LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
679 HEnvironment* hydrogen_env = current_block_->last_environment();
680 instr->set_environment(CreateEnvironment(hydrogen_env));
681 return instr;
682}
683
684
fschneider@chromium.org1df6b472011-01-26 08:23:03 +0000685LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
686 LInstruction* instr, int ast_id) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000687 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
fschneider@chromium.org1df6b472011-01-26 08:23:03 +0000688 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000689 instruction_pending_deoptimization_environment_ = instr;
fschneider@chromium.org1df6b472011-01-26 08:23:03 +0000690 pending_deoptimization_ast_id_ = ast_id;
691 return instr;
692}
693
694
695void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000696 instruction_pending_deoptimization_environment_ = NULL;
fschneider@chromium.org1df6b472011-01-26 08:23:03 +0000697 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
698}
699
700
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000701LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
702 HInstruction* hinstr,
703 CanDeoptimize can_deoptimize) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000704#ifdef DEBUG
705 instr->VerifyCall();
706#endif
707 instr->MarkAsCall();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000708 instr = AssignPointerMap(instr);
709
710 if (hinstr->HasSideEffects()) {
711 ASSERT(hinstr->next()->IsSimulate());
712 HSimulate* sim = HSimulate::cast(hinstr->next());
fschneider@chromium.org1df6b472011-01-26 08:23:03 +0000713 instr = SetInstructionPendingDeoptimizationEnvironment(
714 instr, sim->ast_id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000715 }
716
717 // If instruction does not have side-effects lazy deoptimization
718 // after the call will try to deoptimize to the point before the call.
719 // Thus we still need to attach environment to this call even if
720 // call sequence can not deoptimize eagerly.
721 bool needs_environment =
722 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
723 if (needs_environment && !instr->HasEnvironment()) {
724 instr = AssignEnvironment(instr);
725 }
726
727 return instr;
728}
729
730
731LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000732 instr->MarkAsSaveDoubles();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000733 return instr;
734}
735
736
737LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
738 ASSERT(!instr->HasPointerMap());
739 instr->set_pointer_map(new LPointerMap(position_));
740 return instr;
741}
742
743
744LUnallocated* LChunkBuilder::TempRegister() {
745 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
746 allocator_->RecordTemporary(operand);
747 return operand;
748}
749
750
751LOperand* LChunkBuilder::FixedTemp(Register reg) {
752 LUnallocated* operand = ToUnallocated(reg);
753 allocator_->RecordTemporary(operand);
754 return operand;
755}
756
757
758LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
759 LUnallocated* operand = ToUnallocated(reg);
760 allocator_->RecordTemporary(operand);
761 return operand;
762}
763
764
765LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
766 return new LLabel(instr->block());
767}
768
769
770LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
771 return AssignEnvironment(new LDeoptimize);
772}
773
774
775LInstruction* LChunkBuilder::DoBit(Token::Value op,
776 HBitwiseBinaryOperation* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000777 if (instr->representation().IsInteger32()) {
778 ASSERT(instr->left()->representation().IsInteger32());
779 ASSERT(instr->right()->representation().IsInteger32());
780
781 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
782 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
783 return DefineSameAsFirst(new LBitI(op, left, right));
784 } else {
785 ASSERT(instr->representation().IsTagged());
786 ASSERT(instr->left()->representation().IsTagged());
787 ASSERT(instr->right()->representation().IsTagged());
788
789 LOperand* left = UseFixed(instr->left(), rdx);
790 LOperand* right = UseFixed(instr->right(), rax);
791 LArithmeticT* result = new LArithmeticT(op, left, right);
792 return MarkAsCall(DefineFixed(result, rax), instr);
793 }
794}
795
796
797LInstruction* LChunkBuilder::DoShift(Token::Value op,
798 HBitwiseBinaryOperation* instr) {
799 if (instr->representation().IsTagged()) {
800 ASSERT(instr->left()->representation().IsTagged());
801 ASSERT(instr->right()->representation().IsTagged());
802
803 LOperand* left = UseFixed(instr->left(), rdx);
804 LOperand* right = UseFixed(instr->right(), rax);
805 LArithmeticT* result = new LArithmeticT(op, left, right);
806 return MarkAsCall(DefineFixed(result, rax), instr);
807 }
808
809 ASSERT(instr->representation().IsInteger32());
810 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
811 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
812 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
813
814 HValue* right_value = instr->OperandAt(1);
815 LOperand* right = NULL;
816 int constant_value = 0;
817 if (right_value->IsConstant()) {
818 HConstant* constant = HConstant::cast(right_value);
819 right = chunk_->DefineConstantOperand(constant);
820 constant_value = constant->Integer32Value() & 0x1f;
821 } else {
822 right = UseFixed(right_value, rcx);
823 }
824
825 // Shift operations can only deoptimize if we do a logical shift
826 // by 0 and the result cannot be truncated to int32.
827 bool can_deopt = (op == Token::SHR && constant_value == 0);
828 if (can_deopt) {
829 bool can_truncate = true;
830 for (int i = 0; i < instr->uses()->length(); i++) {
831 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
832 can_truncate = false;
833 break;
834 }
835 }
836 can_deopt = !can_truncate;
837 }
838
839 LShiftI* result = new LShiftI(op, left, right, can_deopt);
840 return can_deopt
841 ? AssignEnvironment(DefineSameAsFirst(result))
842 : DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000843}
844
845
846LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
847 HArithmeticBinaryOperation* instr) {
848 Abort("Unimplemented: %s", "DoArithmeticD");
849 return NULL;
850}
851
852
853LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
854 HArithmeticBinaryOperation* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000855 ASSERT(op == Token::ADD ||
856 op == Token::DIV ||
857 op == Token::MOD ||
858 op == Token::MUL ||
859 op == Token::SUB);
860 HValue* left = instr->left();
861 HValue* right = instr->right();
862 ASSERT(left->representation().IsTagged());
863 ASSERT(right->representation().IsTagged());
864 LOperand* left_operand = UseFixed(left, rdx);
865 LOperand* right_operand = UseFixed(right, rax);
866 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
867 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000868}
869
870
871void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
872 ASSERT(is_building());
873 current_block_ = block;
874 next_block_ = next_block;
875 if (block->IsStartBlock()) {
876 block->UpdateEnvironment(graph_->start_environment());
877 argument_count_ = 0;
878 } else if (block->predecessors()->length() == 1) {
879 // We have a single predecessor => copy environment and outgoing
880 // argument count from the predecessor.
881 ASSERT(block->phis()->length() == 0);
882 HBasicBlock* pred = block->predecessors()->at(0);
883 HEnvironment* last_environment = pred->last_environment();
884 ASSERT(last_environment != NULL);
885 // Only copy the environment, if it is later used again.
886 if (pred->end()->SecondSuccessor() == NULL) {
887 ASSERT(pred->end()->FirstSuccessor() == block);
888 } else {
889 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
890 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
891 last_environment = last_environment->Copy();
892 }
893 }
894 block->UpdateEnvironment(last_environment);
895 ASSERT(pred->argument_count() >= 0);
896 argument_count_ = pred->argument_count();
897 } else {
898 // We are at a state join => process phis.
899 HBasicBlock* pred = block->predecessors()->at(0);
900 // No need to copy the environment, it cannot be used later.
901 HEnvironment* last_environment = pred->last_environment();
902 for (int i = 0; i < block->phis()->length(); ++i) {
903 HPhi* phi = block->phis()->at(i);
904 last_environment->SetValueAt(phi->merged_index(), phi);
905 }
906 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
907 last_environment->SetValueAt(block->deleted_phis()->at(i),
908 graph_->GetConstantUndefined());
909 }
910 block->UpdateEnvironment(last_environment);
911 // Pick up the outgoing argument count of one of the predecessors.
912 argument_count_ = pred->argument_count();
913 }
914 HInstruction* current = block->first();
915 int start = chunk_->instructions()->length();
916 while (current != NULL && !is_aborted()) {
917 // Code for constants in registers is generated lazily.
918 if (!current->EmitAtUses()) {
919 VisitInstruction(current);
920 }
921 current = current->next();
922 }
923 int end = chunk_->instructions()->length() - 1;
924 if (end >= start) {
925 block->set_first_instruction_index(start);
926 block->set_last_instruction_index(end);
927 }
928 block->set_argument_count(argument_count_);
929 next_block_ = NULL;
930 current_block_ = NULL;
931}
932
933
934void LChunkBuilder::VisitInstruction(HInstruction* current) {
935 HInstruction* old_current = current_instruction_;
936 current_instruction_ = current;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000937 if (current->has_position()) position_ = current->position();
938 LInstruction* instr = current->CompileToLithium(this);
939
940 if (instr != NULL) {
941 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
942 instr = AssignPointerMap(instr);
943 }
944 if (FLAG_stress_environments && !instr->HasEnvironment()) {
945 instr = AssignEnvironment(instr);
946 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000947 if (current->IsTest() && !instr->IsGoto()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000948 ASSERT(instr->IsControl());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000949 HTest* test = HTest::cast(current);
950 instr->set_hydrogen_value(test->value());
951 HBasicBlock* first = test->FirstSuccessor();
952 HBasicBlock* second = test->SecondSuccessor();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000953 ASSERT(first != NULL && second != NULL);
954 instr->SetBranchTargets(first->block_id(), second->block_id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000955 } else {
956 instr->set_hydrogen_value(current);
957 }
958
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000959 chunk_->AddInstruction(instr, current_block_);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000960 }
961 current_instruction_ = old_current;
962}
963
964
965LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
966 if (hydrogen_env == NULL) return NULL;
967
968 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
969 int ast_id = hydrogen_env->ast_id();
970 ASSERT(ast_id != AstNode::kNoNumber);
971 int value_count = hydrogen_env->length();
972 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
973 ast_id,
974 hydrogen_env->parameter_count(),
975 argument_count_,
976 value_count,
977 outer);
978 int argument_index = 0;
979 for (int i = 0; i < value_count; ++i) {
980 HValue* value = hydrogen_env->values()->at(i);
981 LOperand* op = NULL;
982 if (value->IsArgumentsObject()) {
983 op = NULL;
984 } else if (value->IsPushArgument()) {
985 op = new LArgument(argument_index++);
986 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000987 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000988 }
989 result->AddValue(op, value->representation());
990 }
991
992 return result;
993}
994
995
996LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
997 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(),
998 instr->include_stack_check());
999 return (instr->include_stack_check())
1000 ? AssignPointerMap(result)
1001 : result;
1002}
1003
1004
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001005LInstruction* LChunkBuilder::DoTest(HTest* instr) {
1006 HValue* v = instr->value();
1007 if (v->EmitAtUses()) {
1008 if (v->IsClassOfTest()) {
1009 HClassOfTest* compare = HClassOfTest::cast(v);
1010 ASSERT(compare->value()->representation().IsTagged());
1011
1012 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
1013 TempRegister());
1014 } else if (v->IsCompare()) {
1015 HCompare* compare = HCompare::cast(v);
1016 Token::Value op = compare->token();
1017 HValue* left = compare->left();
1018 HValue* right = compare->right();
1019 Representation r = compare->GetInputRepresentation();
1020 if (r.IsInteger32()) {
1021 ASSERT(left->representation().IsInteger32());
1022 ASSERT(right->representation().IsInteger32());
1023
1024 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1025 UseOrConstantAtStart(right));
1026 } else if (r.IsDouble()) {
1027 ASSERT(left->representation().IsDouble());
1028 ASSERT(right->representation().IsDouble());
1029
1030 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1031 UseRegisterAtStart(right));
1032 } else {
1033 ASSERT(left->representation().IsTagged());
1034 ASSERT(right->representation().IsTagged());
1035 bool reversed = op == Token::GT || op == Token::LTE;
1036 LOperand* left_operand = UseFixed(left, reversed ? rax : rdx);
1037 LOperand* right_operand = UseFixed(right, reversed ? rdx : rax);
1038 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand,
1039 right_operand);
1040 return MarkAsCall(result, instr);
1041 }
1042 } else if (v->IsIsSmi()) {
1043 HIsSmi* compare = HIsSmi::cast(v);
1044 ASSERT(compare->value()->representation().IsTagged());
1045
1046 return new LIsSmiAndBranch(Use(compare->value()));
1047 } else if (v->IsHasInstanceType()) {
1048 HHasInstanceType* compare = HHasInstanceType::cast(v);
1049 ASSERT(compare->value()->representation().IsTagged());
1050
1051 return new LHasInstanceTypeAndBranch(
1052 UseRegisterAtStart(compare->value()));
1053 } else if (v->IsHasCachedArrayIndex()) {
1054 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1055 ASSERT(compare->value()->representation().IsTagged());
1056
1057 return new LHasCachedArrayIndexAndBranch(
1058 UseRegisterAtStart(compare->value()));
1059 } else if (v->IsIsNull()) {
1060 HIsNull* compare = HIsNull::cast(v);
1061 ASSERT(compare->value()->representation().IsTagged());
1062
1063 // We only need a temp register for non-strict compare.
1064 LOperand* temp = compare->is_strict() ? NULL : TempRegister();
1065 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
1066 temp);
1067 } else if (v->IsIsObject()) {
1068 HIsObject* compare = HIsObject::cast(v);
1069 ASSERT(compare->value()->representation().IsTagged());
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001070 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001071 } else if (v->IsCompareJSObjectEq()) {
1072 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1073 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
1074 UseRegisterAtStart(compare->right()));
1075 } else if (v->IsInstanceOf()) {
1076 HInstanceOf* instance_of = HInstanceOf::cast(v);
1077 LInstanceOfAndBranch* result =
1078 new LInstanceOfAndBranch(
1079 UseFixed(instance_of->left(), InstanceofStub::left()),
1080 UseFixed(instance_of->right(), InstanceofStub::right()));
1081 return MarkAsCall(result, instr);
1082 } else if (v->IsTypeofIs()) {
1083 HTypeofIs* typeof_is = HTypeofIs::cast(v);
1084 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1085 } else {
1086 if (v->IsConstant()) {
1087 if (HConstant::cast(v)->handle()->IsTrue()) {
1088 return new LGoto(instr->FirstSuccessor()->block_id());
1089 } else if (HConstant::cast(v)->handle()->IsFalse()) {
1090 return new LGoto(instr->SecondSuccessor()->block_id());
1091 }
1092 }
1093 Abort("Undefined compare before branch");
1094 return NULL;
1095 }
1096 }
1097 return new LBranch(UseRegisterAtStart(v));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001098}
1099
1100
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001101LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001102 ASSERT(instr->value()->representation().IsTagged());
1103 LOperand* value = UseRegisterAtStart(instr->value());
1104 return new LCmpMapAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001105}
1106
1107
1108LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1109 Abort("Unimplemented: %s", "DoArgumentsLength");
1110 return NULL;
1111}
1112
1113
1114LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1115 Abort("Unimplemented: %s", "DoArgumentsElements");
1116 return NULL;
1117}
1118
1119
1120LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1121 Abort("Unimplemented: %s", "DoInstanceOf");
1122 return NULL;
1123}
1124
1125
1126LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1127 HInstanceOfKnownGlobal* instr) {
1128 Abort("Unimplemented: %s", "DoInstanceOfKnownGlobal");
1129 return NULL;
1130}
1131
1132
1133LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1134 Abort("Unimplemented: %s", "DoApplyArguments");
1135 return NULL;
1136}
1137
1138
1139LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001140 ++argument_count_;
1141 LOperand* argument = UseOrConstant(instr->argument());
1142 return new LPushArgument(argument);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001143}
1144
1145
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001146LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1147 Abort("Unimplemented: DoContext");
1148 return NULL;
1149}
1150
1151
1152LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1153 Abort("Unimplemented: DoOuterContext");
1154 return NULL;
1155}
1156
1157
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001158LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001159 return DefineAsRegister(new LGlobalObject);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001160}
1161
1162
1163LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001164 return DefineAsRegister(new LGlobalReceiver);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001165}
1166
1167
1168LInstruction* LChunkBuilder::DoCallConstantFunction(
1169 HCallConstantFunction* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001170 argument_count_ -= instr->argument_count();
1171 return MarkAsCall(DefineFixed(new LCallConstantFunction, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001172}
1173
1174
1175LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1176 Abort("Unimplemented: %s", "DoUnaryMathOperation");
1177 return NULL;
1178}
1179
1180
1181LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1182 Abort("Unimplemented: %s", "DoCallKeyed");
1183 return NULL;
1184}
1185
1186
1187LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001188 argument_count_ -= instr->argument_count();
1189 return MarkAsCall(DefineFixed(new LCallNamed, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001190}
1191
1192
1193LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1194 Abort("Unimplemented: %s", "DoCallGlobal");
1195 return NULL;
1196}
1197
1198
1199LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001200 argument_count_ -= instr->argument_count();
1201 return MarkAsCall(DefineFixed(new LCallKnownGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001202}
1203
1204
1205LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001206 LOperand* constructor = UseFixed(instr->constructor(), rdi);
1207 argument_count_ -= instr->argument_count();
1208 LCallNew* result = new LCallNew(constructor);
1209 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001210}
1211
1212
1213LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1214 Abort("Unimplemented: %s", "DoCallFunction");
1215 return NULL;
1216}
1217
1218
1219LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001220 argument_count_ -= instr->argument_count();
1221 return MarkAsCall(DefineFixed(new LCallRuntime, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001222}
1223
1224
1225LInstruction* LChunkBuilder::DoShr(HShr* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001226 return DoShift(Token::SHR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001227}
1228
1229
1230LInstruction* LChunkBuilder::DoSar(HSar* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001231 return DoShift(Token::SAR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001232}
1233
1234
1235LInstruction* LChunkBuilder::DoShl(HShl* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001236 return DoShift(Token::SHL, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001237}
1238
1239
1240LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001241 return DoBit(Token::BIT_AND, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001242}
1243
1244
1245LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001246 ASSERT(instr->value()->representation().IsInteger32());
1247 ASSERT(instr->representation().IsInteger32());
1248 LOperand* input = UseRegisterAtStart(instr->value());
1249 LBitNotI* result = new LBitNotI(input);
1250 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001251}
1252
1253
1254LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001255 return DoBit(Token::BIT_OR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001256}
1257
1258
1259LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001260 return DoBit(Token::BIT_XOR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001261}
1262
1263
1264LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1265 Abort("Unimplemented: %s", "DoDiv");
1266 return NULL;
1267}
1268
1269
1270LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1271 Abort("Unimplemented: %s", "DoMod");
1272 return NULL;
1273}
1274
1275
1276LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1277 Abort("Unimplemented: %s", "DoMul");
1278 return NULL;
1279}
1280
1281
1282LInstruction* LChunkBuilder::DoSub(HSub* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001283 if (instr->representation().IsInteger32()) {
1284 ASSERT(instr->left()->representation().IsInteger32());
1285 ASSERT(instr->right()->representation().IsInteger32());
1286 LOperand* left = UseRegisterAtStart(instr->left());
1287 LOperand* right = UseOrConstantAtStart(instr->right());
1288 LSubI* sub = new LSubI(left, right);
1289 LInstruction* result = DefineSameAsFirst(sub);
1290 if (instr->CheckFlag(HValue::kCanOverflow)) {
1291 result = AssignEnvironment(result);
1292 }
1293 return result;
1294 } else if (instr->representation().IsDouble()) {
1295 return DoArithmeticD(Token::SUB, instr);
1296 } else {
1297 ASSERT(instr->representation().IsTagged());
1298 return DoArithmeticT(Token::SUB, instr);
1299 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001300}
1301
1302
1303LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001304 if (instr->representation().IsInteger32()) {
1305 ASSERT(instr->left()->representation().IsInteger32());
1306 ASSERT(instr->right()->representation().IsInteger32());
1307 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1308 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1309 LAddI* add = new LAddI(left, right);
1310 LInstruction* result = DefineSameAsFirst(add);
1311 if (instr->CheckFlag(HValue::kCanOverflow)) {
1312 result = AssignEnvironment(result);
1313 }
1314 return result;
1315 } else if (instr->representation().IsDouble()) {
1316 Abort("Unimplemented: %s", "DoAdd on Doubles");
1317 } else {
1318 ASSERT(instr->representation().IsTagged());
1319 return DoArithmeticT(Token::ADD, instr);
1320 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001321 return NULL;
1322}
1323
1324
1325LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1326 Abort("Unimplemented: %s", "DoPower");
1327 return NULL;
1328}
1329
1330
1331LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001332 Token::Value op = instr->token();
1333 Representation r = instr->GetInputRepresentation();
1334 if (r.IsInteger32()) {
1335 ASSERT(instr->left()->representation().IsInteger32());
1336 ASSERT(instr->right()->representation().IsInteger32());
1337 LOperand* left = UseRegisterAtStart(instr->left());
1338 LOperand* right = UseOrConstantAtStart(instr->right());
1339 return DefineAsRegister(new LCmpID(left, right));
1340 } else if (r.IsDouble()) {
1341 ASSERT(instr->left()->representation().IsDouble());
1342 ASSERT(instr->right()->representation().IsDouble());
1343 LOperand* left = UseRegisterAtStart(instr->left());
1344 LOperand* right = UseRegisterAtStart(instr->right());
1345 return DefineAsRegister(new LCmpID(left, right));
1346 } else {
1347 ASSERT(instr->left()->representation().IsTagged());
1348 ASSERT(instr->right()->representation().IsTagged());
1349 bool reversed = (op == Token::GT || op == Token::LTE);
1350 LOperand* left = UseFixed(instr->left(), reversed ? rax : rdx);
1351 LOperand* right = UseFixed(instr->right(), reversed ? rdx : rax);
1352 LCmpT* result = new LCmpT(left, right);
1353 return MarkAsCall(DefineFixed(result, rax), instr);
1354 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001355}
1356
1357
1358LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1359 HCompareJSObjectEq* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001360 LOperand* left = UseRegisterAtStart(instr->left());
1361 LOperand* right = UseRegisterAtStart(instr->right());
1362 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
1363 return DefineAsRegister(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001364}
1365
1366
1367LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001368 ASSERT(instr->value()->representation().IsTagged());
1369 LOperand* value = UseRegisterAtStart(instr->value());
1370
1371 return DefineAsRegister(new LIsNull(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001372}
1373
1374
1375LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001376 ASSERT(instr->value()->representation().IsTagged());
1377 LOperand* value = UseRegister(instr->value());
1378
1379 return DefineAsRegister(new LIsObject(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001380}
1381
1382
1383LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001384 ASSERT(instr->value()->representation().IsTagged());
1385 LOperand* value = UseAtStart(instr->value());
1386
1387 return DefineAsRegister(new LIsSmi(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001388}
1389
1390
1391LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1392 Abort("Unimplemented: %s", "DoHasInstanceType");
1393 return NULL;
1394}
1395
1396
1397LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1398 HHasCachedArrayIndex* instr) {
1399 Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
1400 return NULL;
1401}
1402
1403
1404LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1405 Abort("Unimplemented: %s", "DoClassOfTest");
1406 return NULL;
1407}
1408
1409
1410LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001411 LOperand* array = UseRegisterAtStart(instr->value());
1412 return DefineAsRegister(new LJSArrayLength(array));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001413}
1414
1415
1416LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001417 LOperand* array = UseRegisterAtStart(instr->value());
1418 return DefineAsRegister(new LFixedArrayLength(array));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001419}
1420
1421
1422LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1423 Abort("Unimplemented: %s", "DoValueOf");
1424 return NULL;
1425}
1426
1427
1428LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001429 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
1430 Use(instr->length())));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001431}
1432
1433
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001434LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1435 // The control instruction marking the end of a block that completed
1436 // abruptly (e.g., threw an exception). There is nothing specific to do.
1437 return NULL;
1438}
1439
1440
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001441LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1442 Abort("Unimplemented: %s", "DoThrow");
1443 return NULL;
1444}
1445
1446
1447LInstruction* LChunkBuilder::DoChange(HChange* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001448 Representation from = instr->from();
1449 Representation to = instr->to();
1450 if (from.IsTagged()) {
1451 if (to.IsDouble()) {
1452 LOperand* value = UseRegister(instr->value());
1453 LNumberUntagD* res = new LNumberUntagD(value);
1454 return AssignEnvironment(DefineAsRegister(res));
1455 } else {
1456 ASSERT(to.IsInteger32());
1457 LOperand* value = UseRegister(instr->value());
1458 bool needs_check = !instr->value()->type().IsSmi();
1459 if (needs_check) {
1460 LOperand* xmm_temp =
1461 (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3))
1462 ? NULL
1463 : FixedTemp(xmm1);
1464 LTaggedToI* res = new LTaggedToI(value, xmm_temp);
1465 return AssignEnvironment(DefineSameAsFirst(res));
1466 } else {
1467 return DefineSameAsFirst(new LSmiUntag(value, needs_check));
1468 }
1469 }
1470 } else if (from.IsDouble()) {
1471 if (to.IsTagged()) {
1472 LOperand* value = UseRegister(instr->value());
1473 LOperand* temp = TempRegister();
1474
1475 // Make sure that temp and result_temp are different registers.
1476 LUnallocated* result_temp = TempRegister();
1477 LNumberTagD* result = new LNumberTagD(value, temp);
1478 return AssignPointerMap(Define(result, result_temp));
1479 } else {
1480 ASSERT(to.IsInteger32());
1481 bool needs_temp = instr->CanTruncateToInt32() &&
1482 !CpuFeatures::IsSupported(SSE3);
1483 LOperand* value = needs_temp ?
1484 UseTempRegister(instr->value()) : UseRegister(instr->value());
1485 LOperand* temp = needs_temp ? TempRegister() : NULL;
1486 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp)));
1487 }
1488 } else if (from.IsInteger32()) {
1489 if (to.IsTagged()) {
1490 HValue* val = instr->value();
1491 LOperand* value = UseRegister(val);
1492 if (val->HasRange() && val->range()->IsInSmiRange()) {
1493 return DefineSameAsFirst(new LSmiTag(value));
1494 } else {
1495 LNumberTagI* result = new LNumberTagI(value);
1496 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1497 }
1498 } else {
1499 ASSERT(to.IsDouble());
1500 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value())));
1501 }
1502 }
1503 UNREACHABLE();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001504 return NULL;
1505}
1506
1507
1508LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001509 LOperand* value = UseRegisterAtStart(instr->value());
1510 return AssignEnvironment(new LCheckSmi(value, zero));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001511}
1512
1513
1514LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001515 LOperand* value = UseRegisterAtStart(instr->value());
1516 LCheckInstanceType* result = new LCheckInstanceType(value);
1517 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001518}
1519
1520
1521LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001522 LOperand* temp = TempRegister();
1523 LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp);
1524 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001525}
1526
1527
1528LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001529 LOperand* value = UseRegisterAtStart(instr->value());
1530 return AssignEnvironment(new LCheckSmi(value, not_zero));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001531}
1532
1533
1534LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001535 LOperand* value = UseRegisterAtStart(instr->value());
1536 return AssignEnvironment(new LCheckFunction(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001537}
1538
1539
1540LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001541 LOperand* value = UseRegisterAtStart(instr->value());
1542 LCheckMap* result = new LCheckMap(value);
1543 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001544}
1545
1546
1547LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1548 return new LReturn(UseFixed(instr->value(), rax));
1549}
1550
1551
1552LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1553 Representation r = instr->representation();
1554 if (r.IsInteger32()) {
1555 int32_t value = instr->Integer32Value();
1556 return DefineAsRegister(new LConstantI(value));
1557 } else if (r.IsDouble()) {
1558 double value = instr->DoubleValue();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001559 LOperand* temp = TempRegister();
1560 return DefineAsRegister(new LConstantD(value, temp));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001561 } else if (r.IsTagged()) {
1562 return DefineAsRegister(new LConstantT(instr->handle()));
1563 } else {
1564 UNREACHABLE();
1565 return NULL;
1566 }
1567}
1568
1569
1570LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001571 LLoadGlobal* result = new LLoadGlobal;
1572 return instr->check_hole_value()
1573 ? AssignEnvironment(DefineAsRegister(result))
1574 : DefineAsRegister(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001575}
1576
1577
1578LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001579 LStoreGlobal* result = new LStoreGlobal(UseRegister(instr->value()),
1580 TempRegister());
1581 return instr->check_hole_value() ? AssignEnvironment(result) : result;
1582}
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001583
1584
1585LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1586 Abort("Unimplemented: %s", "DoLoadContextSlot");
1587 return NULL;
1588}
1589
1590
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001591LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1592 Abort("Unimplemented: DoStoreContextSlot");
1593 return NULL;
1594}
1595
1596
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001597LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001598 ASSERT(instr->representation().IsTagged());
1599 LOperand* obj = UseRegisterAtStart(instr->object());
1600 return DefineAsRegister(new LLoadNamedField(obj));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001601}
1602
1603
1604LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1605 Abort("Unimplemented: %s", "DoLoadNamedGeneric");
1606 return NULL;
1607}
1608
1609
1610LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1611 HLoadFunctionPrototype* instr) {
1612 Abort("Unimplemented: %s", "DoLoadFunctionPrototype");
1613 return NULL;
1614}
1615
1616
1617LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001618 LOperand* input = UseRegisterAtStart(instr->value());
1619 return DefineSameAsFirst(new LLoadElements(input));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001620}
1621
1622
1623LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1624 HLoadKeyedFastElement* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001625 ASSERT(instr->representation().IsTagged());
1626 ASSERT(instr->key()->representation().IsInteger32());
1627 LOperand* obj = UseRegisterAtStart(instr->object());
1628 LOperand* key = UseRegisterAtStart(instr->key());
1629 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
1630 return AssignEnvironment(DefineSameAsFirst(result));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001631}
1632
1633
1634LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1635 Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
1636 return NULL;
1637}
1638
1639
1640LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1641 HStoreKeyedFastElement* instr) {
1642 Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
1643 return NULL;
1644}
1645
1646
1647LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1648 Abort("Unimplemented: %s", "DoStoreKeyedGeneric");
1649 return NULL;
1650}
1651
1652
1653LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001654 bool needs_write_barrier = instr->NeedsWriteBarrier();
1655
1656 LOperand* obj = needs_write_barrier
1657 ? UseTempRegister(instr->object())
1658 : UseRegisterAtStart(instr->object());
1659
1660 LOperand* val = needs_write_barrier
1661 ? UseTempRegister(instr->value())
1662 : UseRegister(instr->value());
1663
1664 // We only need a scratch register if we have a write barrier or we
1665 // have a store into the properties array (not in-object-property).
1666 LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
1667 ? TempRegister() : NULL;
1668
1669 return new LStoreNamedField(obj, val, temp);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001670}
1671
1672
1673LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1674 Abort("Unimplemented: %s", "DoStoreNamedGeneric");
1675 return NULL;
1676}
1677
1678
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001679LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1680 Abort("Unimplemented: %s", "DoStringCharCodeAt");
1681 return NULL;
1682}
1683
1684
1685LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1686 Abort("Unimplemented: %s", "DoStringLength");
1687 return NULL;
1688}
1689
1690
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001691LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001692 return MarkAsCall(DefineFixed(new LArrayLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001693}
1694
1695
1696LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001697 return MarkAsCall(DefineFixed(new LObjectLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001698}
1699
1700
1701LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1702 Abort("Unimplemented: %s", "DoRegExpLiteral");
1703 return NULL;
1704}
1705
1706
1707LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001708 return MarkAsCall(DefineFixed(new LFunctionLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001709}
1710
1711
1712LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
1713 Abort("Unimplemented: %s", "DoDeleteProperty");
1714 return NULL;
1715}
1716
1717
1718LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1719 Abort("Unimplemented: %s", "DoOsrEntry");
1720 return NULL;
1721}
1722
1723
1724LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1725 int spill_index = chunk()->GetParameterStackSlot(instr->index());
1726 return DefineAsSpilled(new LParameter, spill_index);
1727}
1728
1729
1730LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
1731 Abort("Unimplemented: %s", "DoUnknownOSRValue");
1732 return NULL;
1733}
1734
1735
1736LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1737 Abort("Unimplemented: %s", "DoCallStub");
1738 return NULL;
1739}
1740
1741
1742LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
1743 Abort("Unimplemented: %s", "DoArgumentsObject");
1744 return NULL;
1745}
1746
1747
1748LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
1749 Abort("Unimplemented: %s", "DoAccessArgumentsAt");
1750 return NULL;
1751}
1752
1753
1754LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
1755 Abort("Unimplemented: %s", "DoTypeof");
1756 return NULL;
1757}
1758
1759
1760LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
1761 Abort("Unimplemented: %s", "DoTypeofIs");
1762 return NULL;
1763}
1764
1765LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1766 HEnvironment* env = current_block_->last_environment();
1767 ASSERT(env != NULL);
1768
1769 env->set_ast_id(instr->ast_id());
1770
1771 env->Drop(instr->pop_count());
1772 for (int i = 0; i < instr->values()->length(); ++i) {
1773 HValue* value = instr->values()->at(i);
1774 if (instr->HasAssignedIndexAt(i)) {
1775 env->Bind(instr->GetAssignedIndexAt(i), value);
1776 } else {
1777 env->Push(value);
1778 }
1779 }
1780 ASSERT(env->length() == instr->environment_length());
1781
1782 // If there is an instruction pending deoptimization environment create a
1783 // lazy bailout instruction to capture the environment.
fschneider@chromium.org1df6b472011-01-26 08:23:03 +00001784 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001785 LLazyBailout* lazy_bailout = new LLazyBailout;
1786 LInstruction* result = AssignEnvironment(lazy_bailout);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001787 instruction_pending_deoptimization_environment_->
fschneider@chromium.org1df6b472011-01-26 08:23:03 +00001788 set_deoptimization_environment(result->environment());
1789 ClearInstructionPendingDeoptimizationEnvironment();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001790 return result;
1791 }
1792
1793 return NULL;
1794}
1795
1796
1797LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
1798 return MarkAsCall(new LStackCheck, instr);
1799}
1800
1801
1802LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001803 HEnvironment* outer = current_block_->last_environment();
1804 HConstant* undefined = graph()->GetConstantUndefined();
1805 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
1806 instr->function(),
1807 false,
1808 undefined);
1809 current_block_->UpdateEnvironment(inner);
1810 chunk_->AddInlinedClosure(instr->closure());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001811 return NULL;
1812}
1813
1814
1815LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001816 HEnvironment* outer = current_block_->last_environment()->outer();
1817 current_block_->UpdateEnvironment(outer);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001818 return NULL;
1819}
1820
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001821} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001822
1823#endif // V8_TARGET_ARCH_X64