blob: eff6d51e83c390beef351a1ecbe9772f6a170127 [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
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000032#include "x64/lithium-x64.h"
33#include "x64/lithium-codegen-x64.h"
34
35namespace v8 {
36namespace internal {
37
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000038#define DEFINE_COMPILE(type) \
39 void L##type::CompileToNative(LCodeGen* generator) { \
40 generator->Do##type(this); \
41 }
42LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
43#undef DEFINE_COMPILE
44
45LOsrEntry::LOsrEntry() {
46 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
47 register_spills_[i] = NULL;
48 }
49 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
50 double_register_spills_[i] = NULL;
51 }
52}
53
54
55void LOsrEntry::MarkSpilledRegister(int allocation_index,
56 LOperand* spill_operand) {
57 ASSERT(spill_operand->IsStackSlot());
58 ASSERT(register_spills_[allocation_index] == NULL);
59 register_spills_[allocation_index] = spill_operand;
60}
61
62
63void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
64 LOperand* spill_operand) {
65 ASSERT(spill_operand->IsDoubleStackSlot());
66 ASSERT(double_register_spills_[allocation_index] == NULL);
67 double_register_spills_[allocation_index] = spill_operand;
68}
69
70
71void LInstruction::PrintTo(StringStream* stream) {
72 stream->Add("%s ", this->Mnemonic());
73 if (HasResult()) {
74 PrintOutputOperandTo(stream);
75 }
76
77 PrintDataTo(stream);
78
79 if (HasEnvironment()) {
80 stream->Add(" ");
81 environment()->PrintTo(stream);
82 }
83
84 if (HasPointerMap()) {
85 stream->Add(" ");
86 pointer_map()->PrintTo(stream);
87 }
88}
89
90
91template<int R, int I, int T>
92void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000093 stream->Add("= ");
94 inputs_.PrintOperandsTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000095}
96
97
98template<int R, int I, int T>
99void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000100 results_.PrintOperandsTo(stream);
101}
102
103
104template<typename T, int N>
105void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
106 for (int i = 0; i < N; i++) {
107 if (i > 0) stream->Add(" ");
108 elems_[i]->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000109 }
110}
111
112
113void LLabel::PrintDataTo(StringStream* stream) {
114 LGap::PrintDataTo(stream);
115 LLabel* rep = replacement();
116 if (rep != NULL) {
117 stream->Add(" Dead block replaced with B%d", rep->block_id());
118 }
119}
120
121
122bool LGap::IsRedundant() const {
123 for (int i = 0; i < 4; i++) {
124 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
125 return false;
126 }
127 }
128
129 return true;
130}
131
132
133void LGap::PrintDataTo(StringStream* stream) {
134 for (int i = 0; i < 4; i++) {
135 stream->Add("(");
136 if (parallel_moves_[i] != NULL) {
137 parallel_moves_[i]->PrintDataTo(stream);
138 }
139 stream->Add(") ");
140 }
141}
142
143
144const char* LArithmeticD::Mnemonic() const {
145 switch (op()) {
146 case Token::ADD: return "add-d";
147 case Token::SUB: return "sub-d";
148 case Token::MUL: return "mul-d";
149 case Token::DIV: return "div-d";
150 case Token::MOD: return "mod-d";
151 default:
152 UNREACHABLE();
153 return NULL;
154 }
155}
156
157
158const char* LArithmeticT::Mnemonic() const {
159 switch (op()) {
160 case Token::ADD: return "add-t";
161 case Token::SUB: return "sub-t";
162 case Token::MUL: return "mul-t";
163 case Token::MOD: return "mod-t";
164 case Token::DIV: return "div-t";
165 default:
166 UNREACHABLE();
167 return NULL;
168 }
169}
170
171
172void LGoto::PrintDataTo(StringStream* stream) {
173 stream->Add("B%d", block_id());
174}
175
176
177void LBranch::PrintDataTo(StringStream* stream) {
178 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000179 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000180}
181
182
183void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
184 stream->Add("if ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000185 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000186 stream->Add(" %s ", Token::String(op()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000187 InputAt(1)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000188 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
189}
190
191
192void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
193 stream->Add("if ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000194 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000195 stream->Add(is_strict() ? " === null" : " == null");
196 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
197}
198
199
200void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
201 stream->Add("if is_object(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000202 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000203 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
204}
205
206
207void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
208 stream->Add("if is_smi(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000209 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000210 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
211}
212
213
214void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
215 stream->Add("if has_instance_type(");
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(") then B%d else B%d", true_block_id(), false_block_id());
218}
219
220
221void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
222 stream->Add("if has_cached_array_index(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000223 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000224 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
225}
226
227
228void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
229 stream->Add("if class_of_test(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000230 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000231 stream->Add(", \"%o\") then B%d else B%d",
232 *hydrogen()->class_name(),
233 true_block_id(),
234 false_block_id());
235}
236
237
238void LTypeofIs::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000239 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000240 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
241}
242
243
244void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
245 stream->Add("if typeof ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000246 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000247 stream->Add(" == \"%s\" then B%d else B%d",
248 *hydrogen()->type_literal()->ToCString(),
249 true_block_id(), false_block_id());
250}
251
252
253void LCallConstantFunction::PrintDataTo(StringStream* stream) {
254 stream->Add("#%d / ", arity());
255}
256
257
258void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
259 stream->Add("/%s ", hydrogen()->OpName());
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000260 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000261}
262
263
264void LLoadContextSlot::PrintDataTo(StringStream* stream) {
265 stream->Add("(%d, %d)", context_chain_length(), slot_index());
266}
267
268
269void LCallKeyed::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000270 stream->Add("[ecx] #%d / ", arity());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000271}
272
273
274void LCallNamed::PrintDataTo(StringStream* stream) {
275 SmartPointer<char> name_string = name()->ToCString();
276 stream->Add("%s #%d / ", *name_string, arity());
277}
278
279
280void LCallGlobal::PrintDataTo(StringStream* stream) {
281 SmartPointer<char> name_string = name()->ToCString();
282 stream->Add("%s #%d / ", *name_string, arity());
283}
284
285
286void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
287 stream->Add("#%d / ", arity());
288}
289
290
291void LCallNew::PrintDataTo(StringStream* stream) {
292 stream->Add("= ");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000293 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000294 stream->Add(" #%d / ", arity());
295}
296
297
298void LClassOfTest::PrintDataTo(StringStream* stream) {
299 stream->Add("= class_of_test(");
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000300 InputAt(0)->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000301 stream->Add(", \"%o\")", *hydrogen()->class_name());
302}
303
304
305void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
306 arguments()->PrintTo(stream);
307
308 stream->Add(" length ");
309 length()->PrintTo(stream);
310
311 stream->Add(" index ");
312 index()->PrintTo(stream);
313}
314
315
316int LChunk::GetNextSpillIndex(bool is_double) {
317 return spill_slot_count_++;
318}
319
320
321LOperand* LChunk::GetNextSpillSlot(bool is_double) {
322 // All stack slots are Double stack slots on x64.
323 // Alternatively, at some point, start using half-size
324 // stack slots for int32 values.
325 int index = GetNextSpillIndex(is_double);
326 if (is_double) {
327 return LDoubleStackSlot::Create(index);
328 } else {
329 return LStackSlot::Create(index);
330 }
331}
332
333
334void LChunk::MarkEmptyBlocks() {
335 HPhase phase("Mark empty blocks", this);
336 for (int i = 0; i < graph()->blocks()->length(); ++i) {
337 HBasicBlock* block = graph()->blocks()->at(i);
338 int first = block->first_instruction_index();
339 int last = block->last_instruction_index();
340 LInstruction* first_instr = instructions()->at(first);
341 LInstruction* last_instr = instructions()->at(last);
342
343 LLabel* label = LLabel::cast(first_instr);
344 if (last_instr->IsGoto()) {
345 LGoto* goto_instr = LGoto::cast(last_instr);
346 if (!goto_instr->include_stack_check() &&
347 label->IsRedundant() &&
348 !label->is_loop_header()) {
349 bool can_eliminate = true;
350 for (int i = first + 1; i < last && can_eliminate; ++i) {
351 LInstruction* cur = instructions()->at(i);
352 if (cur->IsGap()) {
353 LGap* gap = LGap::cast(cur);
354 if (!gap->IsRedundant()) {
355 can_eliminate = false;
356 }
357 } else {
358 can_eliminate = false;
359 }
360 }
361
362 if (can_eliminate) {
363 label->set_replacement(GetLabel(goto_instr->block_id()));
364 }
365 }
366 }
367 }
368}
369
370
371void LStoreNamed::PrintDataTo(StringStream* stream) {
372 object()->PrintTo(stream);
373 stream->Add(".");
374 stream->Add(*String::cast(*name())->ToCString());
375 stream->Add(" <- ");
376 value()->PrintTo(stream);
377}
378
379
380void LStoreKeyed::PrintDataTo(StringStream* stream) {
381 object()->PrintTo(stream);
382 stream->Add("[");
383 key()->PrintTo(stream);
384 stream->Add("] <- ");
385 value()->PrintTo(stream);
386}
387
388
389int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
390 LGap* gap = new LGap(block);
391 int index = -1;
392 if (instr->IsControl()) {
393 instructions_.Add(gap);
394 index = instructions_.length();
395 instructions_.Add(instr);
396 } else {
397 index = instructions_.length();
398 instructions_.Add(instr);
399 instructions_.Add(gap);
400 }
401 if (instr->HasPointerMap()) {
402 pointer_maps_.Add(instr->pointer_map());
403 instr->pointer_map()->set_lithium_position(index);
404 }
405 return index;
406}
407
408
409LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
410 return LConstantOperand::Create(constant->id());
411}
412
413
414int LChunk::GetParameterStackSlot(int index) const {
415 // The receiver is at index 0, the first parameter at index 1, so we
416 // shift all parameter indexes down by the number of parameters, and
417 // make sure they end up negative so they are distinguishable from
418 // spill slots.
419 int result = index - graph()->info()->scope()->num_parameters() - 1;
420 ASSERT(result < 0);
421 return result;
422}
423
424// A parameter relative to ebp in the arguments stub.
425int LChunk::ParameterAt(int index) {
426 ASSERT(-1 <= index); // -1 is the receiver.
427 return (1 + graph()->info()->scope()->num_parameters() - index) *
428 kPointerSize;
429}
430
431
432LGap* LChunk::GetGapAt(int index) const {
433 return LGap::cast(instructions_[index]);
434}
435
436
437bool LChunk::IsGapAt(int index) const {
438 return instructions_[index]->IsGap();
439}
440
441
442int LChunk::NearestGapPos(int index) const {
443 while (!IsGapAt(index)) index--;
444 return index;
445}
446
447
448void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
449 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
450}
451
452
453Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
454 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
455}
456
457
458Representation LChunk::LookupLiteralRepresentation(
459 LConstantOperand* operand) const {
460 return graph_->LookupValue(operand->index())->representation();
461}
462
463
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000464LChunk* LChunkBuilder::Build() {
465 ASSERT(is_unused());
466 chunk_ = new LChunk(graph());
467 HPhase phase("Building chunk", chunk_);
468 status_ = BUILDING;
469 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
470 for (int i = 0; i < blocks->length(); i++) {
471 HBasicBlock* next = NULL;
472 if (i < blocks->length() - 1) next = blocks->at(i + 1);
473 DoBasicBlock(blocks->at(i), next);
474 if (is_aborted()) return NULL;
475 }
476 status_ = DONE;
477 return chunk_;
478}
479
480
481void LChunkBuilder::Abort(const char* format, ...) {
482 if (FLAG_trace_bailout) {
483 SmartPointer<char> debug_name = graph()->debug_name()->ToCString();
484 PrintF("Aborting LChunk building in @\"%s\": ", *debug_name);
485 va_list arguments;
486 va_start(arguments, format);
487 OS::VPrint(format, arguments);
488 va_end(arguments);
489 PrintF("\n");
490 }
491 status_ = ABORTED;
492}
493
494
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000495LRegister* LChunkBuilder::ToOperand(Register reg) {
496 return LRegister::Create(Register::ToAllocationIndex(reg));
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000497}
498
499
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000500LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
501 return new LUnallocated(LUnallocated::FIXED_REGISTER,
502 Register::ToAllocationIndex(reg));
503}
504
505
506LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
507 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
508 XMMRegister::ToAllocationIndex(reg));
509}
510
511
512LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
513 return Use(value, ToUnallocated(fixed_register));
514}
515
516
517LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
518 return Use(value, ToUnallocated(reg));
519}
520
521
522LOperand* LChunkBuilder::UseRegister(HValue* value) {
523 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
524}
525
526
527LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
528 return Use(value,
529 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
530 LUnallocated::USED_AT_START));
531}
532
533
534LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
535 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
536}
537
538
539LOperand* LChunkBuilder::Use(HValue* value) {
540 return Use(value, new LUnallocated(LUnallocated::NONE));
541}
542
543
544LOperand* LChunkBuilder::UseAtStart(HValue* value) {
545 return Use(value, new LUnallocated(LUnallocated::NONE,
546 LUnallocated::USED_AT_START));
547}
548
549
550LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
551 return value->IsConstant()
552 ? chunk_->DefineConstantOperand(HConstant::cast(value))
553 : Use(value);
554}
555
556
557LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
558 return value->IsConstant()
559 ? chunk_->DefineConstantOperand(HConstant::cast(value))
560 : UseAtStart(value);
561}
562
563
564LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
565 return value->IsConstant()
566 ? chunk_->DefineConstantOperand(HConstant::cast(value))
567 : UseRegister(value);
568}
569
570
571LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
572 return value->IsConstant()
573 ? chunk_->DefineConstantOperand(HConstant::cast(value))
574 : UseRegisterAtStart(value);
575}
576
577
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000578LOperand* LChunkBuilder::UseAny(HValue* value) {
579 return value->IsConstant()
580 ? chunk_->DefineConstantOperand(HConstant::cast(value))
581 : Use(value, new LUnallocated(LUnallocated::ANY));
582}
583
584
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000585LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
586 if (value->EmitAtUses()) {
587 HInstruction* instr = HInstruction::cast(value);
588 VisitInstruction(instr);
589 }
590 allocator_->RecordUse(value, operand);
591 return operand;
592}
593
594
595template<int I, int T>
596LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
597 LUnallocated* result) {
598 allocator_->RecordDefinition(current_instruction_, result);
599 instr->set_result(result);
600 return instr;
601}
602
603
604template<int I, int T>
605LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
606 return Define(instr, new LUnallocated(LUnallocated::NONE));
607}
608
609
610template<int I, int T>
611LInstruction* LChunkBuilder::DefineAsRegister(
612 LTemplateInstruction<1, I, T>* instr) {
613 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
614}
615
616
617template<int I, int T>
618LInstruction* LChunkBuilder::DefineAsSpilled(
619 LTemplateInstruction<1, I, T>* instr,
620 int index) {
621 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
622}
623
624
625template<int I, int T>
626LInstruction* LChunkBuilder::DefineSameAsFirst(
627 LTemplateInstruction<1, I, T>* instr) {
628 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
629}
630
631
632template<int I, int T>
633LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
634 Register reg) {
635 return Define(instr, ToUnallocated(reg));
636}
637
638
639template<int I, int T>
640LInstruction* LChunkBuilder::DefineFixedDouble(
641 LTemplateInstruction<1, I, T>* instr,
642 XMMRegister reg) {
643 return Define(instr, ToUnallocated(reg));
644}
645
646
647LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
648 HEnvironment* hydrogen_env = current_block_->last_environment();
649 instr->set_environment(CreateEnvironment(hydrogen_env));
650 return instr;
651}
652
653
654LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
655 LInstruction* instr, int ast_id) {
656 ASSERT(instructions_pending_deoptimization_environment_ == NULL);
657 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
658 instructions_pending_deoptimization_environment_ = instr;
659 pending_deoptimization_ast_id_ = ast_id;
660 return instr;
661}
662
663
664void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
665 instructions_pending_deoptimization_environment_ = NULL;
666 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
667}
668
669
670LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
671 HInstruction* hinstr,
672 CanDeoptimize can_deoptimize) {
673 allocator_->MarkAsCall();
674 instr = AssignPointerMap(instr);
675
676 if (hinstr->HasSideEffects()) {
677 ASSERT(hinstr->next()->IsSimulate());
678 HSimulate* sim = HSimulate::cast(hinstr->next());
679 instr = SetInstructionPendingDeoptimizationEnvironment(
680 instr, sim->ast_id());
681 }
682
683 // If instruction does not have side-effects lazy deoptimization
684 // after the call will try to deoptimize to the point before the call.
685 // Thus we still need to attach environment to this call even if
686 // call sequence can not deoptimize eagerly.
687 bool needs_environment =
688 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
689 if (needs_environment && !instr->HasEnvironment()) {
690 instr = AssignEnvironment(instr);
691 }
692
693 return instr;
694}
695
696
697LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
698 allocator_->MarkAsSaveDoubles();
699 return instr;
700}
701
702
703LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
704 ASSERT(!instr->HasPointerMap());
705 instr->set_pointer_map(new LPointerMap(position_));
706 return instr;
707}
708
709
710LUnallocated* LChunkBuilder::TempRegister() {
711 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
712 allocator_->RecordTemporary(operand);
713 return operand;
714}
715
716
717LOperand* LChunkBuilder::FixedTemp(Register reg) {
718 LUnallocated* operand = ToUnallocated(reg);
719 allocator_->RecordTemporary(operand);
720 return operand;
721}
722
723
724LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
725 LUnallocated* operand = ToUnallocated(reg);
726 allocator_->RecordTemporary(operand);
727 return operand;
728}
729
730
731LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
732 return new LLabel(instr->block());
733}
734
735
736LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
737 return AssignEnvironment(new LDeoptimize);
738}
739
740
741LInstruction* LChunkBuilder::DoBit(Token::Value op,
742 HBitwiseBinaryOperation* instr) {
743 Abort("Unimplemented: %s", "DoBit");
744 return NULL;
745}
746
747
748LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
749 HArithmeticBinaryOperation* instr) {
750 Abort("Unimplemented: %s", "DoArithmeticD");
751 return NULL;
752}
753
754
755LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
756 HArithmeticBinaryOperation* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000757 ASSERT(op == Token::ADD ||
758 op == Token::DIV ||
759 op == Token::MOD ||
760 op == Token::MUL ||
761 op == Token::SUB);
762 HValue* left = instr->left();
763 HValue* right = instr->right();
764 ASSERT(left->representation().IsTagged());
765 ASSERT(right->representation().IsTagged());
766 LOperand* left_operand = UseFixed(left, rdx);
767 LOperand* right_operand = UseFixed(right, rax);
768 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
769 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000770}
771
772
773void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
774 ASSERT(is_building());
775 current_block_ = block;
776 next_block_ = next_block;
777 if (block->IsStartBlock()) {
778 block->UpdateEnvironment(graph_->start_environment());
779 argument_count_ = 0;
780 } else if (block->predecessors()->length() == 1) {
781 // We have a single predecessor => copy environment and outgoing
782 // argument count from the predecessor.
783 ASSERT(block->phis()->length() == 0);
784 HBasicBlock* pred = block->predecessors()->at(0);
785 HEnvironment* last_environment = pred->last_environment();
786 ASSERT(last_environment != NULL);
787 // Only copy the environment, if it is later used again.
788 if (pred->end()->SecondSuccessor() == NULL) {
789 ASSERT(pred->end()->FirstSuccessor() == block);
790 } else {
791 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
792 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
793 last_environment = last_environment->Copy();
794 }
795 }
796 block->UpdateEnvironment(last_environment);
797 ASSERT(pred->argument_count() >= 0);
798 argument_count_ = pred->argument_count();
799 } else {
800 // We are at a state join => process phis.
801 HBasicBlock* pred = block->predecessors()->at(0);
802 // No need to copy the environment, it cannot be used later.
803 HEnvironment* last_environment = pred->last_environment();
804 for (int i = 0; i < block->phis()->length(); ++i) {
805 HPhi* phi = block->phis()->at(i);
806 last_environment->SetValueAt(phi->merged_index(), phi);
807 }
808 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
809 last_environment->SetValueAt(block->deleted_phis()->at(i),
810 graph_->GetConstantUndefined());
811 }
812 block->UpdateEnvironment(last_environment);
813 // Pick up the outgoing argument count of one of the predecessors.
814 argument_count_ = pred->argument_count();
815 }
816 HInstruction* current = block->first();
817 int start = chunk_->instructions()->length();
818 while (current != NULL && !is_aborted()) {
819 // Code for constants in registers is generated lazily.
820 if (!current->EmitAtUses()) {
821 VisitInstruction(current);
822 }
823 current = current->next();
824 }
825 int end = chunk_->instructions()->length() - 1;
826 if (end >= start) {
827 block->set_first_instruction_index(start);
828 block->set_last_instruction_index(end);
829 }
830 block->set_argument_count(argument_count_);
831 next_block_ = NULL;
832 current_block_ = NULL;
833}
834
835
836void LChunkBuilder::VisitInstruction(HInstruction* current) {
837 HInstruction* old_current = current_instruction_;
838 current_instruction_ = current;
839 allocator_->BeginInstruction();
840 if (current->has_position()) position_ = current->position();
841 LInstruction* instr = current->CompileToLithium(this);
842
843 if (instr != NULL) {
844 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
845 instr = AssignPointerMap(instr);
846 }
847 if (FLAG_stress_environments && !instr->HasEnvironment()) {
848 instr = AssignEnvironment(instr);
849 }
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000850 if (current->IsTest() && !instr->IsGoto()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000851 ASSERT(instr->IsControl());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000852 HTest* test = HTest::cast(current);
853 instr->set_hydrogen_value(test->value());
854 HBasicBlock* first = test->FirstSuccessor();
855 HBasicBlock* second = test->SecondSuccessor();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000856 ASSERT(first != NULL && second != NULL);
857 instr->SetBranchTargets(first->block_id(), second->block_id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000858 } else {
859 instr->set_hydrogen_value(current);
860 }
861
862 int index = chunk_->AddInstruction(instr, current_block_);
863 allocator_->SummarizeInstruction(index);
864 } else {
865 // This instruction should be omitted.
866 allocator_->OmitInstruction();
867 }
868 current_instruction_ = old_current;
869}
870
871
872LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
873 if (hydrogen_env == NULL) return NULL;
874
875 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
876 int ast_id = hydrogen_env->ast_id();
877 ASSERT(ast_id != AstNode::kNoNumber);
878 int value_count = hydrogen_env->length();
879 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
880 ast_id,
881 hydrogen_env->parameter_count(),
882 argument_count_,
883 value_count,
884 outer);
885 int argument_index = 0;
886 for (int i = 0; i < value_count; ++i) {
887 HValue* value = hydrogen_env->values()->at(i);
888 LOperand* op = NULL;
889 if (value->IsArgumentsObject()) {
890 op = NULL;
891 } else if (value->IsPushArgument()) {
892 op = new LArgument(argument_index++);
893 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000894 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000895 }
896 result->AddValue(op, value->representation());
897 }
898
899 return result;
900}
901
902
903LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
904 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(),
905 instr->include_stack_check());
906 return (instr->include_stack_check())
907 ? AssignPointerMap(result)
908 : result;
909}
910
911
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000912LInstruction* LChunkBuilder::DoTest(HTest* instr) {
913 HValue* v = instr->value();
914 if (v->EmitAtUses()) {
915 if (v->IsClassOfTest()) {
916 HClassOfTest* compare = HClassOfTest::cast(v);
917 ASSERT(compare->value()->representation().IsTagged());
918
919 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
920 TempRegister());
921 } else if (v->IsCompare()) {
922 HCompare* compare = HCompare::cast(v);
923 Token::Value op = compare->token();
924 HValue* left = compare->left();
925 HValue* right = compare->right();
926 Representation r = compare->GetInputRepresentation();
927 if (r.IsInteger32()) {
928 ASSERT(left->representation().IsInteger32());
929 ASSERT(right->representation().IsInteger32());
930
931 return new LCmpIDAndBranch(UseRegisterAtStart(left),
932 UseOrConstantAtStart(right));
933 } else if (r.IsDouble()) {
934 ASSERT(left->representation().IsDouble());
935 ASSERT(right->representation().IsDouble());
936
937 return new LCmpIDAndBranch(UseRegisterAtStart(left),
938 UseRegisterAtStart(right));
939 } else {
940 ASSERT(left->representation().IsTagged());
941 ASSERT(right->representation().IsTagged());
942 bool reversed = op == Token::GT || op == Token::LTE;
943 LOperand* left_operand = UseFixed(left, reversed ? rax : rdx);
944 LOperand* right_operand = UseFixed(right, reversed ? rdx : rax);
945 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand,
946 right_operand);
947 return MarkAsCall(result, instr);
948 }
949 } else if (v->IsIsSmi()) {
950 HIsSmi* compare = HIsSmi::cast(v);
951 ASSERT(compare->value()->representation().IsTagged());
952
953 return new LIsSmiAndBranch(Use(compare->value()));
954 } else if (v->IsHasInstanceType()) {
955 HHasInstanceType* compare = HHasInstanceType::cast(v);
956 ASSERT(compare->value()->representation().IsTagged());
957
958 return new LHasInstanceTypeAndBranch(
959 UseRegisterAtStart(compare->value()));
960 } else if (v->IsHasCachedArrayIndex()) {
961 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
962 ASSERT(compare->value()->representation().IsTagged());
963
964 return new LHasCachedArrayIndexAndBranch(
965 UseRegisterAtStart(compare->value()));
966 } else if (v->IsIsNull()) {
967 HIsNull* compare = HIsNull::cast(v);
968 ASSERT(compare->value()->representation().IsTagged());
969
970 // We only need a temp register for non-strict compare.
971 LOperand* temp = compare->is_strict() ? NULL : TempRegister();
972 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
973 temp);
974 } else if (v->IsIsObject()) {
975 HIsObject* compare = HIsObject::cast(v);
976 ASSERT(compare->value()->representation().IsTagged());
977
978 LOperand* temp1 = TempRegister();
979 LOperand* temp2 = TempRegister();
980 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
981 temp1,
982 temp2);
983 } else if (v->IsCompareJSObjectEq()) {
984 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
985 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
986 UseRegisterAtStart(compare->right()));
987 } else if (v->IsInstanceOf()) {
988 HInstanceOf* instance_of = HInstanceOf::cast(v);
989 LInstanceOfAndBranch* result =
990 new LInstanceOfAndBranch(
991 UseFixed(instance_of->left(), InstanceofStub::left()),
992 UseFixed(instance_of->right(), InstanceofStub::right()));
993 return MarkAsCall(result, instr);
994 } else if (v->IsTypeofIs()) {
995 HTypeofIs* typeof_is = HTypeofIs::cast(v);
996 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
997 } else {
998 if (v->IsConstant()) {
999 if (HConstant::cast(v)->handle()->IsTrue()) {
1000 return new LGoto(instr->FirstSuccessor()->block_id());
1001 } else if (HConstant::cast(v)->handle()->IsFalse()) {
1002 return new LGoto(instr->SecondSuccessor()->block_id());
1003 }
1004 }
1005 Abort("Undefined compare before branch");
1006 return NULL;
1007 }
1008 }
1009 return new LBranch(UseRegisterAtStart(v));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001010}
1011
1012
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001013LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1014 Abort("Unimplemented: %s", "DoCompareMap");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001015 return NULL;
1016}
1017
1018
1019LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1020 Abort("Unimplemented: %s", "DoArgumentsLength");
1021 return NULL;
1022}
1023
1024
1025LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1026 Abort("Unimplemented: %s", "DoArgumentsElements");
1027 return NULL;
1028}
1029
1030
1031LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1032 Abort("Unimplemented: %s", "DoInstanceOf");
1033 return NULL;
1034}
1035
1036
1037LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1038 HInstanceOfKnownGlobal* instr) {
1039 Abort("Unimplemented: %s", "DoInstanceOfKnownGlobal");
1040 return NULL;
1041}
1042
1043
1044LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1045 Abort("Unimplemented: %s", "DoApplyArguments");
1046 return NULL;
1047}
1048
1049
1050LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1051 Abort("Unimplemented: %s", "DoPushArgument");
1052 return NULL;
1053}
1054
1055
1056LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1057 Abort("Unimplemented: %s", "DoGlobalObject");
1058 return NULL;
1059}
1060
1061
1062LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1063 Abort("Unimplemented: %s", "DoGlobalReceiver");
1064 return NULL;
1065}
1066
1067
1068LInstruction* LChunkBuilder::DoCallConstantFunction(
1069 HCallConstantFunction* instr) {
1070 Abort("Unimplemented: %s", "DoCallConstantFunction");
1071 return NULL;
1072}
1073
1074
1075LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1076 Abort("Unimplemented: %s", "DoUnaryMathOperation");
1077 return NULL;
1078}
1079
1080
1081LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1082 Abort("Unimplemented: %s", "DoCallKeyed");
1083 return NULL;
1084}
1085
1086
1087LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1088 Abort("Unimplemented: %s", "DoCallNamed");
1089 return NULL;
1090}
1091
1092
1093LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1094 Abort("Unimplemented: %s", "DoCallGlobal");
1095 return NULL;
1096}
1097
1098
1099LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1100 Abort("Unimplemented: %s", "DoCallKnownGlobal");
1101 return NULL;
1102}
1103
1104
1105LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1106 Abort("Unimplemented: %s", "DoCallNew");
1107 return NULL;
1108}
1109
1110
1111LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1112 Abort("Unimplemented: %s", "DoCallFunction");
1113 return NULL;
1114}
1115
1116
1117LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1118 Abort("Unimplemented: %s", "DoCallRuntime");
1119 return NULL;
1120}
1121
1122
1123LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1124 Abort("Unimplemented: %s", "DoShr");
1125 return NULL;
1126}
1127
1128
1129LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1130 Abort("Unimplemented: %s", "DoSar");
1131 return NULL;
1132}
1133
1134
1135LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1136 Abort("Unimplemented: %s", "DoShl");
1137 return NULL;
1138}
1139
1140
1141LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1142 Abort("Unimplemented: %s", "DoBitAnd");
1143 return NULL;
1144}
1145
1146
1147LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1148 Abort("Unimplemented: %s", "DoBitNot");
1149 return NULL;
1150}
1151
1152
1153LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1154 Abort("Unimplemented: %s", "DoBitOr");
1155 return NULL;
1156}
1157
1158
1159LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1160 Abort("Unimplemented: %s", "DoBitXor");
1161 return NULL;
1162}
1163
1164
1165LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1166 Abort("Unimplemented: %s", "DoDiv");
1167 return NULL;
1168}
1169
1170
1171LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1172 Abort("Unimplemented: %s", "DoMod");
1173 return NULL;
1174}
1175
1176
1177LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1178 Abort("Unimplemented: %s", "DoMul");
1179 return NULL;
1180}
1181
1182
1183LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1184 Abort("Unimplemented: %s", "DoSub");
1185 return NULL;
1186}
1187
1188
1189LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001190 if (instr->representation().IsInteger32()) {
1191 ASSERT(instr->left()->representation().IsInteger32());
1192 ASSERT(instr->right()->representation().IsInteger32());
1193 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1194 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1195 LAddI* add = new LAddI(left, right);
1196 LInstruction* result = DefineSameAsFirst(add);
1197 if (instr->CheckFlag(HValue::kCanOverflow)) {
1198 result = AssignEnvironment(result);
1199 }
1200 return result;
1201 } else if (instr->representation().IsDouble()) {
1202 Abort("Unimplemented: %s", "DoAdd on Doubles");
1203 } else {
1204 ASSERT(instr->representation().IsTagged());
1205 return DoArithmeticT(Token::ADD, instr);
1206 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001207 return NULL;
1208}
1209
1210
1211LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1212 Abort("Unimplemented: %s", "DoPower");
1213 return NULL;
1214}
1215
1216
1217LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001218 Token::Value op = instr->token();
1219 Representation r = instr->GetInputRepresentation();
1220 if (r.IsInteger32()) {
1221 ASSERT(instr->left()->representation().IsInteger32());
1222 ASSERT(instr->right()->representation().IsInteger32());
1223 LOperand* left = UseRegisterAtStart(instr->left());
1224 LOperand* right = UseOrConstantAtStart(instr->right());
1225 return DefineAsRegister(new LCmpID(left, right));
1226 } else if (r.IsDouble()) {
1227 ASSERT(instr->left()->representation().IsDouble());
1228 ASSERT(instr->right()->representation().IsDouble());
1229 LOperand* left = UseRegisterAtStart(instr->left());
1230 LOperand* right = UseRegisterAtStart(instr->right());
1231 return DefineAsRegister(new LCmpID(left, right));
1232 } else {
1233 ASSERT(instr->left()->representation().IsTagged());
1234 ASSERT(instr->right()->representation().IsTagged());
1235 bool reversed = (op == Token::GT || op == Token::LTE);
1236 LOperand* left = UseFixed(instr->left(), reversed ? rax : rdx);
1237 LOperand* right = UseFixed(instr->right(), reversed ? rdx : rax);
1238 LCmpT* result = new LCmpT(left, right);
1239 return MarkAsCall(DefineFixed(result, rax), instr);
1240 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001241}
1242
1243
1244LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1245 HCompareJSObjectEq* instr) {
1246 Abort("Unimplemented: %s", "DoCompareJSObjectEq");
1247 return NULL;
1248}
1249
1250
1251LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1252 Abort("Unimplemented: %s", "DoIsNull");
1253 return NULL;
1254}
1255
1256
1257LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1258 Abort("Unimplemented: %s", "DoIsObject");
1259 return NULL;
1260}
1261
1262
1263LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1264 Abort("Unimplemented: %s", "DoIsSmi");
1265 return NULL;
1266}
1267
1268
1269LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1270 Abort("Unimplemented: %s", "DoHasInstanceType");
1271 return NULL;
1272}
1273
1274
1275LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1276 HHasCachedArrayIndex* instr) {
1277 Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
1278 return NULL;
1279}
1280
1281
1282LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1283 Abort("Unimplemented: %s", "DoClassOfTest");
1284 return NULL;
1285}
1286
1287
1288LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1289 Abort("Unimplemented: %s", "DoJSArrayLength");
1290 return NULL;
1291}
1292
1293
1294LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1295 Abort("Unimplemented: %s", "DoFixedArrayLength");
1296 return NULL;
1297}
1298
1299
1300LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1301 Abort("Unimplemented: %s", "DoValueOf");
1302 return NULL;
1303}
1304
1305
1306LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1307 Abort("Unimplemented: %s", "DoBoundsCheck");
1308 return NULL;
1309}
1310
1311
1312LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1313 Abort("Unimplemented: %s", "DoThrow");
1314 return NULL;
1315}
1316
1317
1318LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1319 Abort("Unimplemented: %s", "DoChange");
1320 return NULL;
1321}
1322
1323
1324LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1325 Abort("Unimplemented: %s", "DoCheckNonSmi");
1326 return NULL;
1327}
1328
1329
1330LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1331 Abort("Unimplemented: %s", "DoCheckInstanceType");
1332 return NULL;
1333}
1334
1335
1336LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1337 Abort("Unimplemented: %s", "DoCheckPrototypeMaps");
1338 return NULL;
1339}
1340
1341
1342LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1343 Abort("Unimplemented: %s", "DoCheckSmi");
1344 return NULL;
1345}
1346
1347
1348LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1349 Abort("Unimplemented: %s", "DoCheckFunction");
1350 return NULL;
1351}
1352
1353
1354LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1355 Abort("Unimplemented: %s", "DoCheckMap");
1356 return NULL;
1357}
1358
1359
1360LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1361 return new LReturn(UseFixed(instr->value(), rax));
1362}
1363
1364
1365LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1366 Representation r = instr->representation();
1367 if (r.IsInteger32()) {
1368 int32_t value = instr->Integer32Value();
1369 return DefineAsRegister(new LConstantI(value));
1370 } else if (r.IsDouble()) {
1371 double value = instr->DoubleValue();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001372 LOperand* temp = TempRegister();
1373 return DefineAsRegister(new LConstantD(value, temp));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001374 } else if (r.IsTagged()) {
1375 return DefineAsRegister(new LConstantT(instr->handle()));
1376 } else {
1377 UNREACHABLE();
1378 return NULL;
1379 }
1380}
1381
1382
1383LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
1384 Abort("Unimplemented: %s", "DoLoadGlobal");
1385 return NULL;
1386}
1387
1388
1389LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
1390 Abort("Unimplemented: %s", "DoStoreGlobal");
1391 return NULL;
1392}
1393
1394
1395LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1396 Abort("Unimplemented: %s", "DoLoadContextSlot");
1397 return NULL;
1398}
1399
1400
1401LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1402 Abort("Unimplemented: %s", "DoLoadNamedField");
1403 return NULL;
1404}
1405
1406
1407LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1408 Abort("Unimplemented: %s", "DoLoadNamedGeneric");
1409 return NULL;
1410}
1411
1412
1413LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1414 HLoadFunctionPrototype* instr) {
1415 Abort("Unimplemented: %s", "DoLoadFunctionPrototype");
1416 return NULL;
1417}
1418
1419
1420LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1421 Abort("Unimplemented: %s", "DoLoadElements");
1422 return NULL;
1423}
1424
1425
1426LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1427 HLoadKeyedFastElement* instr) {
1428 Abort("Unimplemented: %s", "DoLoadKeyedFastElement");
1429 return NULL;
1430}
1431
1432
1433LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1434 Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
1435 return NULL;
1436}
1437
1438
1439LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1440 HStoreKeyedFastElement* instr) {
1441 Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
1442 return NULL;
1443}
1444
1445
1446LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1447 Abort("Unimplemented: %s", "DoStoreKeyedGeneric");
1448 return NULL;
1449}
1450
1451
1452LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1453 Abort("Unimplemented: %s", "DoStoreNamedField");
1454 return NULL;
1455}
1456
1457
1458LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1459 Abort("Unimplemented: %s", "DoStoreNamedGeneric");
1460 return NULL;
1461}
1462
1463
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001464LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1465 Abort("Unimplemented: %s", "DoStringCharCodeAt");
1466 return NULL;
1467}
1468
1469
1470LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1471 Abort("Unimplemented: %s", "DoStringLength");
1472 return NULL;
1473}
1474
1475
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001476LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1477 Abort("Unimplemented: %s", "DoArrayLiteral");
1478 return NULL;
1479}
1480
1481
1482LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1483 Abort("Unimplemented: %s", "DoObjectLiteral");
1484 return NULL;
1485}
1486
1487
1488LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1489 Abort("Unimplemented: %s", "DoRegExpLiteral");
1490 return NULL;
1491}
1492
1493
1494LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1495 Abort("Unimplemented: %s", "DoFunctionLiteral");
1496 return NULL;
1497}
1498
1499
1500LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
1501 Abort("Unimplemented: %s", "DoDeleteProperty");
1502 return NULL;
1503}
1504
1505
1506LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1507 Abort("Unimplemented: %s", "DoOsrEntry");
1508 return NULL;
1509}
1510
1511
1512LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1513 int spill_index = chunk()->GetParameterStackSlot(instr->index());
1514 return DefineAsSpilled(new LParameter, spill_index);
1515}
1516
1517
1518LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
1519 Abort("Unimplemented: %s", "DoUnknownOSRValue");
1520 return NULL;
1521}
1522
1523
1524LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1525 Abort("Unimplemented: %s", "DoCallStub");
1526 return NULL;
1527}
1528
1529
1530LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
1531 Abort("Unimplemented: %s", "DoArgumentsObject");
1532 return NULL;
1533}
1534
1535
1536LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
1537 Abort("Unimplemented: %s", "DoAccessArgumentsAt");
1538 return NULL;
1539}
1540
1541
1542LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
1543 Abort("Unimplemented: %s", "DoTypeof");
1544 return NULL;
1545}
1546
1547
1548LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
1549 Abort("Unimplemented: %s", "DoTypeofIs");
1550 return NULL;
1551}
1552
1553LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1554 HEnvironment* env = current_block_->last_environment();
1555 ASSERT(env != NULL);
1556
1557 env->set_ast_id(instr->ast_id());
1558
1559 env->Drop(instr->pop_count());
1560 for (int i = 0; i < instr->values()->length(); ++i) {
1561 HValue* value = instr->values()->at(i);
1562 if (instr->HasAssignedIndexAt(i)) {
1563 env->Bind(instr->GetAssignedIndexAt(i), value);
1564 } else {
1565 env->Push(value);
1566 }
1567 }
1568 ASSERT(env->length() == instr->environment_length());
1569
1570 // If there is an instruction pending deoptimization environment create a
1571 // lazy bailout instruction to capture the environment.
1572 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
1573 LLazyBailout* lazy_bailout = new LLazyBailout;
1574 LInstruction* result = AssignEnvironment(lazy_bailout);
1575 instructions_pending_deoptimization_environment_->
1576 set_deoptimization_environment(result->environment());
1577 ClearInstructionPendingDeoptimizationEnvironment();
1578 return result;
1579 }
1580
1581 return NULL;
1582}
1583
1584
1585LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
1586 return MarkAsCall(new LStackCheck, instr);
1587}
1588
1589
1590LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
1591 Abort("Unimplemented: %s", "DoEnterInlined");
1592 return NULL;
1593}
1594
1595
1596LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
1597 Abort("Unimplemented: %s", "DoLeaveInlined");
1598 return NULL;
1599}
1600
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001601} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001602
1603#endif // V8_TARGET_ARCH_X64