blob: 5ef6eb7534a4c94b6a8fe74671778ee9c8945ec6 [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 }
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000850 if (current->IsBranch() && !instr->IsGoto()) {
851 // TODO(fschneider): Handle branch instructions uniformly like
852 // other instructions. This requires us to generate the right
853 // branch instruction already at the HIR level.
854 ASSERT(instr->IsControl());
855 HBranch* branch = HBranch::cast(current);
856 instr->set_hydrogen_value(branch->value());
857 HBasicBlock* first = branch->FirstSuccessor();
858 HBasicBlock* second = branch->SecondSuccessor();
859 ASSERT(first != NULL && second != NULL);
860 instr->SetBranchTargets(first->block_id(), second->block_id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000861 } else {
862 instr->set_hydrogen_value(current);
863 }
864
865 int index = chunk_->AddInstruction(instr, current_block_);
866 allocator_->SummarizeInstruction(index);
867 } else {
868 // This instruction should be omitted.
869 allocator_->OmitInstruction();
870 }
871 current_instruction_ = old_current;
872}
873
874
875LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
876 if (hydrogen_env == NULL) return NULL;
877
878 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
879 int ast_id = hydrogen_env->ast_id();
880 ASSERT(ast_id != AstNode::kNoNumber);
881 int value_count = hydrogen_env->length();
882 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
883 ast_id,
884 hydrogen_env->parameter_count(),
885 argument_count_,
886 value_count,
887 outer);
888 int argument_index = 0;
889 for (int i = 0; i < value_count; ++i) {
890 HValue* value = hydrogen_env->values()->at(i);
891 LOperand* op = NULL;
892 if (value->IsArgumentsObject()) {
893 op = NULL;
894 } else if (value->IsPushArgument()) {
895 op = new LArgument(argument_index++);
896 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000897 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000898 }
899 result->AddValue(op, value->representation());
900 }
901
902 return result;
903}
904
905
906LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
907 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(),
908 instr->include_stack_check());
909 return (instr->include_stack_check())
910 ? AssignPointerMap(result)
911 : result;
912}
913
914
915LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
916 Abort("Unimplemented: %s", "DoBranch");
917 return NULL;
918}
919
920
921LInstruction* LChunkBuilder::DoCompareMapAndBranch(
922 HCompareMapAndBranch* instr) {
923 Abort("Unimplemented: %s", "DoCompareMapAndBranch");
924 return NULL;
925}
926
927
928LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
929 Abort("Unimplemented: %s", "DoArgumentsLength");
930 return NULL;
931}
932
933
934LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
935 Abort("Unimplemented: %s", "DoArgumentsElements");
936 return NULL;
937}
938
939
940LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
941 Abort("Unimplemented: %s", "DoInstanceOf");
942 return NULL;
943}
944
945
946LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
947 HInstanceOfKnownGlobal* instr) {
948 Abort("Unimplemented: %s", "DoInstanceOfKnownGlobal");
949 return NULL;
950}
951
952
953LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
954 Abort("Unimplemented: %s", "DoApplyArguments");
955 return NULL;
956}
957
958
959LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
960 Abort("Unimplemented: %s", "DoPushArgument");
961 return NULL;
962}
963
964
965LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
966 Abort("Unimplemented: %s", "DoGlobalObject");
967 return NULL;
968}
969
970
971LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
972 Abort("Unimplemented: %s", "DoGlobalReceiver");
973 return NULL;
974}
975
976
977LInstruction* LChunkBuilder::DoCallConstantFunction(
978 HCallConstantFunction* instr) {
979 Abort("Unimplemented: %s", "DoCallConstantFunction");
980 return NULL;
981}
982
983
984LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
985 Abort("Unimplemented: %s", "DoUnaryMathOperation");
986 return NULL;
987}
988
989
990LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
991 Abort("Unimplemented: %s", "DoCallKeyed");
992 return NULL;
993}
994
995
996LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
997 Abort("Unimplemented: %s", "DoCallNamed");
998 return NULL;
999}
1000
1001
1002LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1003 Abort("Unimplemented: %s", "DoCallGlobal");
1004 return NULL;
1005}
1006
1007
1008LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1009 Abort("Unimplemented: %s", "DoCallKnownGlobal");
1010 return NULL;
1011}
1012
1013
1014LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1015 Abort("Unimplemented: %s", "DoCallNew");
1016 return NULL;
1017}
1018
1019
1020LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1021 Abort("Unimplemented: %s", "DoCallFunction");
1022 return NULL;
1023}
1024
1025
1026LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1027 Abort("Unimplemented: %s", "DoCallRuntime");
1028 return NULL;
1029}
1030
1031
1032LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1033 Abort("Unimplemented: %s", "DoShr");
1034 return NULL;
1035}
1036
1037
1038LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1039 Abort("Unimplemented: %s", "DoSar");
1040 return NULL;
1041}
1042
1043
1044LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1045 Abort("Unimplemented: %s", "DoShl");
1046 return NULL;
1047}
1048
1049
1050LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1051 Abort("Unimplemented: %s", "DoBitAnd");
1052 return NULL;
1053}
1054
1055
1056LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1057 Abort("Unimplemented: %s", "DoBitNot");
1058 return NULL;
1059}
1060
1061
1062LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1063 Abort("Unimplemented: %s", "DoBitOr");
1064 return NULL;
1065}
1066
1067
1068LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1069 Abort("Unimplemented: %s", "DoBitXor");
1070 return NULL;
1071}
1072
1073
1074LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1075 Abort("Unimplemented: %s", "DoDiv");
1076 return NULL;
1077}
1078
1079
1080LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1081 Abort("Unimplemented: %s", "DoMod");
1082 return NULL;
1083}
1084
1085
1086LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1087 Abort("Unimplemented: %s", "DoMul");
1088 return NULL;
1089}
1090
1091
1092LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1093 Abort("Unimplemented: %s", "DoSub");
1094 return NULL;
1095}
1096
1097
1098LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001099 if (instr->representation().IsInteger32()) {
1100 ASSERT(instr->left()->representation().IsInteger32());
1101 ASSERT(instr->right()->representation().IsInteger32());
1102 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1103 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1104 LAddI* add = new LAddI(left, right);
1105 LInstruction* result = DefineSameAsFirst(add);
1106 if (instr->CheckFlag(HValue::kCanOverflow)) {
1107 result = AssignEnvironment(result);
1108 }
1109 return result;
1110 } else if (instr->representation().IsDouble()) {
1111 Abort("Unimplemented: %s", "DoAdd on Doubles");
1112 } else {
1113 ASSERT(instr->representation().IsTagged());
1114 return DoArithmeticT(Token::ADD, instr);
1115 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001116 return NULL;
1117}
1118
1119
1120LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1121 Abort("Unimplemented: %s", "DoPower");
1122 return NULL;
1123}
1124
1125
1126LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1127 Abort("Unimplemented: %s", "DoCompare");
1128 return NULL;
1129}
1130
1131
1132LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1133 HCompareJSObjectEq* instr) {
1134 Abort("Unimplemented: %s", "DoCompareJSObjectEq");
1135 return NULL;
1136}
1137
1138
1139LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1140 Abort("Unimplemented: %s", "DoIsNull");
1141 return NULL;
1142}
1143
1144
1145LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1146 Abort("Unimplemented: %s", "DoIsObject");
1147 return NULL;
1148}
1149
1150
1151LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1152 Abort("Unimplemented: %s", "DoIsSmi");
1153 return NULL;
1154}
1155
1156
1157LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1158 Abort("Unimplemented: %s", "DoHasInstanceType");
1159 return NULL;
1160}
1161
1162
1163LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1164 HHasCachedArrayIndex* instr) {
1165 Abort("Unimplemented: %s", "DoHasCachedArrayIndex");
1166 return NULL;
1167}
1168
1169
1170LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1171 Abort("Unimplemented: %s", "DoClassOfTest");
1172 return NULL;
1173}
1174
1175
1176LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1177 Abort("Unimplemented: %s", "DoJSArrayLength");
1178 return NULL;
1179}
1180
1181
1182LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1183 Abort("Unimplemented: %s", "DoFixedArrayLength");
1184 return NULL;
1185}
1186
1187
1188LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1189 Abort("Unimplemented: %s", "DoValueOf");
1190 return NULL;
1191}
1192
1193
1194LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1195 Abort("Unimplemented: %s", "DoBoundsCheck");
1196 return NULL;
1197}
1198
1199
1200LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1201 Abort("Unimplemented: %s", "DoThrow");
1202 return NULL;
1203}
1204
1205
1206LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1207 Abort("Unimplemented: %s", "DoChange");
1208 return NULL;
1209}
1210
1211
1212LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1213 Abort("Unimplemented: %s", "DoCheckNonSmi");
1214 return NULL;
1215}
1216
1217
1218LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1219 Abort("Unimplemented: %s", "DoCheckInstanceType");
1220 return NULL;
1221}
1222
1223
1224LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1225 Abort("Unimplemented: %s", "DoCheckPrototypeMaps");
1226 return NULL;
1227}
1228
1229
1230LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1231 Abort("Unimplemented: %s", "DoCheckSmi");
1232 return NULL;
1233}
1234
1235
1236LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1237 Abort("Unimplemented: %s", "DoCheckFunction");
1238 return NULL;
1239}
1240
1241
1242LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1243 Abort("Unimplemented: %s", "DoCheckMap");
1244 return NULL;
1245}
1246
1247
1248LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1249 return new LReturn(UseFixed(instr->value(), rax));
1250}
1251
1252
1253LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1254 Representation r = instr->representation();
1255 if (r.IsInteger32()) {
1256 int32_t value = instr->Integer32Value();
1257 return DefineAsRegister(new LConstantI(value));
1258 } else if (r.IsDouble()) {
1259 double value = instr->DoubleValue();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001260 LOperand* temp = TempRegister();
1261 return DefineAsRegister(new LConstantD(value, temp));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001262 } else if (r.IsTagged()) {
1263 return DefineAsRegister(new LConstantT(instr->handle()));
1264 } else {
1265 UNREACHABLE();
1266 return NULL;
1267 }
1268}
1269
1270
1271LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
1272 Abort("Unimplemented: %s", "DoLoadGlobal");
1273 return NULL;
1274}
1275
1276
1277LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
1278 Abort("Unimplemented: %s", "DoStoreGlobal");
1279 return NULL;
1280}
1281
1282
1283LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1284 Abort("Unimplemented: %s", "DoLoadContextSlot");
1285 return NULL;
1286}
1287
1288
1289LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1290 Abort("Unimplemented: %s", "DoLoadNamedField");
1291 return NULL;
1292}
1293
1294
1295LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1296 Abort("Unimplemented: %s", "DoLoadNamedGeneric");
1297 return NULL;
1298}
1299
1300
1301LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1302 HLoadFunctionPrototype* instr) {
1303 Abort("Unimplemented: %s", "DoLoadFunctionPrototype");
1304 return NULL;
1305}
1306
1307
1308LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1309 Abort("Unimplemented: %s", "DoLoadElements");
1310 return NULL;
1311}
1312
1313
1314LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1315 HLoadKeyedFastElement* instr) {
1316 Abort("Unimplemented: %s", "DoLoadKeyedFastElement");
1317 return NULL;
1318}
1319
1320
1321LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1322 Abort("Unimplemented: %s", "DoLoadKeyedGeneric");
1323 return NULL;
1324}
1325
1326
1327LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1328 HStoreKeyedFastElement* instr) {
1329 Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
1330 return NULL;
1331}
1332
1333
1334LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1335 Abort("Unimplemented: %s", "DoStoreKeyedGeneric");
1336 return NULL;
1337}
1338
1339
1340LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1341 Abort("Unimplemented: %s", "DoStoreNamedField");
1342 return NULL;
1343}
1344
1345
1346LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1347 Abort("Unimplemented: %s", "DoStoreNamedGeneric");
1348 return NULL;
1349}
1350
1351
1352LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1353 Abort("Unimplemented: %s", "DoArrayLiteral");
1354 return NULL;
1355}
1356
1357
1358LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1359 Abort("Unimplemented: %s", "DoObjectLiteral");
1360 return NULL;
1361}
1362
1363
1364LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1365 Abort("Unimplemented: %s", "DoRegExpLiteral");
1366 return NULL;
1367}
1368
1369
1370LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1371 Abort("Unimplemented: %s", "DoFunctionLiteral");
1372 return NULL;
1373}
1374
1375
1376LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
1377 Abort("Unimplemented: %s", "DoDeleteProperty");
1378 return NULL;
1379}
1380
1381
1382LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1383 Abort("Unimplemented: %s", "DoOsrEntry");
1384 return NULL;
1385}
1386
1387
1388LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1389 int spill_index = chunk()->GetParameterStackSlot(instr->index());
1390 return DefineAsSpilled(new LParameter, spill_index);
1391}
1392
1393
1394LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
1395 Abort("Unimplemented: %s", "DoUnknownOSRValue");
1396 return NULL;
1397}
1398
1399
1400LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1401 Abort("Unimplemented: %s", "DoCallStub");
1402 return NULL;
1403}
1404
1405
1406LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
1407 Abort("Unimplemented: %s", "DoArgumentsObject");
1408 return NULL;
1409}
1410
1411
1412LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
1413 Abort("Unimplemented: %s", "DoAccessArgumentsAt");
1414 return NULL;
1415}
1416
1417
1418LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
1419 Abort("Unimplemented: %s", "DoTypeof");
1420 return NULL;
1421}
1422
1423
1424LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
1425 Abort("Unimplemented: %s", "DoTypeofIs");
1426 return NULL;
1427}
1428
1429LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1430 HEnvironment* env = current_block_->last_environment();
1431 ASSERT(env != NULL);
1432
1433 env->set_ast_id(instr->ast_id());
1434
1435 env->Drop(instr->pop_count());
1436 for (int i = 0; i < instr->values()->length(); ++i) {
1437 HValue* value = instr->values()->at(i);
1438 if (instr->HasAssignedIndexAt(i)) {
1439 env->Bind(instr->GetAssignedIndexAt(i), value);
1440 } else {
1441 env->Push(value);
1442 }
1443 }
1444 ASSERT(env->length() == instr->environment_length());
1445
1446 // If there is an instruction pending deoptimization environment create a
1447 // lazy bailout instruction to capture the environment.
1448 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
1449 LLazyBailout* lazy_bailout = new LLazyBailout;
1450 LInstruction* result = AssignEnvironment(lazy_bailout);
1451 instructions_pending_deoptimization_environment_->
1452 set_deoptimization_environment(result->environment());
1453 ClearInstructionPendingDeoptimizationEnvironment();
1454 return result;
1455 }
1456
1457 return NULL;
1458}
1459
1460
1461LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
1462 return MarkAsCall(new LStackCheck, instr);
1463}
1464
1465
1466LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
1467 Abort("Unimplemented: %s", "DoEnterInlined");
1468 return NULL;
1469}
1470
1471
1472LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
1473 Abort("Unimplemented: %s", "DoLeaveInlined");
1474 return NULL;
1475}
1476
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001477} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001478
1479#endif // V8_TARGET_ARCH_X64