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