blob: e79465cb3a4689e20a8afb0a649da81bc9eb5230 [file] [log] [blame]
Ben Murdoch086aeea2011-05-13 15:57:08 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
Steve Block1e0659c2011-05-24 12:43:12 +010028#include "lithium-allocator-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010029#include "arm/lithium-arm.h"
30#include "arm/lithium-codegen-arm.h"
31
32namespace v8 {
33namespace internal {
34
35#define DEFINE_COMPILE(type) \
36 void L##type::CompileToNative(LCodeGen* generator) { \
37 generator->Do##type(this); \
38 }
39LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
40#undef DEFINE_COMPILE
41
42LOsrEntry::LOsrEntry() {
43 for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
44 register_spills_[i] = NULL;
45 }
46 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
47 double_register_spills_[i] = NULL;
48 }
49}
50
51
52void LOsrEntry::MarkSpilledRegister(int allocation_index,
53 LOperand* spill_operand) {
54 ASSERT(spill_operand->IsStackSlot());
55 ASSERT(register_spills_[allocation_index] == NULL);
56 register_spills_[allocation_index] = spill_operand;
57}
58
59
Steve Block1e0659c2011-05-24 12:43:12 +010060#ifdef DEBUG
61void LInstruction::VerifyCall() {
62 // Call instructions can use only fixed registers as
63 // temporaries and outputs because all registers
64 // are blocked by the calling convention.
65 // Inputs must use a fixed register.
66 ASSERT(Output() == NULL ||
67 LUnallocated::cast(Output())->HasFixedPolicy() ||
68 !LUnallocated::cast(Output())->HasRegisterPolicy());
69 for (UseIterator it(this); it.HasNext(); it.Advance()) {
70 LOperand* operand = it.Next();
71 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
72 !LUnallocated::cast(operand)->HasRegisterPolicy());
73 }
74 for (TempIterator it(this); it.HasNext(); it.Advance()) {
75 LOperand* operand = it.Next();
76 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
77 !LUnallocated::cast(operand)->HasRegisterPolicy());
78 }
79}
80#endif
81
82
Ben Murdochb0fe1622011-05-05 13:52:32 +010083void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
84 LOperand* spill_operand) {
85 ASSERT(spill_operand->IsDoubleStackSlot());
86 ASSERT(double_register_spills_[allocation_index] == NULL);
87 double_register_spills_[allocation_index] = spill_operand;
88}
89
90
Steve Block1e0659c2011-05-24 12:43:12 +010091void LInstruction::PrintTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +010092 stream->Add("%s ", this->Mnemonic());
Steve Block1e0659c2011-05-24 12:43:12 +010093
94 PrintOutputOperandTo(stream);
95
Ben Murdochb0fe1622011-05-05 13:52:32 +010096 PrintDataTo(stream);
97
98 if (HasEnvironment()) {
99 stream->Add(" ");
100 environment()->PrintTo(stream);
101 }
102
103 if (HasPointerMap()) {
104 stream->Add(" ");
105 pointer_map()->PrintTo(stream);
106 }
107}
108
109
Steve Block1e0659c2011-05-24 12:43:12 +0100110template<int R, int I, int T>
111void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
112 stream->Add("= ");
113 inputs_.PrintOperandsTo(stream);
114}
115
116
117template<int R, int I, int T>
118void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
119 results_.PrintOperandsTo(stream);
120}
121
122
123template<typename T, int N>
124void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
125 for (int i = 0; i < N; i++) {
126 if (i > 0) stream->Add(" ");
127 elems_[i]->PrintTo(stream);
128 }
129}
130
131
132void LLabel::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100133 LGap::PrintDataTo(stream);
134 LLabel* rep = replacement();
135 if (rep != NULL) {
136 stream->Add(" Dead block replaced with B%d", rep->block_id());
137 }
138}
139
140
Ben Murdochb0fe1622011-05-05 13:52:32 +0100141bool LGap::IsRedundant() const {
142 for (int i = 0; i < 4; i++) {
143 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
144 return false;
145 }
146 }
147
148 return true;
149}
150
151
152void LGap::PrintDataTo(StringStream* stream) const {
153 for (int i = 0; i < 4; i++) {
154 stream->Add("(");
155 if (parallel_moves_[i] != NULL) {
156 parallel_moves_[i]->PrintDataTo(stream);
157 }
158 stream->Add(") ");
159 }
160}
161
162
163const char* LArithmeticD::Mnemonic() const {
164 switch (op()) {
165 case Token::ADD: return "add-d";
166 case Token::SUB: return "sub-d";
167 case Token::MUL: return "mul-d";
168 case Token::DIV: return "div-d";
169 case Token::MOD: return "mod-d";
170 default:
171 UNREACHABLE();
172 return NULL;
173 }
174}
175
176
177const char* LArithmeticT::Mnemonic() const {
178 switch (op()) {
179 case Token::ADD: return "add-t";
180 case Token::SUB: return "sub-t";
181 case Token::MUL: return "mul-t";
182 case Token::MOD: return "mod-t";
183 case Token::DIV: return "div-t";
Steve Block1e0659c2011-05-24 12:43:12 +0100184 case Token::BIT_AND: return "bit-and-t";
185 case Token::BIT_OR: return "bit-or-t";
186 case Token::BIT_XOR: return "bit-xor-t";
187 case Token::SHL: return "shl-t";
188 case Token::SAR: return "sar-t";
189 case Token::SHR: return "shr-t";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100190 default:
191 UNREACHABLE();
192 return NULL;
193 }
194}
195
196
Steve Block1e0659c2011-05-24 12:43:12 +0100197void LGoto::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100198 stream->Add("B%d", block_id());
199}
200
201
Steve Block1e0659c2011-05-24 12:43:12 +0100202void LBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100203 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
Steve Block1e0659c2011-05-24 12:43:12 +0100204 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100205}
206
207
Steve Block1e0659c2011-05-24 12:43:12 +0100208void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100209 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100210 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100211 stream->Add(" %s ", Token::String(op()));
Steve Block1e0659c2011-05-24 12:43:12 +0100212 InputAt(1)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100213 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
214}
215
216
Steve Block1e0659c2011-05-24 12:43:12 +0100217void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100218 stream->Add("if ");
Steve Block1e0659c2011-05-24 12:43:12 +0100219 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220 stream->Add(is_strict() ? " === null" : " == null");
221 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
222}
223
224
Steve Block1e0659c2011-05-24 12:43:12 +0100225void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226 stream->Add("if is_object(");
Steve Block1e0659c2011-05-24 12:43:12 +0100227 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100228 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
229}
230
231
Steve Block1e0659c2011-05-24 12:43:12 +0100232void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233 stream->Add("if is_smi(");
Steve Block1e0659c2011-05-24 12:43:12 +0100234 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
236}
237
238
Steve Block1e0659c2011-05-24 12:43:12 +0100239void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100240 stream->Add("if has_instance_type(");
Steve Block1e0659c2011-05-24 12:43:12 +0100241 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100242 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
243}
244
245
Steve Block1e0659c2011-05-24 12:43:12 +0100246void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100247 stream->Add("if has_cached_array_index(");
Steve Block1e0659c2011-05-24 12:43:12 +0100248 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100249 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
250}
251
252
Steve Block1e0659c2011-05-24 12:43:12 +0100253void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100254 stream->Add("if class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100255 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100256 stream->Add(", \"%o\") then B%d else B%d",
257 *hydrogen()->class_name(),
258 true_block_id(),
259 false_block_id());
260}
261
262
Steve Block1e0659c2011-05-24 12:43:12 +0100263void LTypeofIs::PrintDataTo(StringStream* stream) {
264 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100265 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
266}
267
268
Steve Block1e0659c2011-05-24 12:43:12 +0100269void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100270 stream->Add("if typeof ");
Steve Block1e0659c2011-05-24 12:43:12 +0100271 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100272 stream->Add(" == \"%s\" then B%d else B%d",
273 *hydrogen()->type_literal()->ToCString(),
274 true_block_id(), false_block_id());
275}
276
277
Steve Block1e0659c2011-05-24 12:43:12 +0100278void LCallConstantFunction::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100279 stream->Add("#%d / ", arity());
280}
281
282
Steve Block1e0659c2011-05-24 12:43:12 +0100283void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100284 stream->Add("/%s ", hydrogen()->OpName());
Steve Block1e0659c2011-05-24 12:43:12 +0100285 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100286}
287
288
Ben Murdochb8e0da22011-05-16 14:20:40 +0100289void LLoadContextSlot::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100290 InputAt(0)->PrintTo(stream);
291 stream->Add("[%d]", slot_index());
Ben Murdochb8e0da22011-05-16 14:20:40 +0100292}
293
294
Steve Block1e0659c2011-05-24 12:43:12 +0100295void LStoreContextSlot::PrintDataTo(StringStream* stream) {
296 InputAt(0)->PrintTo(stream);
297 stream->Add("[%d] <- ", slot_index());
298 InputAt(1)->PrintTo(stream);
299}
300
301
302void LCallKeyed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100303 stream->Add("[r2] #%d / ", arity());
304}
305
306
Steve Block1e0659c2011-05-24 12:43:12 +0100307void LCallNamed::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100308 SmartPointer<char> name_string = name()->ToCString();
309 stream->Add("%s #%d / ", *name_string, arity());
310}
311
312
Steve Block1e0659c2011-05-24 12:43:12 +0100313void LCallGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100314 SmartPointer<char> name_string = name()->ToCString();
315 stream->Add("%s #%d / ", *name_string, arity());
316}
317
318
Steve Block1e0659c2011-05-24 12:43:12 +0100319void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100320 stream->Add("#%d / ", arity());
321}
322
323
Steve Block1e0659c2011-05-24 12:43:12 +0100324void LCallNew::PrintDataTo(StringStream* stream) {
325 stream->Add("= ");
326 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100327 stream->Add(" #%d / ", arity());
328}
329
330
Steve Block1e0659c2011-05-24 12:43:12 +0100331void LClassOfTest::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100332 stream->Add("= class_of_test(");
Steve Block1e0659c2011-05-24 12:43:12 +0100333 InputAt(0)->PrintTo(stream);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100334 stream->Add(", \"%o\")", *hydrogen()->class_name());
335}
336
337
Steve Block1e0659c2011-05-24 12:43:12 +0100338void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100339 arguments()->PrintTo(stream);
340
341 stream->Add(" length ");
342 length()->PrintTo(stream);
343
344 stream->Add(" index ");
345 index()->PrintTo(stream);
346}
347
348
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100349void LStoreNamedField::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100350 object()->PrintTo(stream);
351 stream->Add(".");
352 stream->Add(*String::cast(*name())->ToCString());
353 stream->Add(" <- ");
354 value()->PrintTo(stream);
355}
356
357
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100358void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
359 object()->PrintTo(stream);
360 stream->Add(".");
361 stream->Add(*String::cast(*name())->ToCString());
362 stream->Add(" <- ");
363 value()->PrintTo(stream);
364}
365
366
367void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
Steve Block1e0659c2011-05-24 12:43:12 +0100368 object()->PrintTo(stream);
369 stream->Add("[");
370 key()->PrintTo(stream);
371 stream->Add("] <- ");
372 value()->PrintTo(stream);
373}
374
375
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100376void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
377 object()->PrintTo(stream);
378 stream->Add("[");
379 key()->PrintTo(stream);
380 stream->Add("] <- ");
381 value()->PrintTo(stream);
382}
383
384
385LChunk::LChunk(CompilationInfo* info, HGraph* graph)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100386 : spill_slot_count_(0),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100387 info_(info),
Ben Murdochb0fe1622011-05-05 13:52:32 +0100388 graph_(graph),
389 instructions_(32),
390 pointer_maps_(8),
391 inlined_closures_(1) {
392}
393
394
Ben Murdochb0fe1622011-05-05 13:52:32 +0100395int LChunk::GetNextSpillIndex(bool is_double) {
396 // Skip a slot if for a double-width slot.
397 if (is_double) spill_slot_count_++;
398 return spill_slot_count_++;
399}
400
401
402LOperand* LChunk::GetNextSpillSlot(bool is_double) {
403 int index = GetNextSpillIndex(is_double);
404 if (is_double) {
405 return LDoubleStackSlot::Create(index);
406 } else {
407 return LStackSlot::Create(index);
408 }
409}
410
411
412void LChunk::MarkEmptyBlocks() {
413 HPhase phase("Mark empty blocks", this);
414 for (int i = 0; i < graph()->blocks()->length(); ++i) {
415 HBasicBlock* block = graph()->blocks()->at(i);
416 int first = block->first_instruction_index();
417 int last = block->last_instruction_index();
418 LInstruction* first_instr = instructions()->at(first);
419 LInstruction* last_instr = instructions()->at(last);
420
421 LLabel* label = LLabel::cast(first_instr);
422 if (last_instr->IsGoto()) {
423 LGoto* goto_instr = LGoto::cast(last_instr);
424 if (!goto_instr->include_stack_check() &&
425 label->IsRedundant() &&
426 !label->is_loop_header()) {
427 bool can_eliminate = true;
428 for (int i = first + 1; i < last && can_eliminate; ++i) {
429 LInstruction* cur = instructions()->at(i);
430 if (cur->IsGap()) {
431 LGap* gap = LGap::cast(cur);
432 if (!gap->IsRedundant()) {
433 can_eliminate = false;
434 }
435 } else {
436 can_eliminate = false;
437 }
438 }
439
440 if (can_eliminate) {
441 label->set_replacement(GetLabel(goto_instr->block_id()));
442 }
443 }
444 }
445 }
446}
447
448
Steve Block1e0659c2011-05-24 12:43:12 +0100449void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100450 LGap* gap = new LGap(block);
451 int index = -1;
452 if (instr->IsControl()) {
453 instructions_.Add(gap);
454 index = instructions_.length();
455 instructions_.Add(instr);
456 } else {
457 index = instructions_.length();
458 instructions_.Add(instr);
459 instructions_.Add(gap);
460 }
461 if (instr->HasPointerMap()) {
462 pointer_maps_.Add(instr->pointer_map());
463 instr->pointer_map()->set_lithium_position(index);
464 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100465}
466
467
468LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
469 return LConstantOperand::Create(constant->id());
470}
471
472
473int LChunk::GetParameterStackSlot(int index) const {
474 // The receiver is at index 0, the first parameter at index 1, so we
475 // shift all parameter indexes down by the number of parameters, and
476 // make sure they end up negative so they are distinguishable from
477 // spill slots.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100478 int result = index - info()->scope()->num_parameters() - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479 ASSERT(result < 0);
480 return result;
481}
482
483// A parameter relative to ebp in the arguments stub.
484int LChunk::ParameterAt(int index) {
485 ASSERT(-1 <= index); // -1 is the receiver.
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100486 return (1 + info()->scope()->num_parameters() - index) *
Ben Murdochb0fe1622011-05-05 13:52:32 +0100487 kPointerSize;
488}
489
490
491LGap* LChunk::GetGapAt(int index) const {
492 return LGap::cast(instructions_[index]);
493}
494
495
496bool LChunk::IsGapAt(int index) const {
497 return instructions_[index]->IsGap();
498}
499
500
501int LChunk::NearestGapPos(int index) const {
502 while (!IsGapAt(index)) index--;
503 return index;
504}
505
506
507void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
508 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
509}
510
511
Ben Murdochb0fe1622011-05-05 13:52:32 +0100512Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
513 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
514}
515
516
517Representation LChunk::LookupLiteralRepresentation(
518 LConstantOperand* operand) const {
519 return graph_->LookupValue(operand->index())->representation();
520}
521
522
523LChunk* LChunkBuilder::Build() {
524 ASSERT(is_unused());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100525 chunk_ = new LChunk(info(), graph());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100526 HPhase phase("Building chunk", chunk_);
527 status_ = BUILDING;
528 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
529 for (int i = 0; i < blocks->length(); i++) {
530 HBasicBlock* next = NULL;
531 if (i < blocks->length() - 1) next = blocks->at(i + 1);
532 DoBasicBlock(blocks->at(i), next);
533 if (is_aborted()) return NULL;
534 }
535 status_ = DONE;
536 return chunk_;
537}
538
539
540void LChunkBuilder::Abort(const char* format, ...) {
541 if (FLAG_trace_bailout) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100542 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
543 PrintF("Aborting LChunk building in @\"%s\": ", *name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100544 va_list arguments;
545 va_start(arguments, format);
546 OS::VPrint(format, arguments);
547 va_end(arguments);
548 PrintF("\n");
549 }
550 status_ = ABORTED;
551}
552
553
554LRegister* LChunkBuilder::ToOperand(Register reg) {
555 return LRegister::Create(Register::ToAllocationIndex(reg));
556}
557
558
559LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
560 return new LUnallocated(LUnallocated::FIXED_REGISTER,
561 Register::ToAllocationIndex(reg));
562}
563
564
565LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
566 return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
567 DoubleRegister::ToAllocationIndex(reg));
568}
569
570
571LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
572 return Use(value, ToUnallocated(fixed_register));
573}
574
575
576LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) {
577 return Use(value, ToUnallocated(reg));
578}
579
580
581LOperand* LChunkBuilder::UseRegister(HValue* value) {
582 return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
583}
584
585
586LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
587 return Use(value,
588 new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
589 LUnallocated::USED_AT_START));
590}
591
592
593LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
594 return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
595}
596
597
598LOperand* LChunkBuilder::Use(HValue* value) {
599 return Use(value, new LUnallocated(LUnallocated::NONE));
600}
601
602
603LOperand* LChunkBuilder::UseAtStart(HValue* value) {
604 return Use(value, new LUnallocated(LUnallocated::NONE,
605 LUnallocated::USED_AT_START));
606}
607
608
609LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
610 return value->IsConstant()
611 ? chunk_->DefineConstantOperand(HConstant::cast(value))
612 : Use(value);
613}
614
615
616LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
617 return value->IsConstant()
618 ? chunk_->DefineConstantOperand(HConstant::cast(value))
619 : UseAtStart(value);
620}
621
622
623LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
624 return value->IsConstant()
625 ? chunk_->DefineConstantOperand(HConstant::cast(value))
626 : UseRegister(value);
627}
628
629
630LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
631 return value->IsConstant()
632 ? chunk_->DefineConstantOperand(HConstant::cast(value))
633 : UseRegisterAtStart(value);
634}
635
636
Ben Murdochb8e0da22011-05-16 14:20:40 +0100637LOperand* LChunkBuilder::UseAny(HValue* value) {
638 return value->IsConstant()
639 ? chunk_->DefineConstantOperand(HConstant::cast(value))
640 : Use(value, new LUnallocated(LUnallocated::ANY));
641}
642
643
Ben Murdochb0fe1622011-05-05 13:52:32 +0100644LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
645 if (value->EmitAtUses()) {
646 HInstruction* instr = HInstruction::cast(value);
647 VisitInstruction(instr);
648 }
649 allocator_->RecordUse(value, operand);
650 return operand;
651}
652
653
Steve Block1e0659c2011-05-24 12:43:12 +0100654template<int I, int T>
655LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
656 LUnallocated* result) {
657 allocator_->RecordDefinition(current_instruction_, result);
658 instr->set_result(result);
659 return instr;
660}
661
662
663template<int I, int T>
664LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100665 return Define(instr, new LUnallocated(LUnallocated::NONE));
666}
667
668
Steve Block1e0659c2011-05-24 12:43:12 +0100669template<int I, int T>
670LInstruction* LChunkBuilder::DefineAsRegister(
671 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
673}
674
675
Steve Block1e0659c2011-05-24 12:43:12 +0100676template<int I, int T>
677LInstruction* LChunkBuilder::DefineAsSpilled(
678 LTemplateInstruction<1, I, T>* instr, int index) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100679 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
680}
681
682
Steve Block1e0659c2011-05-24 12:43:12 +0100683template<int I, int T>
684LInstruction* LChunkBuilder::DefineSameAsFirst(
685 LTemplateInstruction<1, I, T>* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100686 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
687}
688
689
Steve Block1e0659c2011-05-24 12:43:12 +0100690template<int I, int T>
691LInstruction* LChunkBuilder::DefineFixed(
692 LTemplateInstruction<1, I, T>* instr, Register reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100693 return Define(instr, ToUnallocated(reg));
694}
695
696
Steve Block1e0659c2011-05-24 12:43:12 +0100697template<int I, int T>
698LInstruction* LChunkBuilder::DefineFixedDouble(
699 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100700 return Define(instr, ToUnallocated(reg));
701}
702
703
704LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
705 HEnvironment* hydrogen_env = current_block_->last_environment();
706 instr->set_environment(CreateEnvironment(hydrogen_env));
707 return instr;
708}
709
710
711LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
712 LInstruction* instr, int ast_id) {
Steve Block1e0659c2011-05-24 12:43:12 +0100713 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100714 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
Steve Block1e0659c2011-05-24 12:43:12 +0100715 instruction_pending_deoptimization_environment_ = instr;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100716 pending_deoptimization_ast_id_ = ast_id;
717 return instr;
718}
719
720
721void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
Steve Block1e0659c2011-05-24 12:43:12 +0100722 instruction_pending_deoptimization_environment_ = NULL;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100723 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
724}
725
726
727LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
728 HInstruction* hinstr,
729 CanDeoptimize can_deoptimize) {
Steve Block1e0659c2011-05-24 12:43:12 +0100730#ifdef DEBUG
731 instr->VerifyCall();
732#endif
733 instr->MarkAsCall();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100734 instr = AssignPointerMap(instr);
735
736 if (hinstr->HasSideEffects()) {
737 ASSERT(hinstr->next()->IsSimulate());
738 HSimulate* sim = HSimulate::cast(hinstr->next());
739 instr = SetInstructionPendingDeoptimizationEnvironment(
740 instr, sim->ast_id());
741 }
742
743 // If instruction does not have side-effects lazy deoptimization
744 // after the call will try to deoptimize to the point before the call.
745 // Thus we still need to attach environment to this call even if
746 // call sequence can not deoptimize eagerly.
747 bool needs_environment =
748 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
749 if (needs_environment && !instr->HasEnvironment()) {
750 instr = AssignEnvironment(instr);
751 }
752
753 return instr;
754}
755
756
Steve Block1e0659c2011-05-24 12:43:12 +0100757LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
758 instr->MarkAsSaveDoubles();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100759 return instr;
760}
761
762
Steve Block1e0659c2011-05-24 12:43:12 +0100763LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
764 ASSERT(!instr->HasPointerMap());
765 instr->set_pointer_map(new LPointerMap(position_));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100766 return instr;
767}
768
769
Ben Murdochb0fe1622011-05-05 13:52:32 +0100770LUnallocated* LChunkBuilder::TempRegister() {
771 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
772 allocator_->RecordTemporary(operand);
773 return operand;
774}
775
776
777LOperand* LChunkBuilder::FixedTemp(Register reg) {
778 LUnallocated* operand = ToUnallocated(reg);
779 allocator_->RecordTemporary(operand);
780 return operand;
781}
782
783
784LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
785 LUnallocated* operand = ToUnallocated(reg);
786 allocator_->RecordTemporary(operand);
787 return operand;
788}
789
790
791LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
792 return new LLabel(instr->block());
793}
794
795
796LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
797 return AssignEnvironment(new LDeoptimize);
798}
799
800
801LInstruction* LChunkBuilder::DoBit(Token::Value op,
802 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100803 if (instr->representation().IsInteger32()) {
804 ASSERT(instr->left()->representation().IsInteger32());
805 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100806
Steve Block1e0659c2011-05-24 12:43:12 +0100807 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
808 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
809 return DefineSameAsFirst(new LBitI(op, left, right));
810 } else {
811 ASSERT(instr->representation().IsTagged());
812 ASSERT(instr->left()->representation().IsTagged());
813 ASSERT(instr->right()->representation().IsTagged());
814
815 LOperand* left = UseFixed(instr->left(), r1);
816 LOperand* right = UseFixed(instr->right(), r0);
817 LArithmeticT* result = new LArithmeticT(op, left, right);
818 return MarkAsCall(DefineFixed(result, r0), instr);
819 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100820}
821
822
823LInstruction* LChunkBuilder::DoShift(Token::Value op,
824 HBitwiseBinaryOperation* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +0100825 if (instr->representation().IsTagged()) {
826 ASSERT(instr->left()->representation().IsTagged());
827 ASSERT(instr->right()->representation().IsTagged());
828
829 LOperand* left = UseFixed(instr->left(), r1);
830 LOperand* right = UseFixed(instr->right(), r0);
831 LArithmeticT* result = new LArithmeticT(op, left, right);
832 return MarkAsCall(DefineFixed(result, r0), instr);
833 }
834
Ben Murdochb0fe1622011-05-05 13:52:32 +0100835 ASSERT(instr->representation().IsInteger32());
836 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
837 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
838 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
839
840 HValue* right_value = instr->OperandAt(1);
841 LOperand* right = NULL;
842 int constant_value = 0;
843 if (right_value->IsConstant()) {
844 HConstant* constant = HConstant::cast(right_value);
845 right = chunk_->DefineConstantOperand(constant);
846 constant_value = constant->Integer32Value() & 0x1f;
847 } else {
848 right = UseRegister(right_value);
849 }
850
851 // Shift operations can only deoptimize if we do a logical shift
852 // by 0 and the result cannot be truncated to int32.
853 bool can_deopt = (op == Token::SHR && constant_value == 0);
854 if (can_deopt) {
855 bool can_truncate = true;
856 for (int i = 0; i < instr->uses()->length(); i++) {
857 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
858 can_truncate = false;
859 break;
860 }
861 }
862 can_deopt = !can_truncate;
863 }
864
865 LInstruction* result =
866 DefineSameAsFirst(new LShiftI(op, left, right, can_deopt));
867 if (can_deopt) AssignEnvironment(result);
868 return result;
869}
870
871
872LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
873 HArithmeticBinaryOperation* instr) {
874 ASSERT(instr->representation().IsDouble());
875 ASSERT(instr->left()->representation().IsDouble());
876 ASSERT(instr->right()->representation().IsDouble());
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100877 ASSERT(op != Token::MOD);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100878 LOperand* left = UseRegisterAtStart(instr->left());
879 LOperand* right = UseRegisterAtStart(instr->right());
880 LArithmeticD* result = new LArithmeticD(op, left, right);
881 return DefineSameAsFirst(result);
882}
883
884
885LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
886 HArithmeticBinaryOperation* instr) {
887 ASSERT(op == Token::ADD ||
888 op == Token::DIV ||
889 op == Token::MOD ||
890 op == Token::MUL ||
891 op == Token::SUB);
892 HValue* left = instr->left();
893 HValue* right = instr->right();
894 ASSERT(left->representation().IsTagged());
895 ASSERT(right->representation().IsTagged());
896 LOperand* left_operand = UseFixed(left, r1);
897 LOperand* right_operand = UseFixed(right, r0);
Steve Block1e0659c2011-05-24 12:43:12 +0100898 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100899 return MarkAsCall(DefineFixed(result, r0), instr);
900}
901
Steve Block1e0659c2011-05-24 12:43:12 +0100902
Ben Murdochb0fe1622011-05-05 13:52:32 +0100903void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
904 ASSERT(is_building());
905 current_block_ = block;
906 next_block_ = next_block;
907 if (block->IsStartBlock()) {
908 block->UpdateEnvironment(graph_->start_environment());
909 argument_count_ = 0;
910 } else if (block->predecessors()->length() == 1) {
911 // We have a single predecessor => copy environment and outgoing
912 // argument count from the predecessor.
913 ASSERT(block->phis()->length() == 0);
914 HBasicBlock* pred = block->predecessors()->at(0);
915 HEnvironment* last_environment = pred->last_environment();
916 ASSERT(last_environment != NULL);
917 // Only copy the environment, if it is later used again.
918 if (pred->end()->SecondSuccessor() == NULL) {
919 ASSERT(pred->end()->FirstSuccessor() == block);
920 } else {
921 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
922 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
923 last_environment = last_environment->Copy();
924 }
925 }
926 block->UpdateEnvironment(last_environment);
927 ASSERT(pred->argument_count() >= 0);
928 argument_count_ = pred->argument_count();
929 } else {
930 // We are at a state join => process phis.
931 HBasicBlock* pred = block->predecessors()->at(0);
932 // No need to copy the environment, it cannot be used later.
933 HEnvironment* last_environment = pred->last_environment();
934 for (int i = 0; i < block->phis()->length(); ++i) {
935 HPhi* phi = block->phis()->at(i);
936 last_environment->SetValueAt(phi->merged_index(), phi);
937 }
938 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
939 last_environment->SetValueAt(block->deleted_phis()->at(i),
940 graph_->GetConstantUndefined());
941 }
942 block->UpdateEnvironment(last_environment);
943 // Pick up the outgoing argument count of one of the predecessors.
944 argument_count_ = pred->argument_count();
945 }
946 HInstruction* current = block->first();
947 int start = chunk_->instructions()->length();
948 while (current != NULL && !is_aborted()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100949 // Code for constants in registers is generated lazily.
950 if (!current->EmitAtUses()) {
951 VisitInstruction(current);
952 }
953 current = current->next();
954 }
955 int end = chunk_->instructions()->length() - 1;
956 if (end >= start) {
957 block->set_first_instruction_index(start);
958 block->set_last_instruction_index(end);
959 }
960 block->set_argument_count(argument_count_);
961 next_block_ = NULL;
962 current_block_ = NULL;
963}
964
965
966void LChunkBuilder::VisitInstruction(HInstruction* current) {
967 HInstruction* old_current = current_instruction_;
968 current_instruction_ = current;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100969 if (current->has_position()) position_ = current->position();
970 LInstruction* instr = current->CompileToLithium(this);
971
972 if (instr != NULL) {
973 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
974 instr = AssignPointerMap(instr);
975 }
976 if (FLAG_stress_environments && !instr->HasEnvironment()) {
977 instr = AssignEnvironment(instr);
978 }
Steve Block1e0659c2011-05-24 12:43:12 +0100979 if (current->IsTest() && !instr->IsGoto()) {
980 ASSERT(instr->IsControl());
981 HTest* test = HTest::cast(current);
982 instr->set_hydrogen_value(test->value());
983 HBasicBlock* first = test->FirstSuccessor();
984 HBasicBlock* second = test->SecondSuccessor();
985 ASSERT(first != NULL && second != NULL);
986 instr->SetBranchTargets(first->block_id(), second->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100987 } else {
988 instr->set_hydrogen_value(current);
989 }
990
Steve Block1e0659c2011-05-24 12:43:12 +0100991 chunk_->AddInstruction(instr, current_block_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100992 }
993 current_instruction_ = old_current;
994}
995
996
Ben Murdochb0fe1622011-05-05 13:52:32 +0100997LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
998 if (hydrogen_env == NULL) return NULL;
999
1000 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1001 int ast_id = hydrogen_env->ast_id();
1002 ASSERT(ast_id != AstNode::kNoNumber);
Steve Block9fac8402011-05-12 15:51:54 +01001003 int value_count = hydrogen_env->length();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001004 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1005 ast_id,
1006 hydrogen_env->parameter_count(),
1007 argument_count_,
1008 value_count,
1009 outer);
1010 int argument_index = 0;
1011 for (int i = 0; i < value_count; ++i) {
1012 HValue* value = hydrogen_env->values()->at(i);
1013 LOperand* op = NULL;
1014 if (value->IsArgumentsObject()) {
1015 op = NULL;
1016 } else if (value->IsPushArgument()) {
1017 op = new LArgument(argument_index++);
1018 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001019 op = UseAny(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001020 }
1021 result->AddValue(op, value->representation());
1022 }
1023
1024 return result;
1025}
1026
1027
1028LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1029 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(),
1030 instr->include_stack_check());
1031 if (instr->include_stack_check()) result = AssignPointerMap(result);
1032 return result;
1033}
1034
1035
Steve Block1e0659c2011-05-24 12:43:12 +01001036LInstruction* LChunkBuilder::DoTest(HTest* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001037 HValue* v = instr->value();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001038 if (v->EmitAtUses()) {
1039 if (v->IsClassOfTest()) {
1040 HClassOfTest* compare = HClassOfTest::cast(v);
1041 ASSERT(compare->value()->representation().IsTagged());
1042
1043 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
Steve Block1e0659c2011-05-24 12:43:12 +01001044 TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001045 } else if (v->IsCompare()) {
1046 HCompare* compare = HCompare::cast(v);
1047 Token::Value op = compare->token();
1048 HValue* left = compare->left();
1049 HValue* right = compare->right();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001050 Representation r = compare->GetInputRepresentation();
1051 if (r.IsInteger32()) {
1052 ASSERT(left->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001053 ASSERT(right->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001054 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001055 UseRegisterAtStart(right));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001056 } else if (r.IsDouble()) {
1057 ASSERT(left->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001058 ASSERT(right->representation().IsDouble());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001059 return new LCmpIDAndBranch(UseRegisterAtStart(left),
Steve Block1e0659c2011-05-24 12:43:12 +01001060 UseRegisterAtStart(right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001061 } else {
1062 ASSERT(left->representation().IsTagged());
1063 ASSERT(right->representation().IsTagged());
1064 bool reversed = op == Token::GT || op == Token::LTE;
1065 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1);
1066 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0);
1067 LInstruction* result = new LCmpTAndBranch(left_operand,
Steve Block1e0659c2011-05-24 12:43:12 +01001068 right_operand);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001069 return MarkAsCall(result, instr);
1070 }
1071 } else if (v->IsIsSmi()) {
1072 HIsSmi* compare = HIsSmi::cast(v);
1073 ASSERT(compare->value()->representation().IsTagged());
1074
Steve Block1e0659c2011-05-24 12:43:12 +01001075 return new LIsSmiAndBranch(Use(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001076 } else if (v->IsHasInstanceType()) {
1077 HHasInstanceType* compare = HHasInstanceType::cast(v);
1078 ASSERT(compare->value()->representation().IsTagged());
Steve Block1e0659c2011-05-24 12:43:12 +01001079 return new LHasInstanceTypeAndBranch(
1080 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001081 } else if (v->IsHasCachedArrayIndex()) {
1082 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1083 ASSERT(compare->value()->representation().IsTagged());
1084
1085 return new LHasCachedArrayIndexAndBranch(
Steve Block1e0659c2011-05-24 12:43:12 +01001086 UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001087 } else if (v->IsIsNull()) {
1088 HIsNull* compare = HIsNull::cast(v);
1089 ASSERT(compare->value()->representation().IsTagged());
1090
Steve Block1e0659c2011-05-24 12:43:12 +01001091 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001092 } else if (v->IsIsObject()) {
1093 HIsObject* compare = HIsObject::cast(v);
1094 ASSERT(compare->value()->representation().IsTagged());
1095
Steve Block1e0659c2011-05-24 12:43:12 +01001096 LOperand* temp = TempRegister();
1097 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001098 } else if (v->IsCompareJSObjectEq()) {
1099 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1100 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
Steve Block1e0659c2011-05-24 12:43:12 +01001101 UseRegisterAtStart(compare->right()));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001102 } else if (v->IsInstanceOf()) {
1103 HInstanceOf* instance_of = HInstanceOf::cast(v);
1104 LInstruction* result =
Steve Block1e0659c2011-05-24 12:43:12 +01001105 new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0),
1106 UseFixed(instance_of->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001107 return MarkAsCall(result, instr);
1108 } else if (v->IsTypeofIs()) {
1109 HTypeofIs* typeof_is = HTypeofIs::cast(v);
Steve Block1e0659c2011-05-24 12:43:12 +01001110 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1111 } else if (v->IsIsConstructCall()) {
1112 return new LIsConstructCallAndBranch(TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001113 } else {
1114 if (v->IsConstant()) {
1115 if (HConstant::cast(v)->handle()->IsTrue()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001116 return new LGoto(instr->FirstSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001117 } else if (HConstant::cast(v)->handle()->IsFalse()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001118 return new LGoto(instr->SecondSuccessor()->block_id());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001119 }
1120 }
1121 Abort("Undefined compare before branch");
1122 return NULL;
1123 }
1124 }
Steve Block1e0659c2011-05-24 12:43:12 +01001125 return new LBranch(UseRegisterAtStart(v));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001126}
1127
1128
Steve Block1e0659c2011-05-24 12:43:12 +01001129LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001130 ASSERT(instr->value()->representation().IsTagged());
1131 LOperand* value = UseRegisterAtStart(instr->value());
Steve Block9fac8402011-05-12 15:51:54 +01001132 LOperand* temp = TempRegister();
1133 return new LCmpMapAndBranch(value, temp);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001134}
1135
1136
1137LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001138 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001139}
1140
1141
1142LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1143 return DefineAsRegister(new LArgumentsElements);
1144}
1145
1146
1147LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001148 LInstanceOf* result =
Steve Block9fac8402011-05-12 15:51:54 +01001149 new LInstanceOf(UseFixed(instr->left(), r0),
1150 UseFixed(instr->right(), r1));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001151 return MarkAsCall(DefineFixed(result, r0), instr);
1152}
1153
1154
Ben Murdoch086aeea2011-05-13 15:57:08 +01001155LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1156 HInstanceOfKnownGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001157 LInstanceOfKnownGlobal* result =
1158 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001159 return MarkAsCall(DefineFixed(result, r0), instr);
Ben Murdoch086aeea2011-05-13 15:57:08 +01001160}
1161
1162
Ben Murdochb0fe1622011-05-05 13:52:32 +01001163LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1164 LOperand* function = UseFixed(instr->function(), r1);
1165 LOperand* receiver = UseFixed(instr->receiver(), r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001166 LOperand* length = UseFixed(instr->length(), r2);
1167 LOperand* elements = UseFixed(instr->elements(), r3);
1168 LApplyArguments* result = new LApplyArguments(function,
1169 receiver,
1170 length,
1171 elements);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001172 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
1173}
1174
1175
1176LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1177 ++argument_count_;
1178 LOperand* argument = Use(instr->argument());
1179 return new LPushArgument(argument);
1180}
1181
1182
Steve Block1e0659c2011-05-24 12:43:12 +01001183LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1184 return DefineAsRegister(new LContext);
1185}
1186
1187
1188LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1189 LOperand* context = UseRegisterAtStart(instr->value());
1190 return DefineAsRegister(new LOuterContext(context));
1191}
1192
1193
Ben Murdochb0fe1622011-05-05 13:52:32 +01001194LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001195 LOperand* context = UseRegisterAtStart(instr->value());
1196 return DefineAsRegister(new LGlobalObject(context));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001197}
1198
1199
1200LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001201 LOperand* global_object = UseRegisterAtStart(instr->value());
1202 return DefineAsRegister(new LGlobalReceiver(global_object));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001203}
1204
1205
1206LInstruction* LChunkBuilder::DoCallConstantFunction(
1207 HCallConstantFunction* instr) {
1208 argument_count_ -= instr->argument_count();
1209 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr);
1210}
1211
1212
1213LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1214 BuiltinFunctionId op = instr->op();
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001215 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1216 LOperand* input = UseFixedDouble(instr->value(), d2);
1217 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
1218 return MarkAsCall(DefineFixedDouble(result, d2), instr);
1219 } else {
1220 LOperand* input = UseRegisterAtStart(instr->value());
1221 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
1222 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
1223 switch (op) {
1224 case kMathAbs:
1225 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1226 case kMathFloor:
1227 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1228 case kMathSqrt:
1229 return DefineSameAsFirst(result);
1230 case kMathRound:
1231 return AssignEnvironment(DefineAsRegister(result));
1232 case kMathPowHalf:
1233 Abort("MathPowHalf LUnaryMathOperation not implemented");
1234 return NULL;
1235 default:
1236 UNREACHABLE();
1237 return NULL;
1238 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001239 }
1240}
1241
1242
1243LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1244 ASSERT(instr->key()->representation().IsTagged());
1245 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001246 LOperand* key = UseFixed(instr->key(), r2);
1247 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001248}
1249
1250
1251LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1252 argument_count_ -= instr->argument_count();
1253 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr);
1254}
1255
1256
1257LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1258 argument_count_ -= instr->argument_count();
1259 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr);
1260}
1261
1262
1263LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1264 argument_count_ -= instr->argument_count();
1265 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr);
1266}
1267
1268
1269LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1270 LOperand* constructor = UseFixed(instr->constructor(), r1);
1271 argument_count_ -= instr->argument_count();
Steve Block1e0659c2011-05-24 12:43:12 +01001272 LCallNew* result = new LCallNew(constructor);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001273 return MarkAsCall(DefineFixed(result, r0), instr);
1274}
1275
1276
1277LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1278 argument_count_ -= instr->argument_count();
1279 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr);
1280}
1281
1282
1283LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1284 argument_count_ -= instr->argument_count();
1285 return MarkAsCall(DefineFixed(new LCallRuntime, r0), instr);
1286}
1287
1288
1289LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1290 return DoShift(Token::SHR, instr);
1291}
1292
1293
1294LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1295 return DoShift(Token::SAR, instr);
1296}
1297
1298
1299LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1300 return DoShift(Token::SHL, instr);
1301}
1302
1303
1304LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1305 return DoBit(Token::BIT_AND, instr);
1306}
1307
1308
1309LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1310 ASSERT(instr->value()->representation().IsInteger32());
1311 ASSERT(instr->representation().IsInteger32());
1312 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value())));
1313}
1314
1315
1316LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1317 return DoBit(Token::BIT_OR, instr);
1318}
1319
1320
1321LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1322 return DoBit(Token::BIT_XOR, instr);
1323}
1324
1325
1326LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1327 if (instr->representation().IsDouble()) {
1328 return DoArithmeticD(Token::DIV, instr);
1329 } else if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001330 // TODO(1042) The fixed register allocation
1331 // is needed because we call GenericBinaryOpStub from
1332 // the generated code, which requires registers r0
1333 // and r1 to be used. We should remove that
1334 // when we provide a native implementation.
Steve Block1e0659c2011-05-24 12:43:12 +01001335 LOperand* dividend = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001336 LOperand* divisor = UseFixed(instr->right(), r1);
1337 return AssignEnvironment(AssignPointerMap(
Steve Block1e0659c2011-05-24 12:43:12 +01001338 DefineFixed(new LDivI(dividend, divisor), r0)));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001339 } else {
1340 return DoArithmeticT(Token::DIV, instr);
1341 }
1342}
1343
1344
1345LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1346 if (instr->representation().IsInteger32()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001347 // TODO(1042) The fixed register allocation
1348 // is needed because we call GenericBinaryOpStub from
1349 // the generated code, which requires registers r0
1350 // and r1 to be used. We should remove that
1351 // when we provide a native implementation.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001352 ASSERT(instr->left()->representation().IsInteger32());
1353 ASSERT(instr->right()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001354 LOperand* value = UseFixed(instr->left(), r0);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001355 LOperand* divisor = UseFixed(instr->right(), r1);
1356 LInstruction* result = DefineFixed(new LModI(value, divisor), r0);
1357 result = AssignEnvironment(AssignPointerMap(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001358 return result;
1359 } else if (instr->representation().IsTagged()) {
1360 return DoArithmeticT(Token::MOD, instr);
1361 } else {
1362 ASSERT(instr->representation().IsDouble());
1363 // We call a C function for double modulo. It can't trigger a GC.
1364 // We need to use fixed result register for the call.
1365 // TODO(fschneider): Allow any register as input registers.
1366 LOperand* left = UseFixedDouble(instr->left(), d1);
1367 LOperand* right = UseFixedDouble(instr->right(), d2);
1368 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
1369 return MarkAsCall(DefineFixedDouble(result, d1), instr);
1370 }
1371}
1372
1373
1374LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1375 if (instr->representation().IsInteger32()) {
1376 ASSERT(instr->left()->representation().IsInteger32());
1377 ASSERT(instr->right()->representation().IsInteger32());
1378 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1379 LOperand* right = UseOrConstant(instr->MostConstantOperand());
1380 LOperand* temp = NULL;
1381 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1382 temp = TempRegister();
1383 }
1384 LMulI* mul = new LMulI(left, right, temp);
1385 return AssignEnvironment(DefineSameAsFirst(mul));
1386 } else if (instr->representation().IsDouble()) {
1387 return DoArithmeticD(Token::MUL, instr);
1388 } else {
1389 return DoArithmeticT(Token::MUL, instr);
1390 }
1391}
1392
1393
1394LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1395 if (instr->representation().IsInteger32()) {
1396 ASSERT(instr->left()->representation().IsInteger32());
1397 ASSERT(instr->right()->representation().IsInteger32());
Steve Block1e0659c2011-05-24 12:43:12 +01001398 LOperand* left = UseRegisterAtStart(instr->left());
1399 LOperand* right = UseOrConstantAtStart(instr->right());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001400 LSubI* sub = new LSubI(left, right);
1401 LInstruction* result = DefineSameAsFirst(sub);
1402 if (instr->CheckFlag(HValue::kCanOverflow)) {
1403 result = AssignEnvironment(result);
1404 }
1405 return result;
1406 } else if (instr->representation().IsDouble()) {
1407 return DoArithmeticD(Token::SUB, instr);
1408 } else {
1409 return DoArithmeticT(Token::SUB, instr);
1410 }
1411}
1412
1413
1414LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1415 if (instr->representation().IsInteger32()) {
1416 ASSERT(instr->left()->representation().IsInteger32());
1417 ASSERT(instr->right()->representation().IsInteger32());
1418 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1419 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
1420 LAddI* add = new LAddI(left, right);
1421 LInstruction* result = DefineSameAsFirst(add);
1422 if (instr->CheckFlag(HValue::kCanOverflow)) {
1423 result = AssignEnvironment(result);
1424 }
1425 return result;
1426 } else if (instr->representation().IsDouble()) {
1427 return DoArithmeticD(Token::ADD, instr);
1428 } else {
1429 ASSERT(instr->representation().IsTagged());
1430 return DoArithmeticT(Token::ADD, instr);
1431 }
1432}
1433
1434
1435LInstruction* LChunkBuilder::DoPower(HPower* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001436 ASSERT(instr->representation().IsDouble());
1437 // We call a C function for double power. It can't trigger a GC.
1438 // We need to use fixed result register for the call.
1439 Representation exponent_type = instr->right()->representation();
1440 ASSERT(instr->left()->representation().IsDouble());
1441 LOperand* left = UseFixedDouble(instr->left(), d1);
1442 LOperand* right = exponent_type.IsDouble() ?
1443 UseFixedDouble(instr->right(), d2) :
1444 UseFixed(instr->right(), r0);
1445 LPower* result = new LPower(left, right);
1446 return MarkAsCall(DefineFixedDouble(result, d3),
1447 instr,
1448 CAN_DEOPTIMIZE_EAGERLY);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001449}
1450
1451
1452LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1453 Token::Value op = instr->token();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001454 Representation r = instr->GetInputRepresentation();
1455 if (r.IsInteger32()) {
1456 ASSERT(instr->left()->representation().IsInteger32());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001457 ASSERT(instr->right()->representation().IsInteger32());
1458 LOperand* left = UseRegisterAtStart(instr->left());
Steve Block1e0659c2011-05-24 12:43:12 +01001459 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001460 return DefineAsRegister(new LCmpID(left, right));
1461 } else if (r.IsDouble()) {
1462 ASSERT(instr->left()->representation().IsDouble());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001463 ASSERT(instr->right()->representation().IsDouble());
1464 LOperand* left = UseRegisterAtStart(instr->left());
1465 LOperand* right = UseRegisterAtStart(instr->right());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001466 return DefineAsRegister(new LCmpID(left, right));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001467 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001468 ASSERT(instr->left()->representation().IsTagged());
1469 ASSERT(instr->right()->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001470 bool reversed = (op == Token::GT || op == Token::LTE);
1471 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
1472 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
Steve Block1e0659c2011-05-24 12:43:12 +01001473 LCmpT* result = new LCmpT(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001474 return MarkAsCall(DefineFixed(result, r0), instr);
1475 }
1476}
1477
1478
1479LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1480 HCompareJSObjectEq* instr) {
1481 LOperand* left = UseRegisterAtStart(instr->left());
1482 LOperand* right = UseRegisterAtStart(instr->right());
Steve Block1e0659c2011-05-24 12:43:12 +01001483 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001484 return DefineAsRegister(result);
1485}
1486
1487
1488LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1489 ASSERT(instr->value()->representation().IsTagged());
1490 LOperand* value = UseRegisterAtStart(instr->value());
1491
Ben Murdochb8e0da22011-05-16 14:20:40 +01001492 return DefineAsRegister(new LIsNull(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001493}
1494
1495
1496LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1497 ASSERT(instr->value()->representation().IsTagged());
1498 LOperand* value = UseRegisterAtStart(instr->value());
1499
Steve Block1e0659c2011-05-24 12:43:12 +01001500 return DefineAsRegister(new LIsObject(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001501}
1502
1503
1504LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
1505 ASSERT(instr->value()->representation().IsTagged());
1506 LOperand* value = UseAtStart(instr->value());
1507
1508 return DefineAsRegister(new LIsSmi(value));
1509}
1510
1511
1512LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
1513 ASSERT(instr->value()->representation().IsTagged());
1514 LOperand* value = UseRegisterAtStart(instr->value());
1515
1516 return DefineAsRegister(new LHasInstanceType(value));
1517}
1518
1519
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001520LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1521 HGetCachedArrayIndex* instr) {
1522 ASSERT(instr->value()->representation().IsTagged());
1523 LOperand* value = UseRegisterAtStart(instr->value());
1524
1525 return DefineAsRegister(new LGetCachedArrayIndex(value));
1526}
1527
1528
Ben Murdochb0fe1622011-05-05 13:52:32 +01001529LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
1530 HHasCachedArrayIndex* instr) {
1531 ASSERT(instr->value()->representation().IsTagged());
1532 LOperand* value = UseRegister(instr->value());
1533
1534 return DefineAsRegister(new LHasCachedArrayIndex(value));
1535}
1536
1537
1538LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
1539 ASSERT(instr->value()->representation().IsTagged());
1540 LOperand* value = UseTempRegister(instr->value());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001541 return DefineSameAsFirst(new LClassOfTest(value));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001542}
1543
1544
Steve Block9fac8402011-05-12 15:51:54 +01001545LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
1546 LOperand* array = UseRegisterAtStart(instr->value());
1547 return DefineAsRegister(new LJSArrayLength(array));
1548}
Ben Murdochb0fe1622011-05-05 13:52:32 +01001549
Ben Murdochb0fe1622011-05-05 13:52:32 +01001550
Steve Block1e0659c2011-05-24 12:43:12 +01001551LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
1552 LOperand* array = UseRegisterAtStart(instr->value());
1553 return DefineAsRegister(new LPixelArrayLength(array));
1554}
1555
1556
Steve Block9fac8402011-05-12 15:51:54 +01001557LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1558 LOperand* array = UseRegisterAtStart(instr->value());
1559 return DefineAsRegister(new LFixedArrayLength(array));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001560}
1561
1562
1563LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1564 LOperand* object = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001565 LValueOf* result = new LValueOf(object, TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001566 return AssignEnvironment(DefineSameAsFirst(result));
1567}
1568
1569
1570LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1571 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
Ben Murdoch086aeea2011-05-13 15:57:08 +01001572 UseRegister(instr->length())));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001573}
1574
1575
Steve Block1e0659c2011-05-24 12:43:12 +01001576LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1577 // The control instruction marking the end of a block that completed
1578 // abruptly (e.g., threw an exception). There is nothing specific to do.
1579 return NULL;
1580}
1581
1582
Ben Murdochb0fe1622011-05-05 13:52:32 +01001583LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1584 LOperand* value = UseFixed(instr->value(), r0);
1585 return MarkAsCall(new LThrow(value), instr);
1586}
1587
1588
1589LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1590 Representation from = instr->from();
1591 Representation to = instr->to();
1592 if (from.IsTagged()) {
1593 if (to.IsDouble()) {
1594 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001595 LNumberUntagD* res = new LNumberUntagD(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001596 return AssignEnvironment(DefineAsRegister(res));
1597 } else {
1598 ASSERT(to.IsInteger32());
1599 LOperand* value = UseRegister(instr->value());
1600 bool needs_check = !instr->value()->type().IsSmi();
1601 LInstruction* res = NULL;
1602 if (needs_check) {
1603 res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1)));
1604 } else {
1605 res = DefineSameAsFirst(new LSmiUntag(value, needs_check));
1606 }
1607 if (needs_check) {
1608 res = AssignEnvironment(res);
1609 }
1610 return res;
1611 }
1612 } else if (from.IsDouble()) {
1613 if (to.IsTagged()) {
1614 LOperand* value = UseRegister(instr->value());
1615 LOperand* temp1 = TempRegister();
1616 LOperand* temp2 = TempRegister();
1617
1618 // Make sure that the temp and result_temp registers are
1619 // different.
1620 LUnallocated* result_temp = TempRegister();
Steve Block1e0659c2011-05-24 12:43:12 +01001621 LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001622 Define(result, result_temp);
1623 return AssignPointerMap(result);
1624 } else {
1625 ASSERT(to.IsInteger32());
1626 LOperand* value = UseRegister(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001627 LDoubleToI* res = new LDoubleToI(value, TempRegister());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001628 return AssignEnvironment(DefineAsRegister(res));
1629 }
1630 } else if (from.IsInteger32()) {
1631 if (to.IsTagged()) {
1632 HValue* val = instr->value();
1633 LOperand* value = UseRegister(val);
1634 if (val->HasRange() && val->range()->IsInSmiRange()) {
1635 return DefineSameAsFirst(new LSmiTag(value));
1636 } else {
Steve Block1e0659c2011-05-24 12:43:12 +01001637 LNumberTagI* result = new LNumberTagI(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001638 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1639 }
1640 } else {
1641 ASSERT(to.IsDouble());
1642 LOperand* value = Use(instr->value());
1643 return DefineAsRegister(new LInteger32ToDouble(value));
1644 }
1645 }
1646 UNREACHABLE();
1647 return NULL;
1648}
1649
1650
1651LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1652 LOperand* value = UseRegisterAtStart(instr->value());
1653 return AssignEnvironment(new LCheckSmi(value, eq));
1654}
1655
1656
1657LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1658 LOperand* value = UseRegisterAtStart(instr->value());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001659 LInstruction* result = new LCheckInstanceType(value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001660 return AssignEnvironment(result);
1661}
1662
1663
1664LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
Steve Block9fac8402011-05-12 15:51:54 +01001665 LOperand* temp1 = TempRegister();
1666 LOperand* temp2 = TempRegister();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001667 LInstruction* result = new LCheckPrototypeMaps(temp1, temp2);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001668 return AssignEnvironment(result);
1669}
1670
1671
1672LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1673 LOperand* value = UseRegisterAtStart(instr->value());
1674 return AssignEnvironment(new LCheckSmi(value, ne));
1675}
1676
1677
1678LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1679 LOperand* value = UseRegisterAtStart(instr->value());
1680 return AssignEnvironment(new LCheckFunction(value));
1681}
1682
1683
1684LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1685 LOperand* value = UseRegisterAtStart(instr->value());
1686 LInstruction* result = new LCheckMap(value);
1687 return AssignEnvironment(result);
1688}
1689
1690
1691LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1692 return new LReturn(UseFixed(instr->value(), r0));
1693}
1694
1695
1696LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1697 Representation r = instr->representation();
1698 if (r.IsInteger32()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001699 return DefineAsRegister(new LConstantI);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001700 } else if (r.IsDouble()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001701 return DefineAsRegister(new LConstantD);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001702 } else if (r.IsTagged()) {
Steve Block1e0659c2011-05-24 12:43:12 +01001703 return DefineAsRegister(new LConstantT);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001704 } else {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001705 UNREACHABLE();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001706 return NULL;
1707 }
1708}
1709
1710
1711LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001712 LLoadGlobal* result = new LLoadGlobal();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001713 return instr->check_hole_value()
1714 ? AssignEnvironment(DefineAsRegister(result))
1715 : DefineAsRegister(result);
1716}
1717
1718
1719LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001720 if (instr->check_hole_value()) {
1721 LOperand* temp = TempRegister();
1722 LOperand* value = UseRegister(instr->value());
1723 return AssignEnvironment(new LStoreGlobal(value, temp));
1724 } else {
1725 LOperand* value = UseRegisterAtStart(instr->value());
1726 return new LStoreGlobal(value, NULL);
1727 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001728}
1729
1730
Ben Murdochb8e0da22011-05-16 14:20:40 +01001731LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001732 LOperand* context = UseRegisterAtStart(instr->value());
1733 return DefineAsRegister(new LLoadContextSlot(context));
1734}
1735
1736
1737LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001738 LOperand* context;
Steve Block1e0659c2011-05-24 12:43:12 +01001739 LOperand* value;
1740 if (instr->NeedsWriteBarrier()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001741 context = UseTempRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001742 value = UseTempRegister(instr->value());
1743 } else {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001744 context = UseRegister(instr->context());
Steve Block1e0659c2011-05-24 12:43:12 +01001745 value = UseRegister(instr->value());
1746 }
1747 return new LStoreContextSlot(context, value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001748}
1749
1750
Ben Murdochb0fe1622011-05-05 13:52:32 +01001751LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1752 return DefineAsRegister(
1753 new LLoadNamedField(UseRegisterAtStart(instr->object())));
1754}
1755
1756
1757LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1758 LOperand* object = UseFixed(instr->object(), r0);
1759 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0);
1760 return MarkAsCall(result, instr);
1761}
1762
1763
Steve Block9fac8402011-05-12 15:51:54 +01001764LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1765 HLoadFunctionPrototype* instr) {
1766 return AssignEnvironment(DefineAsRegister(
1767 new LLoadFunctionPrototype(UseRegister(instr->function()))));
1768}
1769
1770
Ben Murdochb0fe1622011-05-05 13:52:32 +01001771LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1772 LOperand* input = UseRegisterAtStart(instr->value());
Steve Block1e0659c2011-05-24 12:43:12 +01001773 return DefineAsRegister(new LLoadElements(input));
1774}
1775
1776
1777LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
1778 HLoadPixelArrayExternalPointer* instr) {
1779 LOperand* input = UseRegisterAtStart(instr->value());
1780 return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001781}
1782
1783
1784LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1785 HLoadKeyedFastElement* instr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001786 ASSERT(instr->representation().IsTagged());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001787 ASSERT(instr->key()->representation().IsInteger32());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001788 LOperand* obj = UseRegisterAtStart(instr->object());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001789 LOperand* key = UseRegisterAtStart(instr->key());
Steve Block1e0659c2011-05-24 12:43:12 +01001790 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001791 return AssignEnvironment(DefineSameAsFirst(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001792}
1793
1794
Steve Block1e0659c2011-05-24 12:43:12 +01001795LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
1796 HLoadPixelArrayElement* instr) {
1797 ASSERT(instr->representation().IsInteger32());
1798 ASSERT(instr->key()->representation().IsInteger32());
1799 LOperand* external_pointer =
1800 UseRegisterAtStart(instr->external_pointer());
1801 LOperand* key = UseRegisterAtStart(instr->key());
1802 LLoadPixelArrayElement* result =
1803 new LLoadPixelArrayElement(external_pointer, key);
1804 return DefineAsRegister(result);
1805}
1806
1807
Ben Murdochb0fe1622011-05-05 13:52:32 +01001808LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1809 LOperand* object = UseFixed(instr->object(), r1);
1810 LOperand* key = UseFixed(instr->key(), r0);
1811
1812 LInstruction* result =
1813 DefineFixed(new LLoadKeyedGeneric(object, key), r0);
1814 return MarkAsCall(result, instr);
1815}
1816
1817
1818LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1819 HStoreKeyedFastElement* instr) {
1820 bool needs_write_barrier = instr->NeedsWriteBarrier();
1821 ASSERT(instr->value()->representation().IsTagged());
1822 ASSERT(instr->object()->representation().IsTagged());
1823 ASSERT(instr->key()->representation().IsInteger32());
1824
1825 LOperand* obj = UseTempRegister(instr->object());
1826 LOperand* val = needs_write_barrier
1827 ? UseTempRegister(instr->value())
1828 : UseRegisterAtStart(instr->value());
1829 LOperand* key = needs_write_barrier
1830 ? UseTempRegister(instr->key())
1831 : UseRegisterOrConstantAtStart(instr->key());
1832
1833 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1834}
1835
1836
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001837LInstruction* LChunkBuilder::DoStorePixelArrayElement(
1838 HStorePixelArrayElement* instr) {
1839 Abort("DoStorePixelArrayElement not implemented");
1840 return NULL;
1841}
1842
1843
Ben Murdochb0fe1622011-05-05 13:52:32 +01001844LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1845 LOperand* obj = UseFixed(instr->object(), r2);
1846 LOperand* key = UseFixed(instr->key(), r1);
1847 LOperand* val = UseFixed(instr->value(), r0);
1848
1849 ASSERT(instr->object()->representation().IsTagged());
1850 ASSERT(instr->key()->representation().IsTagged());
1851 ASSERT(instr->value()->representation().IsTagged());
1852
1853 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
1854}
1855
1856
1857LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
Ben Murdoch086aeea2011-05-13 15:57:08 +01001858 bool needs_write_barrier = instr->NeedsWriteBarrier();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001859
1860 LOperand* obj = needs_write_barrier
1861 ? UseTempRegister(instr->object())
1862 : UseRegisterAtStart(instr->object());
1863
1864 LOperand* val = needs_write_barrier
1865 ? UseTempRegister(instr->value())
1866 : UseRegister(instr->value());
1867
Ben Murdochb8e0da22011-05-16 14:20:40 +01001868 return new LStoreNamedField(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001869}
1870
1871
1872LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1873 LOperand* obj = UseFixed(instr->object(), r1);
1874 LOperand* val = UseFixed(instr->value(), r0);
1875
Ben Murdochb8e0da22011-05-16 14:20:40 +01001876 LInstruction* result = new LStoreNamedGeneric(obj, val);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001877 return MarkAsCall(result, instr);
1878}
1879
1880
Steve Block1e0659c2011-05-24 12:43:12 +01001881LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1882 LOperand* string = UseRegister(instr->string());
1883 LOperand* index = UseRegisterOrConstant(instr->index());
1884 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
1885 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1886}
1887
1888
1889LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1890 LOperand* string = UseRegisterAtStart(instr->value());
1891 return DefineAsRegister(new LStringLength(string));
1892}
1893
1894
Ben Murdochb0fe1622011-05-05 13:52:32 +01001895LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1896 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr);
1897}
1898
1899
1900LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1901 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr);
1902}
1903
1904
1905LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1906 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr);
1907}
1908
1909
1910LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1911 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr);
1912}
1913
1914
1915LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001916 LOperand* object = UseFixed(instr->object(), r0);
1917 LOperand* key = UseFixed(instr->key(), r1);
1918 LDeleteProperty* result = new LDeleteProperty(object, key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001919 return MarkAsCall(DefineFixed(result, r0), instr);
1920}
1921
1922
1923LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1924 allocator_->MarkAsOsrEntry();
1925 current_block_->last_environment()->set_ast_id(instr->ast_id());
1926 return AssignEnvironment(new LOsrEntry);
1927}
1928
1929
1930LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1931 int spill_index = chunk()->GetParameterStackSlot(instr->index());
1932 return DefineAsSpilled(new LParameter, spill_index);
1933}
1934
1935
1936LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
1937 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
1938 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
1939}
1940
1941
1942LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1943 argument_count_ -= instr->argument_count();
1944 return MarkAsCall(DefineFixed(new LCallStub, r0), instr);
1945}
1946
1947
1948LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001949 // There are no real uses of the arguments object.
1950 // arguments.length and element access are supported directly on
1951 // stack arguments, and any real arguments object use causes a bailout.
1952 // So this value is never used.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001953 return NULL;
1954}
1955
1956
1957LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
1958 LOperand* arguments = UseRegister(instr->arguments());
1959 LOperand* length = UseTempRegister(instr->length());
Ben Murdoch086aeea2011-05-13 15:57:08 +01001960 LOperand* index = UseRegister(instr->index());
Steve Block1e0659c2011-05-24 12:43:12 +01001961 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
1962 return AssignEnvironment(DefineAsRegister(result));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001963}
1964
1965
1966LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
Steve Block1e0659c2011-05-24 12:43:12 +01001967 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
Ben Murdochb0fe1622011-05-05 13:52:32 +01001968 return MarkAsCall(DefineFixed(result, r0), instr);
1969}
1970
1971
1972LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
1973 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
1974}
1975
Steve Block1e0659c2011-05-24 12:43:12 +01001976
1977LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
1978 return DefineAsRegister(new LIsConstructCall());
1979}
1980
1981
Ben Murdochb0fe1622011-05-05 13:52:32 +01001982LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1983 HEnvironment* env = current_block_->last_environment();
1984 ASSERT(env != NULL);
1985
1986 env->set_ast_id(instr->ast_id());
1987
1988 env->Drop(instr->pop_count());
1989 for (int i = 0; i < instr->values()->length(); ++i) {
1990 HValue* value = instr->values()->at(i);
1991 if (instr->HasAssignedIndexAt(i)) {
1992 env->Bind(instr->GetAssignedIndexAt(i), value);
1993 } else {
1994 env->Push(value);
1995 }
1996 }
1997
Steve Block9fac8402011-05-12 15:51:54 +01001998 ASSERT(env->length() == instr->environment_length());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001999
2000 // If there is an instruction pending deoptimization environment create a
2001 // lazy bailout instruction to capture the environment.
2002 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2003 LInstruction* result = new LLazyBailout;
2004 result = AssignEnvironment(result);
Steve Block1e0659c2011-05-24 12:43:12 +01002005 instruction_pending_deoptimization_environment_->
Ben Murdochb0fe1622011-05-05 13:52:32 +01002006 set_deoptimization_environment(result->environment());
2007 ClearInstructionPendingDeoptimizationEnvironment();
2008 return result;
2009 }
2010
2011 return NULL;
2012}
2013
2014
2015LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2016 return MarkAsCall(new LStackCheck, instr);
2017}
2018
2019
2020LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2021 HEnvironment* outer = current_block_->last_environment();
2022 HConstant* undefined = graph()->GetConstantUndefined();
2023 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2024 instr->function(),
2025 false,
2026 undefined);
2027 current_block_->UpdateEnvironment(inner);
2028 chunk_->AddInlinedClosure(instr->closure());
2029 return NULL;
2030}
2031
2032
2033LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2034 HEnvironment* outer = current_block_->last_environment()->outer();
2035 current_block_->UpdateEnvironment(outer);
2036 return NULL;
2037}
2038
2039
Ben Murdochb0fe1622011-05-05 13:52:32 +01002040} } // namespace v8::internal