blob: e78cee48379c04e9e972b597b527d4c98bd60e70 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000028#include "v8.h"
29
30#if defined(V8_TARGET_ARCH_X64)
31
ricow@chromium.org83aa5492011-02-07 12:42:56 +000032#include "lithium-allocator-inl.h"
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000033#include "x64/lithium-x64.h"
34#include "x64/lithium-codegen-x64.h"
35
36namespace v8 {
37namespace internal {
38
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000039#define DEFINE_COMPILE(type) \
40 void L##type::CompileToNative(LCodeGen* generator) { \
41 generator->Do##type(this); \
42 }
43LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
44#undef DEFINE_COMPILE
45
46LOsrEntry::LOsrEntry() {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000047 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000048 register_spills_[i] = NULL;
49 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000050 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000051 double_register_spills_[i] = NULL;
52 }
53}
54
55
56void LOsrEntry::MarkSpilledRegister(int allocation_index,
57 LOperand* spill_operand) {
58 ASSERT(spill_operand->IsStackSlot());
59 ASSERT(register_spills_[allocation_index] == NULL);
60 register_spills_[allocation_index] = spill_operand;
61}
62
63
64void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
65 LOperand* spill_operand) {
66 ASSERT(spill_operand->IsDoubleStackSlot());
67 ASSERT(double_register_spills_[allocation_index] == NULL);
68 double_register_spills_[allocation_index] = spill_operand;
69}
70
71
ricow@chromium.org83aa5492011-02-07 12:42:56 +000072#ifdef DEBUG
73void LInstruction::VerifyCall() {
danno@chromium.org160a7b02011-04-18 15:51:38 +000074 // Call instructions can use only fixed registers as temporaries and
75 // outputs because all registers are blocked by the calling convention.
76 // Inputs operands must use a fixed register or use-at-start policy or
77 // a non-register policy.
ricow@chromium.org83aa5492011-02-07 12:42:56 +000078 ASSERT(Output() == NULL ||
79 LUnallocated::cast(Output())->HasFixedPolicy() ||
80 !LUnallocated::cast(Output())->HasRegisterPolicy());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000081 for (UseIterator it(this); !it.Done(); it.Advance()) {
82 LUnallocated* operand = LUnallocated::cast(it.Current());
danno@chromium.org160a7b02011-04-18 15:51:38 +000083 ASSERT(operand->HasFixedPolicy() ||
84 operand->IsUsedAtStart());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000085 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000086 for (TempIterator it(this); !it.Done(); it.Advance()) {
87 LUnallocated* operand = LUnallocated::cast(it.Current());
danno@chromium.org160a7b02011-04-18 15:51:38 +000088 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000089 }
90}
91#endif
92
93
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000094void LInstruction::PrintTo(StringStream* stream) {
95 stream->Add("%s ", this->Mnemonic());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000096
97 PrintOutputOperandTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000098
99 PrintDataTo(stream);
100
101 if (HasEnvironment()) {
102 stream->Add(" ");
103 environment()->PrintTo(stream);
104 }
105
106 if (HasPointerMap()) {
107 stream->Add(" ");
108 pointer_map()->PrintTo(stream);
109 }
110}
111
112
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000113void LInstruction::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000114 stream->Add("= ");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000115 for (int i = 0; i < InputCount(); i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000116 if (i > 0) stream->Add(" ");
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000117 if (InputAt(i) == NULL) {
118 stream->Add("NULL");
119 } else {
120 InputAt(i)->PrintTo(stream);
121 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000122 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000123}
124
125
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000126void LInstruction::PrintOutputOperandTo(StringStream* stream) {
127 if (HasResult()) result()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000128}
129
130
131void LLabel::PrintDataTo(StringStream* stream) {
132 LGap::PrintDataTo(stream);
133 LLabel* rep = replacement();
134 if (rep != NULL) {
135 stream->Add(" Dead block replaced with B%d", rep->block_id());
136 }
137}
138
139
140bool LGap::IsRedundant() const {
141 for (int i = 0; i < 4; i++) {
142 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
143 return false;
144 }
145 }
146
147 return true;
148}
149
150
151void LGap::PrintDataTo(StringStream* stream) {
152 for (int i = 0; i < 4; i++) {
153 stream->Add("(");
154 if (parallel_moves_[i] != NULL) {
155 parallel_moves_[i]->PrintDataTo(stream);
156 }
157 stream->Add(") ");
158 }
159}
160
161
162const char* LArithmeticD::Mnemonic() const {
163 switch (op()) {
164 case Token::ADD: return "add-d";
165 case Token::SUB: return "sub-d";
166 case Token::MUL: return "mul-d";
167 case Token::DIV: return "div-d";
168 case Token::MOD: return "mod-d";
169 default:
170 UNREACHABLE();
171 return NULL;
172 }
173}
174
175
176const char* LArithmeticT::Mnemonic() const {
177 switch (op()) {
178 case Token::ADD: return "add-t";
179 case Token::SUB: return "sub-t";
180 case Token::MUL: return "mul-t";
181 case Token::MOD: return "mod-t";
182 case Token::DIV: return "div-t";
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000183 case Token::BIT_AND: return "bit-and-t";
184 case Token::BIT_OR: return "bit-or-t";
185 case Token::BIT_XOR: return "bit-xor-t";
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000186 case Token::ROR: return "ror-t";
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000187 case Token::SHL: return "sal-t";
188 case Token::SAR: return "sar-t";
189 case Token::SHR: return "shr-t";
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000190 default:
191 UNREACHABLE();
192 return NULL;
193 }
194}
195
196
197void LGoto::PrintDataTo(StringStream* stream) {
198 stream->Add("B%d", block_id());
199}
200
201
202void LBranch::PrintDataTo(StringStream* stream) {
203 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000204 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000205}
206
207
208void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
209 stream->Add("if ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000210 left()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000211 stream->Add(" %s ", Token::String(op()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000212 right()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000213 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
214}
215
216
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000217void LIsNilAndBranch::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000218 stream->Add("if ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000219 value()->PrintTo(stream);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000220 stream->Add(kind() == kStrictEquality ? " === " : " == ");
221 stream->Add(nil() == kNullValue ? "null" : "undefined");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000222 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
223}
224
225
226void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
227 stream->Add("if is_object(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000228 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000229 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
230}
231
232
erikcorry0ad885c2011-11-21 13:51:57 +0000233void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
234 stream->Add("if is_string(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000235 value()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000236 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
237}
238
239
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000240void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
241 stream->Add("if is_smi(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000242 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000243 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
244}
245
246
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000247void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
248 stream->Add("if is_undetectable(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000249 value()->PrintTo(stream);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000250 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
251}
252
253
erikcorry0ad885c2011-11-21 13:51:57 +0000254void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
255 stream->Add("if string_compare(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000256 left()->PrintTo(stream);
257 right()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000258 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
259}
260
261
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000262void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
263 stream->Add("if has_instance_type(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000264 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000265 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
266}
267
268
269void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
270 stream->Add("if has_cached_array_index(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000271 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000272 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
273}
274
275
276void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
277 stream->Add("if class_of_test(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000278 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000279 stream->Add(", \"%o\") then B%d else B%d",
280 *hydrogen()->class_name(),
281 true_block_id(),
282 false_block_id());
283}
284
285
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000286void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
287 stream->Add("if typeof ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000288 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000289 stream->Add(" == \"%s\" then B%d else B%d",
290 *hydrogen()->type_literal()->ToCString(),
291 true_block_id(), false_block_id());
292}
293
294
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000295void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
296 stream->Add(" = ");
297 base_object()->PrintTo(stream);
298 stream->Add(" + %d", offset());
299}
300
301
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000302void LCallConstantFunction::PrintDataTo(StringStream* stream) {
303 stream->Add("#%d / ", arity());
304}
305
306
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000307void LLoadContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000308 context()->PrintTo(stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000309 stream->Add("[%d]", slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000310}
311
312
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000313void LStoreContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000314 context()->PrintTo(stream);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000315 stream->Add("[%d] <- ", slot_index());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000316 value()->PrintTo(stream);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000317}
318
319
danno@chromium.org160a7b02011-04-18 15:51:38 +0000320void LInvokeFunction::PrintDataTo(StringStream* stream) {
321 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000322 function()->PrintTo(stream);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000323 stream->Add(" #%d / ", arity());
324}
325
326
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000327void LCallKeyed::PrintDataTo(StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000328 stream->Add("[rcx] #%d / ", arity());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000329}
330
331
332void LCallNamed::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000333 SmartArrayPointer<char> name_string = name()->ToCString();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000334 stream->Add("%s #%d / ", *name_string, arity());
335}
336
337
338void LCallGlobal::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000339 SmartArrayPointer<char> name_string = name()->ToCString();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000340 stream->Add("%s #%d / ", *name_string, arity());
341}
342
343
344void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
345 stream->Add("#%d / ", arity());
346}
347
348
349void LCallNew::PrintDataTo(StringStream* stream) {
350 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000351 constructor()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000352 stream->Add(" #%d / ", arity());
353}
354
355
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000356void LCallNewArray::PrintDataTo(StringStream* stream) {
357 stream->Add("= ");
358 constructor()->PrintTo(stream);
359 stream->Add(" #%d / ", arity());
360 ASSERT(hydrogen()->property_cell()->value()->IsSmi());
361 ElementsKind kind = static_cast<ElementsKind>(
362 Smi::cast(hydrogen()->property_cell()->value())->value());
363 stream->Add(" (%s) ", ElementsKindToString(kind));
364}
365
366
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000367void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
368 arguments()->PrintTo(stream);
369
370 stream->Add(" length ");
371 length()->PrintTo(stream);
372
373 stream->Add(" index ");
374 index()->PrintTo(stream);
375}
376
377
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000378int LPlatformChunk::GetNextSpillIndex(bool is_double) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000379 return spill_slot_count_++;
380}
381
382
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000383LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000384 // All stack slots are Double stack slots on x64.
385 // Alternatively, at some point, start using half-size
386 // stack slots for int32 values.
387 int index = GetNextSpillIndex(is_double);
388 if (is_double) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000389 return LDoubleStackSlot::Create(index, zone());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000390 } else {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000391 return LStackSlot::Create(index, zone());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000392 }
393}
394
395
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000396void LStoreNamedField::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000397 object()->PrintTo(stream);
398 stream->Add(".");
399 stream->Add(*String::cast(*name())->ToCString());
400 stream->Add(" <- ");
401 value()->PrintTo(stream);
402}
403
404
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000405void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
406 object()->PrintTo(stream);
407 stream->Add(".");
408 stream->Add(*String::cast(*name())->ToCString());
409 stream->Add(" <- ");
410 value()->PrintTo(stream);
411}
412
413
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000414void LLoadKeyed::PrintDataTo(StringStream* stream) {
415 elements()->PrintTo(stream);
416 stream->Add("[");
417 key()->PrintTo(stream);
418 if (hydrogen()->IsDehoisted()) {
419 stream->Add(" + %d]", additional_index());
420 } else {
421 stream->Add("]");
422 }
423}
424
425
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000426void LStoreKeyed::PrintDataTo(StringStream* stream) {
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000427 elements()->PrintTo(stream);
428 stream->Add("[");
429 key()->PrintTo(stream);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000430 if (hydrogen()->IsDehoisted()) {
431 stream->Add(" + %d] <-", additional_index());
432 } else {
433 stream->Add("] <- ");
434 }
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000435 value()->PrintTo(stream);
436}
437
438
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000439void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000440 object()->PrintTo(stream);
441 stream->Add("[");
442 key()->PrintTo(stream);
443 stream->Add("] <- ");
444 value()->PrintTo(stream);
445}
446
447
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000448void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
449 object()->PrintTo(stream);
450 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
451}
452
453
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000454LPlatformChunk* LChunkBuilder::Build() {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000455 ASSERT(is_unused());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000456 chunk_ = new(zone()) LPlatformChunk(info(), graph());
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000457 HPhase phase("L_Building chunk", chunk_);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000458 status_ = BUILDING;
459 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
460 for (int i = 0; i < blocks->length(); i++) {
461 HBasicBlock* next = NULL;
462 if (i < blocks->length() - 1) next = blocks->at(i + 1);
463 DoBasicBlock(blocks->at(i), next);
464 if (is_aborted()) return NULL;
465 }
466 status_ = DONE;
467 return chunk_;
468}
469
470
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000471void LCodeGen::Abort(const char* reason) {
472 info()->set_bailout_reason(reason);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000473 status_ = ABORTED;
474}
475
476
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000477LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000478 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
479 Register::ToAllocationIndex(reg));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000480}
481
482
483LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000484 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
485 XMMRegister::ToAllocationIndex(reg));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000486}
487
488
489LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
490 return Use(value, ToUnallocated(fixed_register));
491}
492
493
494LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
495 return Use(value, ToUnallocated(reg));
496}
497
498
499LOperand* LChunkBuilder::UseRegister(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000500 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000501}
502
503
504LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
505 return Use(value,
ulan@chromium.org812308e2012-02-29 15:58:45 +0000506 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000507 LUnallocated::USED_AT_START));
508}
509
510
511LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000512 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000513}
514
515
516LOperand* LChunkBuilder::Use(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000517 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000518}
519
520
521LOperand* LChunkBuilder::UseAtStart(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000522 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000523 LUnallocated::USED_AT_START));
524}
525
526
527LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
528 return value->IsConstant()
529 ? chunk_->DefineConstantOperand(HConstant::cast(value))
530 : Use(value);
531}
532
533
534LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
535 return value->IsConstant()
536 ? chunk_->DefineConstantOperand(HConstant::cast(value))
537 : UseAtStart(value);
538}
539
540
541LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
542 return value->IsConstant()
543 ? chunk_->DefineConstantOperand(HConstant::cast(value))
544 : UseRegister(value);
545}
546
547
548LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
549 return value->IsConstant()
550 ? chunk_->DefineConstantOperand(HConstant::cast(value))
551 : UseRegisterAtStart(value);
552}
553
554
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000555LOperand* LChunkBuilder::UseAny(HValue* value) {
556 return value->IsConstant()
557 ? chunk_->DefineConstantOperand(HConstant::cast(value))
ulan@chromium.org812308e2012-02-29 15:58:45 +0000558 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000559}
560
561
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000562LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
563 if (value->EmitAtUses()) {
564 HInstruction* instr = HInstruction::cast(value);
565 VisitInstruction(instr);
566 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000567 operand->set_virtual_register(value->id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000568 return operand;
569}
570
571
572template<int I, int T>
573LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
574 LUnallocated* result) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000575 result->set_virtual_register(current_instruction_->id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000576 instr->set_result(result);
577 return instr;
578}
579
580
581template<int I, int T>
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000582LInstruction* LChunkBuilder::DefineAsRegister(
583 LTemplateInstruction<1, I, T>* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000584 return Define(instr,
585 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000586}
587
588
589template<int I, int T>
590LInstruction* LChunkBuilder::DefineAsSpilled(
591 LTemplateInstruction<1, I, T>* instr,
592 int index) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000593 return Define(instr,
594 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000595}
596
597
598template<int I, int T>
599LInstruction* LChunkBuilder::DefineSameAsFirst(
600 LTemplateInstruction<1, I, T>* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000601 return Define(instr,
602 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000603}
604
605
606template<int I, int T>
607LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
608 Register reg) {
609 return Define(instr, ToUnallocated(reg));
610}
611
612
613template<int I, int T>
614LInstruction* LChunkBuilder::DefineFixedDouble(
615 LTemplateInstruction<1, I, T>* instr,
616 XMMRegister reg) {
617 return Define(instr, ToUnallocated(reg));
618}
619
620
621LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
622 HEnvironment* hydrogen_env = current_block_->last_environment();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000623 int argument_index_accumulator = 0;
624 instr->set_environment(CreateEnvironment(hydrogen_env,
625 &argument_index_accumulator));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000626 return instr;
627}
628
629
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000630LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
631 HInstruction* hinstr,
632 CanDeoptimize can_deoptimize) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000633 info()->MarkAsNonDeferredCalling();
634
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000635#ifdef DEBUG
636 instr->VerifyCall();
637#endif
638 instr->MarkAsCall();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000639 instr = AssignPointerMap(instr);
640
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000641 if (hinstr->HasObservableSideEffects()) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000642 ASSERT(hinstr->next()->IsSimulate());
643 HSimulate* sim = HSimulate::cast(hinstr->next());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000644 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000645 ASSERT(pending_deoptimization_ast_id_.IsNone());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000646 instruction_pending_deoptimization_environment_ = instr;
647 pending_deoptimization_ast_id_ = sim->ast_id();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000648 }
649
650 // If instruction does not have side-effects lazy deoptimization
651 // after the call will try to deoptimize to the point before the call.
652 // Thus we still need to attach environment to this call even if
653 // call sequence can not deoptimize eagerly.
654 bool needs_environment =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000655 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
656 !hinstr->HasObservableSideEffects();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000657 if (needs_environment && !instr->HasEnvironment()) {
658 instr = AssignEnvironment(instr);
659 }
660
661 return instr;
662}
663
664
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000665LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
666 ASSERT(!instr->HasPointerMap());
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000667 instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000668 return instr;
669}
670
671
672LUnallocated* LChunkBuilder::TempRegister() {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000673 LUnallocated* operand =
674 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000675 int vreg = allocator_->GetVirtualRegister();
676 if (!allocator_->AllocationOk()) {
677 Abort("Out of virtual registers while trying to allocate temp register.");
678 return NULL;
679 }
680 operand->set_virtual_register(vreg);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000681 return operand;
682}
683
684
685LOperand* LChunkBuilder::FixedTemp(Register reg) {
686 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000687 ASSERT(operand->HasFixedPolicy());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000688 return operand;
689}
690
691
692LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
693 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000694 ASSERT(operand->HasFixedPolicy());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000695 return operand;
696}
697
698
699LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000700 return new(zone()) LLabel(instr->block());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000701}
702
703
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000704LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
705 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
706}
707
708
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000709LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000710 return AssignEnvironment(new(zone()) LDeoptimize);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000711}
712
713
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000714LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000715 return AssignEnvironment(new(zone()) LDeoptimize);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000716}
717
718
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000719LInstruction* LChunkBuilder::DoShift(Token::Value op,
720 HBitwiseBinaryOperation* instr) {
721 if (instr->representation().IsTagged()) {
722 ASSERT(instr->left()->representation().IsTagged());
723 ASSERT(instr->right()->representation().IsTagged());
724
725 LOperand* left = UseFixed(instr->left(), rdx);
726 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +0000727 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000728 return MarkAsCall(DefineFixed(result, rax), instr);
729 }
730
731 ASSERT(instr->representation().IsInteger32());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000732 ASSERT(instr->left()->representation().IsInteger32());
733 ASSERT(instr->right()->representation().IsInteger32());
734 LOperand* left = UseRegisterAtStart(instr->left());
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000735
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000736 HValue* right_value = instr->right();
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000737 LOperand* right = NULL;
738 int constant_value = 0;
739 if (right_value->IsConstant()) {
740 HConstant* constant = HConstant::cast(right_value);
741 right = chunk_->DefineConstantOperand(constant);
742 constant_value = constant->Integer32Value() & 0x1f;
743 } else {
744 right = UseFixed(right_value, rcx);
745 }
746
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000747 // Shift operations can only deoptimize if we do a logical shift by 0 and
748 // the result cannot be truncated to int32.
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000749 bool does_deopt = false;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000750 if (op == Token::SHR && constant_value == 0) {
751 if (FLAG_opt_safe_uint32_operations) {
752 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
753 } else {
754 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
755 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
756 does_deopt = true;
757 break;
758 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000759 }
760 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000761 }
762
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000763 LInstruction* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +0000764 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000765 return does_deopt ? AssignEnvironment(result) : result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000766}
767
768
769LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
770 HArithmeticBinaryOperation* instr) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000771 ASSERT(instr->representation().IsDouble());
772 ASSERT(instr->left()->representation().IsDouble());
773 ASSERT(instr->right()->representation().IsDouble());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000774 ASSERT(op != Token::MOD);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000775 LOperand* left = UseRegisterAtStart(instr->left());
776 LOperand* right = UseRegisterAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +0000777 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000778 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000779}
780
781
782LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
783 HArithmeticBinaryOperation* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000784 ASSERT(op == Token::ADD ||
785 op == Token::DIV ||
786 op == Token::MOD ||
787 op == Token::MUL ||
788 op == Token::SUB);
789 HValue* left = instr->left();
790 HValue* right = instr->right();
791 ASSERT(left->representation().IsTagged());
792 ASSERT(right->representation().IsTagged());
793 LOperand* left_operand = UseFixed(left, rdx);
794 LOperand* right_operand = UseFixed(right, rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +0000795 LArithmeticT* result =
796 new(zone()) LArithmeticT(op, left_operand, right_operand);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000797 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000798}
799
800
801void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
802 ASSERT(is_building());
803 current_block_ = block;
804 next_block_ = next_block;
805 if (block->IsStartBlock()) {
806 block->UpdateEnvironment(graph_->start_environment());
807 argument_count_ = 0;
808 } else if (block->predecessors()->length() == 1) {
809 // We have a single predecessor => copy environment and outgoing
810 // argument count from the predecessor.
811 ASSERT(block->phis()->length() == 0);
812 HBasicBlock* pred = block->predecessors()->at(0);
813 HEnvironment* last_environment = pred->last_environment();
814 ASSERT(last_environment != NULL);
815 // Only copy the environment, if it is later used again.
816 if (pred->end()->SecondSuccessor() == NULL) {
817 ASSERT(pred->end()->FirstSuccessor() == block);
818 } else {
819 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
820 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
821 last_environment = last_environment->Copy();
822 }
823 }
824 block->UpdateEnvironment(last_environment);
825 ASSERT(pred->argument_count() >= 0);
826 argument_count_ = pred->argument_count();
827 } else {
828 // We are at a state join => process phis.
829 HBasicBlock* pred = block->predecessors()->at(0);
830 // No need to copy the environment, it cannot be used later.
831 HEnvironment* last_environment = pred->last_environment();
832 for (int i = 0; i < block->phis()->length(); ++i) {
833 HPhi* phi = block->phis()->at(i);
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000834 if (phi->merged_index() < last_environment->length()) {
835 last_environment->SetValueAt(phi->merged_index(), phi);
836 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000837 }
838 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000839 if (block->deleted_phis()->at(i) < last_environment->length()) {
840 last_environment->SetValueAt(block->deleted_phis()->at(i),
841 graph_->GetConstantUndefined());
842 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000843 }
844 block->UpdateEnvironment(last_environment);
845 // Pick up the outgoing argument count of one of the predecessors.
846 argument_count_ = pred->argument_count();
847 }
848 HInstruction* current = block->first();
849 int start = chunk_->instructions()->length();
850 while (current != NULL && !is_aborted()) {
851 // Code for constants in registers is generated lazily.
852 if (!current->EmitAtUses()) {
853 VisitInstruction(current);
854 }
855 current = current->next();
856 }
857 int end = chunk_->instructions()->length() - 1;
858 if (end >= start) {
859 block->set_first_instruction_index(start);
860 block->set_last_instruction_index(end);
861 }
862 block->set_argument_count(argument_count_);
863 next_block_ = NULL;
864 current_block_ = NULL;
865}
866
867
868void LChunkBuilder::VisitInstruction(HInstruction* current) {
869 HInstruction* old_current = current_instruction_;
870 current_instruction_ = current;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000871 if (current->has_position()) position_ = current->position();
872 LInstruction* instr = current->CompileToLithium(this);
873
874 if (instr != NULL) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000875#if DEBUG
876 // Make sure that the lithium instruction has either no fixed register
877 // constraints in temps or the result OR no uses that are only used at
878 // start. If this invariant doesn't hold, the register allocator can decide
879 // to insert a split of a range immediately before the instruction due to an
880 // already allocated register needing to be used for the instruction's fixed
881 // register constraint. In this case, The register allocator won't see an
882 // interference between the split child and the use-at-start (it would if
883 // the it was just a plain use), so it is free to move the split child into
884 // the same register that is used for the use-at-start.
885 // See https://code.google.com/p/chromium/issues/detail?id=201590
886 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
887 int fixed = 0;
888 int used_at_start = 0;
889 for (UseIterator it(instr); !it.Done(); it.Advance()) {
890 LUnallocated* operand = LUnallocated::cast(it.Current());
891 if (operand->IsUsedAtStart()) ++used_at_start;
892 }
893 if (instr->Output() != NULL) {
894 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
895 }
896 for (TempIterator it(instr); !it.Done(); it.Advance()) {
897 LUnallocated* operand = LUnallocated::cast(it.Current());
898 if (operand->HasFixedPolicy()) ++fixed;
899 }
900 ASSERT(fixed == 0 || used_at_start == 0);
901 }
902#endif
903
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000904 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
905 instr = AssignPointerMap(instr);
906 }
907 if (FLAG_stress_environments && !instr->HasEnvironment()) {
908 instr = AssignEnvironment(instr);
909 }
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000910 instr->set_hydrogen_value(current);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000911 chunk_->AddInstruction(instr, current_block_);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000912 }
913 current_instruction_ = old_current;
914}
915
916
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000917LEnvironment* LChunkBuilder::CreateEnvironment(
918 HEnvironment* hydrogen_env,
919 int* argument_index_accumulator) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000920 if (hydrogen_env == NULL) return NULL;
921
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000922 LEnvironment* outer =
923 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000924 BailoutId ast_id = hydrogen_env->ast_id();
925 ASSERT(!ast_id.IsNone() ||
ulan@chromium.org967e2702012-02-28 09:49:15 +0000926 hydrogen_env->frame_type() != JS_FUNCTION);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000927 int value_count = hydrogen_env->length();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000928 LEnvironment* result = new(zone()) LEnvironment(
929 hydrogen_env->closure(),
930 hydrogen_env->frame_type(),
931 ast_id,
932 hydrogen_env->parameter_count(),
933 argument_count_,
934 value_count,
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000935 outer,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000936 hydrogen_env->entry(),
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000937 zone());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000938 int argument_index = *argument_index_accumulator;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000939 for (int i = 0; i < value_count; ++i) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000940 if (hydrogen_env->is_special_index(i)) continue;
941
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000942 HValue* value = hydrogen_env->values()->at(i);
943 LOperand* op = NULL;
944 if (value->IsArgumentsObject()) {
945 op = NULL;
946 } else if (value->IsPushArgument()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000947 op = new(zone()) LArgument(argument_index++);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000948 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000949 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000950 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000951 result->AddValue(op,
952 value->representation(),
953 value->CheckFlag(HInstruction::kUint32));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000954 }
955
ulan@chromium.org967e2702012-02-28 09:49:15 +0000956 if (hydrogen_env->frame_type() == JS_FUNCTION) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000957 *argument_index_accumulator = argument_index;
958 }
959
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000960 return result;
961}
962
963
964LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000965 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000966}
967
968
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000969LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000970 HValue* value = instr->value();
971 if (value->EmitAtUses()) {
972 ASSERT(value->IsConstant());
973 ASSERT(!value->representation().IsDouble());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000974 HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000975 ? instr->FirstSuccessor()
976 : instr->SecondSuccessor();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000977 return new(zone()) LGoto(successor->block_id());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000978 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000979
ulan@chromium.org812308e2012-02-29 15:58:45 +0000980 LBranch* result = new(zone()) LBranch(UseRegister(value));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000981 // Tagged values that are not known smis or booleans require a
982 // deoptimization environment.
983 Representation rep = value->representation();
984 HType type = value->type();
985 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
986 return AssignEnvironment(result);
987 }
988 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000989}
990
991
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000992LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000993 ASSERT(instr->value()->representation().IsTagged());
994 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +0000995 return new(zone()) LCmpMapAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000996}
997
998
999LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001000 info()->MarkAsRequiresFrame();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001001 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001002}
1003
1004
1005LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001006 info()->MarkAsRequiresFrame();
danno@chromium.orgb2a1c072012-03-23 15:47:56 +00001007 return DefineAsRegister(new(zone()) LArgumentsElements);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001008}
1009
1010
1011LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001012 LOperand* left = UseFixed(instr->left(), rax);
1013 LOperand* right = UseFixed(instr->right(), rdx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001014 LInstanceOf* result = new(zone()) LInstanceOf(left, right);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001015 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001016}
1017
1018
1019LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1020 HInstanceOfKnownGlobal* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001021 LInstanceOfKnownGlobal* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +00001022 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), rax),
1023 FixedTemp(rdi));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001024 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001025}
1026
1027
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001028LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) {
1029 LOperand* object = UseRegisterAtStart(instr->object());
1030 return DefineAsRegister(new(zone()) LInstanceSize(object));
1031}
1032
1033
yangguo@chromium.org154ff992012-03-13 08:09:54 +00001034LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1035 LOperand* receiver = UseRegister(instr->receiver());
1036 LOperand* function = UseRegisterAtStart(instr->function());
1037 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
1038 return AssignEnvironment(DefineSameAsFirst(result));
1039}
1040
1041
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001042LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001043 LOperand* function = UseFixed(instr->function(), rdi);
1044 LOperand* receiver = UseFixed(instr->receiver(), rax);
1045 LOperand* length = UseFixed(instr->length(), rbx);
1046 LOperand* elements = UseFixed(instr->elements(), rcx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001047 LApplyArguments* result = new(zone()) LApplyArguments(function,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001048 receiver,
1049 length,
1050 elements);
1051 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001052}
1053
1054
1055LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001056 ++argument_count_;
1057 LOperand* argument = UseOrConstant(instr->argument());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001058 return new(zone()) LPushArgument(argument);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001059}
1060
1061
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001062LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1063 HInnerAllocatedObject* inner_object) {
1064 LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
1065 LInnerAllocatedObject* result =
1066 new(zone()) LInnerAllocatedObject(base_object);
1067 return DefineAsRegister(result);
1068}
1069
1070
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001071LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001072 return instr->HasNoUses()
1073 ? NULL
1074 : DefineAsRegister(new(zone()) LThisFunction);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001075}
1076
1077
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001078LInstruction* LChunkBuilder::DoContext(HContext* instr) {
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001079 // If there is a non-return use, the context must be allocated in a register.
1080 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
1081 if (!it.value()->IsReturn()) {
1082 return DefineAsRegister(new(zone()) LContext);
1083 }
1084 }
1085
1086 return NULL;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001087}
1088
1089
1090LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001091 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001092 return DefineAsRegister(new(zone()) LOuterContext(context));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001093}
1094
1095
yangguo@chromium.org56454712012-02-16 15:33:53 +00001096LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001097 return MarkAsCall(new(zone()) LDeclareGlobals, instr);
yangguo@chromium.org56454712012-02-16 15:33:53 +00001098}
1099
1100
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001101LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001102 return DefineAsRegister(new(zone()) LGlobalObject);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001103}
1104
1105
1106LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001107 LOperand* global_object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001108 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001109}
1110
1111
1112LInstruction* LChunkBuilder::DoCallConstantFunction(
1113 HCallConstantFunction* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001114 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001115 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001116}
1117
1118
danno@chromium.org160a7b02011-04-18 15:51:38 +00001119LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1120 LOperand* function = UseFixed(instr->function(), rdi);
1121 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001122 LInvokeFunction* result = new(zone()) LInvokeFunction(function);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001123 return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1124}
1125
1126
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001127LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001128 switch (instr->op()) {
1129 case kMathFloor: return DoMathFloor(instr);
1130 case kMathRound: return DoMathRound(instr);
1131 case kMathAbs: return DoMathAbs(instr);
1132 case kMathLog: return DoMathLog(instr);
1133 case kMathSin: return DoMathSin(instr);
1134 case kMathCos: return DoMathCos(instr);
1135 case kMathTan: return DoMathTan(instr);
1136 case kMathExp: return DoMathExp(instr);
1137 case kMathSqrt: return DoMathSqrt(instr);
1138 case kMathPowHalf: return DoMathPowHalf(instr);
1139 default:
1140 UNREACHABLE();
1141 return NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001142 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001143}
1144
1145
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001146LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1147 LOperand* input = UseRegisterAtStart(instr->value());
1148 LMathFloor* result = new(zone()) LMathFloor(input);
1149 return AssignEnvironment(DefineAsRegister(result));
1150}
1151
1152
1153LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1154 LOperand* input = UseRegisterAtStart(instr->value());
1155 LMathRound* result = new(zone()) LMathRound(input);
1156 return AssignEnvironment(DefineAsRegister(result));
1157}
1158
1159LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1160 LOperand* input = UseRegisterAtStart(instr->value());
1161 LMathAbs* result = new(zone()) LMathAbs(input);
1162 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1163}
1164
1165
1166LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1167 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1168 LMathLog* result = new(zone()) LMathLog(input);
1169 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1170}
1171
1172
1173LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1174 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1175 LMathSin* result = new(zone()) LMathSin(input);
1176 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1177}
1178
1179
1180LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1181 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1182 LMathCos* result = new(zone()) LMathCos(input);
1183 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1184}
1185
1186
1187LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
1188 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1189 LMathTan* result = new(zone()) LMathTan(input);
1190 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1191}
1192
1193
1194LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1195 ASSERT(instr->representation().IsDouble());
1196 ASSERT(instr->value()->representation().IsDouble());
1197 LOperand* value = UseTempRegister(instr->value());
1198 LOperand* temp1 = TempRegister();
1199 LOperand* temp2 = TempRegister();
1200 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1201 return DefineAsRegister(result);
1202}
1203
1204
1205LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1206 LOperand* input = UseRegisterAtStart(instr->value());
1207 LMathSqrt* result = new(zone()) LMathSqrt(input);
1208 return DefineSameAsFirst(result);
1209}
1210
1211
1212LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1213 LOperand* input = UseRegisterAtStart(instr->value());
1214 LMathPowHalf* result = new(zone()) LMathPowHalf(input);
1215 return DefineSameAsFirst(result);
1216}
1217
1218
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001219LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001220 ASSERT(instr->key()->representation().IsTagged());
1221 LOperand* key = UseFixed(instr->key(), rcx);
1222 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001223 LCallKeyed* result = new(zone()) LCallKeyed(key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001224 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001225}
1226
1227
1228LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001229 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001230 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001231}
1232
1233
1234LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001235 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001236 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001237}
1238
1239
1240LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001241 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001242 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001243}
1244
1245
1246LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001247 LOperand* constructor = UseFixed(instr->constructor(), rdi);
1248 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001249 LCallNew* result = new(zone()) LCallNew(constructor);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001250 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001251}
1252
1253
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001254LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1255 ASSERT(FLAG_optimize_constructed_arrays);
1256 LOperand* constructor = UseFixed(instr->constructor(), rdi);
1257 argument_count_ -= instr->argument_count();
1258 LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1259 return MarkAsCall(DefineFixed(result, rax), instr);
1260}
1261
1262
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001263LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
danno@chromium.orgc612e022011-11-10 11:38:15 +00001264 LOperand* function = UseFixed(instr->function(), rdi);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001265 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001266 LCallFunction* result = new(zone()) LCallFunction(function);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001267 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001268}
1269
1270
1271LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001272 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001273 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001274}
1275
1276
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001277LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1278 return DoShift(Token::ROR, instr);
1279}
1280
1281
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001282LInstruction* LChunkBuilder::DoShr(HShr* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001283 return DoShift(Token::SHR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001284}
1285
1286
1287LInstruction* LChunkBuilder::DoSar(HSar* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001288 return DoShift(Token::SAR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001289}
1290
1291
1292LInstruction* LChunkBuilder::DoShl(HShl* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001293 return DoShift(Token::SHL, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001294}
1295
1296
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001297LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1298 if (instr->representation().IsInteger32()) {
1299 ASSERT(instr->left()->representation().IsInteger32());
1300 ASSERT(instr->right()->representation().IsInteger32());
1301
1302 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1303 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001304 return DefineSameAsFirst(new(zone()) LBitI(left, right));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001305 } else {
1306 ASSERT(instr->representation().IsTagged());
1307 ASSERT(instr->left()->representation().IsTagged());
1308 ASSERT(instr->right()->representation().IsTagged());
1309
1310 LOperand* left = UseFixed(instr->left(), rdx);
1311 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001312 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001313 return MarkAsCall(DefineFixed(result, rax), instr);
1314 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001315}
1316
1317
1318LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001319 ASSERT(instr->value()->representation().IsInteger32());
1320 ASSERT(instr->representation().IsInteger32());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +00001321 if (instr->HasNoUses()) return NULL;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001322 LOperand* input = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001323 LBitNotI* result = new(zone()) LBitNotI(input);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001324 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001325}
1326
1327
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001328LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001329 if (instr->representation().IsDouble()) {
1330 return DoArithmeticD(Token::DIV, instr);
1331 } else if (instr->representation().IsInteger32()) {
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001332 if (instr->HasPowerOf2Divisor()) {
1333 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1334 LOperand* value = UseRegisterAtStart(instr->left());
1335 LDivI* div =
1336 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1337 return AssignEnvironment(DefineSameAsFirst(div));
1338 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001339 // The temporary operand is necessary to ensure that right is not allocated
1340 // into rdx.
1341 LOperand* temp = FixedTemp(rdx);
1342 LOperand* dividend = UseFixed(instr->left(), rax);
1343 LOperand* divisor = UseRegister(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001344 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001345 return AssignEnvironment(DefineFixed(result, rax));
1346 } else {
1347 ASSERT(instr->representation().IsTagged());
1348 return DoArithmeticT(Token::DIV, instr);
1349 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001350}
1351
1352
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001353HValue* LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(HValue* dividend) {
1354 // A value with an integer representation does not need to be transformed.
1355 if (dividend->representation().IsInteger32()) {
1356 return dividend;
1357 // A change from an integer32 can be replaced by the integer32 value.
1358 } else if (dividend->IsChange() &&
1359 HChange::cast(dividend)->from().IsInteger32()) {
1360 return HChange::cast(dividend)->value();
1361 }
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +00001362 return NULL;
1363}
1364
1365
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001366HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1367 if (divisor->IsConstant() &&
1368 HConstant::cast(divisor)->HasInteger32Value()) {
1369 HConstant* constant_val = HConstant::cast(divisor);
1370 return constant_val->CopyToRepresentation(Representation::Integer32(),
1371 divisor->block()->zone());
1372 }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001373 // A value with an integer representation does not need to be transformed.
1374 if (divisor->representation().IsInteger32()) {
1375 return divisor;
1376 // A change from an integer32 can be replaced by the integer32 value.
1377 } else if (divisor->IsChange() &&
1378 HChange::cast(divisor)->from().IsInteger32()) {
1379 return HChange::cast(divisor)->value();
1380 }
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001381 return NULL;
1382}
1383
1384
1385LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1386 HValue* right = instr->right();
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001387 if (!right->IsConstant()) {
1388 ASSERT(right->representation().IsInteger32());
1389 // The temporary operand is necessary to ensure that right is not allocated
1390 // into rdx.
1391 LOperand* temp = FixedTemp(rdx);
1392 LOperand* dividend = UseFixed(instr->left(), rax);
1393 LOperand* divisor = UseRegister(instr->right());
1394 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp);
1395 return AssignEnvironment(DefineFixed(flooring_div, rax));
1396 }
1397
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001398 ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value());
1399 LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
1400 int32_t divisor_si = HConstant::cast(right)->Integer32Value();
1401 if (divisor_si == 0) {
1402 LOperand* dividend = UseRegister(instr->left());
1403 return AssignEnvironment(DefineAsRegister(
1404 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
1405 } else if (IsPowerOf2(abs(divisor_si))) {
1406 LOperand* dividend = UseRegisterAtStart(instr->left());
1407 LInstruction* result = DefineAsRegister(
1408 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
1409 return divisor_si < 0 ? AssignEnvironment(result) : result;
1410 } else {
1411 // use two r64
1412 LOperand* dividend = UseRegisterAtStart(instr->left());
1413 LOperand* temp = TempRegister();
1414 LInstruction* result = DefineAsRegister(
1415 new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
1416 return divisor_si < 0 ? AssignEnvironment(result) : result;
1417 }
1418}
1419
1420
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001421LInstruction* LChunkBuilder::DoMod(HMod* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001422 if (instr->representation().IsInteger32()) {
1423 ASSERT(instr->left()->representation().IsInteger32());
1424 ASSERT(instr->right()->representation().IsInteger32());
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001425
1426 LInstruction* result;
1427 if (instr->HasPowerOf2Divisor()) {
1428 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1429 LOperand* value = UseRegisterAtStart(instr->left());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001430 LModI* mod =
1431 new(zone()) LModI(value, UseOrConstant(instr->right()), NULL);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001432 result = DefineSameAsFirst(mod);
1433 } else {
1434 // The temporary operand is necessary to ensure that right is not
1435 // allocated into edx.
1436 LOperand* temp = FixedTemp(rdx);
1437 LOperand* value = UseFixed(instr->left(), rax);
1438 LOperand* divisor = UseRegister(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001439 LModI* mod = new(zone()) LModI(value, divisor, temp);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001440 result = DefineFixed(mod, rdx);
1441 }
1442
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001443 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1444 instr->CheckFlag(HValue::kCanBeDivByZero))
1445 ? AssignEnvironment(result)
1446 : result;
1447 } else if (instr->representation().IsTagged()) {
1448 return DoArithmeticT(Token::MOD, instr);
1449 } else {
1450 ASSERT(instr->representation().IsDouble());
1451 // We call a C function for double modulo. It can't trigger a GC.
1452 // We need to use fixed result register for the call.
1453 // TODO(fschneider): Allow any register as input registers.
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001454 LOperand* left = UseFixedDouble(instr->left(), xmm2);
1455 LOperand* right = UseFixedDouble(instr->right(), xmm1);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001456 LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001457 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1458 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001459}
1460
1461
1462LInstruction* LChunkBuilder::DoMul(HMul* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001463 if (instr->representation().IsInteger32()) {
1464 ASSERT(instr->left()->representation().IsInteger32());
1465 ASSERT(instr->right()->representation().IsInteger32());
1466 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1467 LOperand* right = UseOrConstant(instr->MostConstantOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001468 LMulI* mul = new(zone()) LMulI(left, right);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001469 if (instr->CheckFlag(HValue::kCanOverflow) ||
1470 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1471 AssignEnvironment(mul);
1472 }
1473 return DefineSameAsFirst(mul);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001474 } else if (instr->representation().IsDouble()) {
1475 return DoArithmeticD(Token::MUL, instr);
1476 } else {
1477 ASSERT(instr->representation().IsTagged());
1478 return DoArithmeticT(Token::MUL, instr);
1479 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001480}
1481
1482
1483LInstruction* LChunkBuilder::DoSub(HSub* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001484 if (instr->representation().IsInteger32()) {
1485 ASSERT(instr->left()->representation().IsInteger32());
1486 ASSERT(instr->right()->representation().IsInteger32());
1487 LOperand* left = UseRegisterAtStart(instr->left());
1488 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001489 LSubI* sub = new(zone()) LSubI(left, right);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001490 LInstruction* result = DefineSameAsFirst(sub);
1491 if (instr->CheckFlag(HValue::kCanOverflow)) {
1492 result = AssignEnvironment(result);
1493 }
1494 return result;
1495 } else if (instr->representation().IsDouble()) {
1496 return DoArithmeticD(Token::SUB, instr);
1497 } else {
1498 ASSERT(instr->representation().IsTagged());
1499 return DoArithmeticT(Token::SUB, instr);
1500 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001501}
1502
1503
1504LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001505 if (instr->representation().IsInteger32()) {
1506 ASSERT(instr->left()->representation().IsInteger32());
1507 ASSERT(instr->right()->representation().IsInteger32());
1508 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
1509 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001510 LAddI* add = new(zone()) LAddI(left, right);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001511 LInstruction* result = DefineSameAsFirst(add);
1512 if (instr->CheckFlag(HValue::kCanOverflow)) {
1513 result = AssignEnvironment(result);
1514 }
1515 return result;
1516 } else if (instr->representation().IsDouble()) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001517 return DoArithmeticD(Token::ADD, instr);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001518 } else {
1519 ASSERT(instr->representation().IsTagged());
1520 return DoArithmeticT(Token::ADD, instr);
1521 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001522 return NULL;
1523}
1524
1525
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001526LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1527 LOperand* left = NULL;
1528 LOperand* right = NULL;
1529 if (instr->representation().IsInteger32()) {
1530 ASSERT(instr->left()->representation().IsInteger32());
1531 ASSERT(instr->right()->representation().IsInteger32());
1532 left = UseRegisterAtStart(instr->LeastConstantOperand());
1533 right = UseOrConstantAtStart(instr->MostConstantOperand());
1534 } else {
1535 ASSERT(instr->representation().IsDouble());
1536 ASSERT(instr->left()->representation().IsDouble());
1537 ASSERT(instr->right()->representation().IsDouble());
1538 left = UseRegisterAtStart(instr->left());
1539 right = UseRegisterAtStart(instr->right());
1540 }
1541 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right);
1542 return DefineSameAsFirst(minmax);
1543}
1544
1545
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001546LInstruction* LChunkBuilder::DoPower(HPower* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001547 ASSERT(instr->representation().IsDouble());
1548 // We call a C function for double power. It can't trigger a GC.
1549 // We need to use fixed result register for the call.
1550 Representation exponent_type = instr->right()->representation();
1551 ASSERT(instr->left()->representation().IsDouble());
1552 LOperand* left = UseFixedDouble(instr->left(), xmm2);
1553 LOperand* right = exponent_type.IsDouble() ?
1554 UseFixedDouble(instr->right(), xmm1) :
1555#ifdef _WIN64
1556 UseFixed(instr->right(), rdx);
1557#else
1558 UseFixed(instr->right(), rdi);
1559#endif
ulan@chromium.org812308e2012-02-29 15:58:45 +00001560 LPower* result = new(zone()) LPower(left, right);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001561 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001562 CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001563}
1564
1565
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001566LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1567 ASSERT(instr->representation().IsDouble());
1568 ASSERT(instr->global_object()->representation().IsTagged());
1569#ifdef _WIN64
1570 LOperand* global_object = UseFixed(instr->global_object(), rcx);
1571#else
1572 LOperand* global_object = UseFixed(instr->global_object(), rdi);
1573#endif
ulan@chromium.org812308e2012-02-29 15:58:45 +00001574 LRandom* result = new(zone()) LRandom(global_object);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001575 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1576}
1577
1578
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001579LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001580 ASSERT(instr->left()->representation().IsTagged());
1581 ASSERT(instr->right()->representation().IsTagged());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001582 LOperand* left = UseFixed(instr->left(), rdx);
1583 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001584 LCmpT* result = new(zone()) LCmpT(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001585 return MarkAsCall(DefineFixed(result, rax), instr);
1586}
1587
1588
1589LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1590 HCompareIDAndBranch* instr) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001591 Representation r = instr->representation();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001592 if (r.IsInteger32()) {
1593 ASSERT(instr->left()->representation().IsInteger32());
1594 ASSERT(instr->right()->representation().IsInteger32());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001595 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001596 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001597 return new(zone()) LCmpIDAndBranch(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001598 } else {
1599 ASSERT(r.IsDouble());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001600 ASSERT(instr->left()->representation().IsDouble());
1601 ASSERT(instr->right()->representation().IsDouble());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001602 LOperand* left;
1603 LOperand* right;
1604 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1605 left = UseRegisterOrConstantAtStart(instr->left());
1606 right = UseRegisterOrConstantAtStart(instr->right());
1607 } else {
1608 left = UseRegisterAtStart(instr->left());
1609 right = UseRegisterAtStart(instr->right());
1610 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001611 return new(zone()) LCmpIDAndBranch(left, right);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001612 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001613}
1614
1615
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001616LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1617 HCompareObjectEqAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001618 LOperand* left = UseRegisterAtStart(instr->left());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001619 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001620 return new(zone()) LCmpObjectEqAndBranch(left, right);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001621}
1622
1623
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001624LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1625 HCompareConstantEqAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001626 LOperand* value = UseRegisterAtStart(instr->value());
1627 return new(zone()) LCmpConstantEqAndBranch(value);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001628}
1629
1630
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001631LInstruction* LChunkBuilder::DoIsNilAndBranch(HIsNilAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001632 ASSERT(instr->value()->representation().IsTagged());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001633 LOperand* temp = instr->kind() == kStrictEquality ? NULL : TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001634 return new(zone()) LIsNilAndBranch(UseRegisterAtStart(instr->value()), temp);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001635}
1636
1637
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001638LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001639 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001640 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001641}
1642
1643
erikcorry0ad885c2011-11-21 13:51:57 +00001644LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1645 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001646 LOperand* value = UseRegisterAtStart(instr->value());
erikcorry0ad885c2011-11-21 13:51:57 +00001647 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001648 return new(zone()) LIsStringAndBranch(value, temp);
erikcorry0ad885c2011-11-21 13:51:57 +00001649}
1650
1651
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001652LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001653 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001654 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001655}
1656
1657
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001658LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1659 HIsUndetectableAndBranch* instr) {
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001660 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001661 LOperand* value = UseRegisterAtStart(instr->value());
1662 LOperand* temp = TempRegister();
1663 return new(zone()) LIsUndetectableAndBranch(value, temp);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001664}
1665
1666
erikcorry0ad885c2011-11-21 13:51:57 +00001667LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1668 HStringCompareAndBranch* instr) {
1669
1670 ASSERT(instr->left()->representation().IsTagged());
1671 ASSERT(instr->right()->representation().IsTagged());
1672 LOperand* left = UseFixed(instr->left(), rdx);
1673 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001674 LStringCompareAndBranch* result =
1675 new(zone()) LStringCompareAndBranch(left, right);
erikcorry0ad885c2011-11-21 13:51:57 +00001676
1677 return MarkAsCall(result, instr);
1678}
1679
1680
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001681LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1682 HHasInstanceTypeAndBranch* instr) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001683 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001684 LOperand* value = UseRegisterAtStart(instr->value());
1685 return new(zone()) LHasInstanceTypeAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001686}
1687
1688
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001689LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1690 HGetCachedArrayIndex* instr) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001691 ASSERT(instr->value()->representation().IsTagged());
1692 LOperand* value = UseRegisterAtStart(instr->value());
1693
ulan@chromium.org812308e2012-02-29 15:58:45 +00001694 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001695}
1696
1697
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001698LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1699 HHasCachedArrayIndexAndBranch* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001700 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001701 LOperand* value = UseRegisterAtStart(instr->value());
1702 return new(zone()) LHasCachedArrayIndexAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001703}
1704
1705
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001706LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1707 HClassOfTestAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001708 LOperand* value = UseRegister(instr->value());
1709 return new(zone()) LClassOfTestAndBranch(value,
1710 TempRegister(),
1711 TempRegister());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001712}
1713
1714
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001715LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1716 HFixedArrayBaseLength* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001717 LOperand* array = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001718 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001719}
1720
1721
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001722LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1723 LOperand* map = UseRegisterAtStart(instr->value());
1724 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1725}
1726
1727
whesse@chromium.org7b260152011-06-20 15:33:18 +00001728LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1729 LOperand* object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001730 return DefineAsRegister(new(zone()) LElementsKind(object));
whesse@chromium.org7b260152011-06-20 15:33:18 +00001731}
1732
1733
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001734LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001735 LOperand* object = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001736 LValueOf* result = new(zone()) LValueOf(object);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001737 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001738}
1739
1740
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001741LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1742 LOperand* object = UseFixed(instr->value(), rax);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001743 LDateField* result = new(zone()) LDateField(object, instr->index());
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001744 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001745}
1746
1747
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001748LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1749 LOperand* string = UseRegister(instr->string());
1750 LOperand* index = UseRegister(instr->index());
1751 ASSERT(rcx.is_byte_register());
1752 LOperand* value = UseFixed(instr->value(), rcx);
1753 LSeqStringSetChar* result =
1754 new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1755 return DefineSameAsFirst(result);
1756}
1757
1758
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001759LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
1760 return NULL;
1761}
1762
1763
ulan@chromium.org2e04b582013-02-21 14:06:02 +00001764LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
1765 HInductionVariableAnnotation* instr) {
1766 return NULL;
1767}
1768
1769
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001770LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001771 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1772 LOperand* length = Use(instr->length());
1773 return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001774}
1775
1776
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001777LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1778 HBoundsCheckBaseIndexInformation* instr) {
1779 UNREACHABLE();
1780 return NULL;
1781}
1782
1783
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00001784LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1785 // The control instruction marking the end of a block that completed
1786 // abruptly (e.g., threw an exception). There is nothing specific to do.
1787 return NULL;
1788}
1789
1790
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001791LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001792 LOperand* value = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001793 return MarkAsCall(new(zone()) LThrow(value), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001794}
1795
1796
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001797LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1798 return NULL;
1799}
1800
1801
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001802LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1803 // All HForceRepresentation instructions should be eliminated in the
1804 // representation change phase of Hydrogen.
1805 UNREACHABLE();
1806 return NULL;
1807}
1808
1809
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001810LInstruction* LChunkBuilder::DoChange(HChange* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001811 Representation from = instr->from();
1812 Representation to = instr->to();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001813 // Only mark conversions that might need to allocate as calling rather than
1814 // all changes. This makes simple, non-allocating conversion not have to force
1815 // building a stack frame.
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001816 if (from.IsTagged()) {
1817 if (to.IsDouble()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001818 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001819 LOperand* value = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001820 LNumberUntagD* res = new(zone()) LNumberUntagD(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001821 return AssignEnvironment(DefineAsRegister(res));
1822 } else {
1823 ASSERT(to.IsInteger32());
1824 LOperand* value = UseRegister(instr->value());
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001825 if (instr->value()->type().IsSmi()) {
1826 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
1827 } else {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001828 bool truncating = instr->CanTruncateToInt32();
1829 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001830 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001831 return AssignEnvironment(DefineSameAsFirst(res));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001832 }
1833 }
1834 } else if (from.IsDouble()) {
1835 if (to.IsTagged()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001836 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001837 LOperand* value = UseRegister(instr->value());
1838 LOperand* temp = TempRegister();
1839
1840 // Make sure that temp and result_temp are different registers.
1841 LUnallocated* result_temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001842 LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001843 return AssignPointerMap(Define(result, result_temp));
1844 } else {
1845 ASSERT(to.IsInteger32());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001846 LOperand* value = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001847 return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToI(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001848 }
1849 } else if (from.IsInteger32()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001850 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001851 if (to.IsTagged()) {
1852 HValue* val = instr->value();
1853 LOperand* value = UseRegister(val);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001854 if (val->CheckFlag(HInstruction::kUint32)) {
1855 LOperand* temp = FixedTemp(xmm1);
1856 LNumberTagU* result = new(zone()) LNumberTagU(value, temp);
1857 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1858 } else if (val->HasRange() && val->range()->IsInSmiRange()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001859 return DefineSameAsFirst(new(zone()) LSmiTag(value));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001860 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001861 LNumberTagI* result = new(zone()) LNumberTagI(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001862 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1863 }
1864 } else {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001865 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1866 LOperand* temp = FixedTemp(xmm1);
1867 return DefineAsRegister(
1868 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
1869 } else {
1870 ASSERT(to.IsDouble());
1871 LOperand* value = Use(instr->value());
1872 return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
1873 }
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001874 }
1875 }
1876 UNREACHABLE();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001877 return NULL;
1878}
1879
1880
1881LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001882 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001883 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001884}
1885
1886
1887LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001888 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001889 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001890 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001891}
1892
1893
1894LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001895 LUnallocated* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001896 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001897 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001898}
1899
1900
1901LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001902 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001903 return AssignEnvironment(new(zone()) LCheckSmi(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001904}
1905
1906
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001907LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
1908 LOperand* value = UseRegisterAtStart(instr->value());
1909 return AssignEnvironment(new(zone()) LCheckSmi(value));
1910}
1911
1912
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001913LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001914 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001915 return AssignEnvironment(new(zone()) LCheckFunction(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001916}
1917
1918
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001919LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001920 LOperand* value = UseRegisterAtStart(instr->value());
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001921 LCheckMaps* result = new(zone()) LCheckMaps(value);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001922 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001923}
1924
1925
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001926LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1927 HValue* value = instr->value();
1928 Representation input_rep = value->representation();
1929 LOperand* reg = UseRegister(value);
1930 if (input_rep.IsDouble()) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001931 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001932 } else if (input_rep.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001933 return DefineSameAsFirst(new(zone()) LClampIToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001934 } else {
1935 ASSERT(input_rep.IsTagged());
1936 // Register allocator doesn't (yet) support allocation of double
1937 // temps. Reserve xmm1 explicitly.
ulan@chromium.org812308e2012-02-29 15:58:45 +00001938 LClampTToUint8* result = new(zone()) LClampTToUint8(reg,
ulan@chromium.org812308e2012-02-29 15:58:45 +00001939 FixedTemp(xmm1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001940 return AssignEnvironment(DefineSameAsFirst(result));
1941 }
1942}
1943
1944
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001945LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001946 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1947 return new(zone()) LReturn(UseFixed(instr->value(), rax),
1948 parameter_count);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001949}
1950
1951
1952LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1953 Representation r = instr->representation();
1954 if (r.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001955 return DefineAsRegister(new(zone()) LConstantI);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001956 } else if (r.IsDouble()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001957 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001958 return DefineAsRegister(new(zone()) LConstantD(temp));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001959 } else if (r.IsTagged()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001960 return DefineAsRegister(new(zone()) LConstantT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001961 } else {
1962 UNREACHABLE();
1963 return NULL;
1964 }
1965}
1966
1967
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001968LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001969 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001970 return instr->RequiresHoleCheck()
ager@chromium.org378b34e2011-01-28 08:04:38 +00001971 ? AssignEnvironment(DefineAsRegister(result))
1972 : DefineAsRegister(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001973}
1974
1975
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001976LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1977 LOperand* global_object = UseFixed(instr->global_object(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001978 LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001979 return MarkAsCall(DefineFixed(result, rax), instr);
1980}
1981
1982
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001983LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00001984 LOperand* value = UseRegister(instr->value());
1985 // Use a temp to avoid reloading the cell value address in the case where
1986 // we perform a hole check.
1987 return instr->RequiresHoleCheck()
ulan@chromium.org812308e2012-02-29 15:58:45 +00001988 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
1989 : new(zone()) LStoreGlobalCell(value, NULL);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001990}
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001991
1992
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001993LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1994 LOperand* global_object = UseFixed(instr->global_object(), rdx);
1995 LOperand* value = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001996 LStoreGlobalGeneric* result = new(zone()) LStoreGlobalGeneric(global_object,
1997 value);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001998 return MarkAsCall(result, instr);
1999}
2000
2001
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002002LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002003 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002004 LInstruction* result =
2005 DefineAsRegister(new(zone()) LLoadContextSlot(context));
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002006 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002007}
2008
2009
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002010LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002011 LOperand* context;
2012 LOperand* value;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002013 LOperand* temp;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002014 if (instr->NeedsWriteBarrier()) {
2015 context = UseTempRegister(instr->context());
2016 value = UseTempRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002017 temp = TempRegister();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002018 } else {
2019 context = UseRegister(instr->context());
2020 value = UseRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002021 temp = NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002022 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002023 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002024 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002025}
2026
2027
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002028LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002029 ASSERT(instr->representation().IsTagged());
2030 LOperand* obj = UseRegisterAtStart(instr->object());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002031 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002032}
2033
2034
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002035LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
2036 HLoadNamedFieldPolymorphic* instr) {
2037 ASSERT(instr->representation().IsTagged());
2038 if (instr->need_generic()) {
2039 LOperand* obj = UseFixed(instr->object(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002040 LLoadNamedFieldPolymorphic* result =
2041 new(zone()) LLoadNamedFieldPolymorphic(obj);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002042 return MarkAsCall(DefineFixed(result, rax), instr);
2043 } else {
2044 LOperand* obj = UseRegisterAtStart(instr->object());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002045 LLoadNamedFieldPolymorphic* result =
2046 new(zone()) LLoadNamedFieldPolymorphic(obj);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002047 return AssignEnvironment(DefineAsRegister(result));
2048 }
2049}
2050
2051
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002052LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002053 LOperand* object = UseFixed(instr->object(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002054 LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(object);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002055 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002056}
2057
2058
2059LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2060 HLoadFunctionPrototype* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002061 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002062 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002063}
2064
2065
2066LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002067 LOperand* input = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002068 return DefineAsRegister(new(zone()) LLoadElements(input));
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002069}
2070
2071
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002072LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2073 HLoadExternalArrayPointer* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002074 LOperand* input = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002075 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002076}
2077
2078
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002079LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002080 ASSERT(instr->key()->representation().IsInteger32() ||
2081 instr->key()->representation().IsTagged());
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002082 ElementsKind elements_kind = instr->elements_kind();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002083 bool clobbers_key = instr->key()->representation().IsTagged();
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002084 LOperand* key = clobbers_key
2085 ? UseTempRegister(instr->key())
2086 : UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002087 LLoadKeyed* result = NULL;
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002088
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002089 if (!instr->is_external()) {
2090 LOperand* obj = UseRegisterAtStart(instr->elements());
2091 result = new(zone()) LLoadKeyed(obj, key);
2092 } else {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002093 ASSERT(
2094 (instr->representation().IsInteger32() &&
2095 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2096 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2097 (instr->representation().IsDouble() &&
2098 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2099 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002100 LOperand* external_pointer = UseRegister(instr->elements());
2101 result = new(zone()) LLoadKeyed(external_pointer, key);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002102 }
2103
2104 DefineAsRegister(result);
2105 bool can_deoptimize = instr->RequiresHoleCheck() ||
2106 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002107 // An unsigned int array load might overflow and cause a deopt, make sure it
2108 // has an environment.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002109 return can_deoptimize ? AssignEnvironment(result) : result;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002110}
2111
2112
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002113LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002114 LOperand* object = UseFixed(instr->object(), rdx);
2115 LOperand* key = UseFixed(instr->key(), rax);
2116
ulan@chromium.org812308e2012-02-29 15:58:45 +00002117 LLoadKeyedGeneric* result = new(zone()) LLoadKeyedGeneric(object, key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002118 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002119}
2120
2121
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002122LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002123 ElementsKind elements_kind = instr->elements_kind();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002124 bool clobbers_key = instr->key()->representation().IsTagged();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002125
2126 if (!instr->is_external()) {
2127 ASSERT(instr->elements()->representation().IsTagged());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002128 bool needs_write_barrier = instr->NeedsWriteBarrier();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002129 LOperand* object = NULL;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002130 LOperand* key = NULL;
2131 LOperand* val = NULL;
2132
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002133 if (instr->value()->representation().IsDouble()) {
2134 object = UseRegisterAtStart(instr->elements());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002135 val = UseTempRegister(instr->value());
2136 key = clobbers_key ? UseTempRegister(instr->key())
2137 : UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002138 } else {
2139 ASSERT(instr->value()->representation().IsTagged());
2140 object = UseTempRegister(instr->elements());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002141 val = needs_write_barrier ? UseTempRegister(instr->value())
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002142 : UseRegisterOrConstantAtStart(instr->value());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002143 key = (clobbers_key || needs_write_barrier)
2144 ? UseTempRegister(instr->key())
2145 : UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002146 }
2147
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002148 return new(zone()) LStoreKeyed(object, key, val);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002149 }
2150
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002151 ASSERT(
2152 (instr->value()->representation().IsInteger32() &&
2153 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2154 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2155 (instr->value()->representation().IsDouble() &&
2156 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2157 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2158 ASSERT(instr->elements()->representation().IsExternal());
2159 bool val_is_temp_register =
2160 elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2161 elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2162 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2163 : UseRegister(instr->value());
2164 LOperand* key = clobbers_key ? UseTempRegister(instr->key())
2165 : UseRegisterOrConstantAtStart(instr->key());
2166 LOperand* external_pointer = UseRegister(instr->elements());
2167 return new(zone()) LStoreKeyed(external_pointer, key, val);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002168}
2169
2170
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002171LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002172 LOperand* object = UseFixed(instr->object(), rdx);
2173 LOperand* key = UseFixed(instr->key(), rcx);
2174 LOperand* value = UseFixed(instr->value(), rax);
2175
2176 ASSERT(instr->object()->representation().IsTagged());
2177 ASSERT(instr->key()->representation().IsTagged());
2178 ASSERT(instr->value()->representation().IsTagged());
2179
ulan@chromium.org812308e2012-02-29 15:58:45 +00002180 LStoreKeyedGeneric* result =
2181 new(zone()) LStoreKeyedGeneric(object, key, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002182 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002183}
2184
2185
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002186LInstruction* LChunkBuilder::DoTransitionElementsKind(
2187 HTransitionElementsKind* instr) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002188 LOperand* object = UseRegister(instr->object());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002189 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002190 LOperand* object = UseRegister(instr->object());
2191 LOperand* new_map_reg = TempRegister();
2192 LOperand* temp_reg = TempRegister();
2193 LTransitionElementsKind* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +00002194 new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002195 return result;
2196 } else if (FLAG_compiled_transitions) {
2197 LTransitionElementsKind* result =
2198 new(zone()) LTransitionElementsKind(object, NULL, NULL);
2199 return AssignPointerMap(result);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002200 } else {
2201 LOperand* object = UseFixed(instr->object(), rax);
2202 LOperand* fixed_object_reg = FixedTemp(rdx);
2203 LOperand* new_map_reg = FixedTemp(rbx);
2204 LTransitionElementsKind* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +00002205 new(zone()) LTransitionElementsKind(object,
2206 new_map_reg,
2207 fixed_object_reg);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002208 return MarkAsCall(result, instr);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002209 }
2210}
2211
2212
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002213LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2214 HTrapAllocationMemento* instr) {
2215 LOperand* object = UseRegister(instr->object());
2216 LOperand* temp = TempRegister();
2217 LTrapAllocationMemento* result =
2218 new(zone()) LTrapAllocationMemento(object, temp);
2219 return AssignEnvironment(result);
2220}
2221
2222
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002223LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002224 bool needs_write_barrier = instr->NeedsWriteBarrier();
verwaest@chromium.org37141392012-05-31 13:27:02 +00002225 bool needs_write_barrier_for_map = !instr->transition().is_null() &&
2226 instr->NeedsWriteBarrierForMap();
ager@chromium.org378b34e2011-01-28 08:04:38 +00002227
verwaest@chromium.org37141392012-05-31 13:27:02 +00002228 LOperand* obj;
2229 if (needs_write_barrier) {
2230 obj = instr->is_in_object()
2231 ? UseRegister(instr->object())
2232 : UseTempRegister(instr->object());
2233 } else {
2234 obj = needs_write_barrier_for_map
2235 ? UseRegister(instr->object())
2236 : UseRegisterAtStart(instr->object());
2237 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002238
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002239 bool register_or_constant = false;
2240 if (instr->value()->IsConstant()) {
2241 HConstant* constant_value = HConstant::cast(instr->value());
2242 register_or_constant = constant_value->HasInteger32Value()
2243 || constant_value->HasDoubleValue()
2244 || constant_value->ImmortalImmovable();
2245 }
2246
2247 LOperand* val;
2248 if (needs_write_barrier) {
2249 val = UseTempRegister(instr->value());
2250 } else if (register_or_constant) {
2251 val = UseRegisterOrConstant(instr->value());
2252 } else {
2253 val = UseRegister(instr->value());
2254 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002255
2256 // We only need a scratch register if we have a write barrier or we
2257 // have a store into the properties array (not in-object-property).
verwaest@chromium.org37141392012-05-31 13:27:02 +00002258 LOperand* temp = (!instr->is_in_object() || needs_write_barrier ||
2259 needs_write_barrier_for_map) ? TempRegister() : NULL;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002260
ulan@chromium.org812308e2012-02-29 15:58:45 +00002261 return new(zone()) LStoreNamedField(obj, val, temp);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002262}
2263
2264
2265LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002266 LOperand* object = UseFixed(instr->object(), rdx);
2267 LOperand* value = UseFixed(instr->value(), rax);
2268
ulan@chromium.org812308e2012-02-29 15:58:45 +00002269 LStoreNamedGeneric* result = new(zone()) LStoreNamedGeneric(object, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002270 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002271}
2272
2273
danno@chromium.org160a7b02011-04-18 15:51:38 +00002274LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2275 LOperand* left = UseOrConstantAtStart(instr->left());
2276 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002277 return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), rax),
2278 instr);
danno@chromium.org160a7b02011-04-18 15:51:38 +00002279}
2280
2281
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002282LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
ricow@chromium.org4668a2c2011-08-29 10:41:00 +00002283 LOperand* string = UseTempRegister(instr->string());
2284 LOperand* index = UseTempRegister(instr->index());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002285 LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002286 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002287}
2288
2289
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002290LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2291 LOperand* char_code = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002292 LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002293 return AssignPointerMap(DefineAsRegister(result));
2294}
2295
2296
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002297LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00002298 LOperand* string = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002299 return DefineAsRegister(new(zone()) LStringLength(string));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002300}
2301
2302
ulan@chromium.org967e2702012-02-28 09:49:15 +00002303LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002304 info()->MarkAsDeferredCalling();
mmassi@chromium.org7028c052012-06-13 11:51:58 +00002305 LAllocateObject* result = new(zone()) LAllocateObject(TempRegister());
ulan@chromium.org967e2702012-02-28 09:49:15 +00002306 return AssignPointerMap(DefineAsRegister(result));
2307}
2308
2309
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002310LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2311 info()->MarkAsDeferredCalling();
2312 LOperand* size = UseTempRegister(instr->size());
2313 LOperand* temp = TempRegister();
2314 LAllocate* result = new(zone()) LAllocate(size, temp);
2315 return AssignPointerMap(DefineAsRegister(result));
2316}
2317
2318
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002319LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002320 return MarkAsCall(DefineFixed(new(zone()) LArrayLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002321}
2322
2323
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00002324LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002325 return MarkAsCall(DefineFixed(new(zone()) LObjectLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002326}
2327
2328
2329LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002330 return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002331}
2332
2333
2334LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002335 return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002336}
2337
2338
2339LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002340 LOperand* object = UseAtStart(instr->object());
2341 LOperand* key = UseOrConstantAtStart(instr->key());
2342 LDeleteProperty* result = new(zone()) LDeleteProperty(object, key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002343 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002344}
2345
2346
2347LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002348 ASSERT(argument_count_ == 0);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002349 allocator_->MarkAsOsrEntry();
2350 current_block_->last_environment()->set_ast_id(instr->ast_id());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002351 return AssignEnvironment(new(zone()) LOsrEntry);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002352}
2353
2354
2355LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002356 LParameter* result = new(zone()) LParameter;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002357 if (instr->kind() == HParameter::STACK_PARAMETER) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002358 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2359 return DefineAsSpilled(result, spill_index);
2360 } else {
2361 ASSERT(info()->IsStub());
2362 CodeStubInterfaceDescriptor* descriptor =
2363 info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
2364 Register reg = descriptor->register_params_[instr->index()];
2365 return DefineFixed(result, reg);
2366 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002367}
2368
2369
2370LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002371 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
ager@chromium.org04921a82011-06-27 13:21:41 +00002372 if (spill_index > LUnallocated::kMaxFixedIndex) {
2373 Abort("Too many spill slots needed for OSR");
2374 spill_index = 0;
2375 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002376 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002377}
2378
2379
2380LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002381 argument_count_ -= instr->argument_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +00002382 return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002383}
2384
2385
2386LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002387 // There are no real uses of the arguments object.
2388 // arguments.length and element access are supported directly on
2389 // stack arguments, and any real arguments object use causes a bailout.
2390 // So this value is never used.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002391 return NULL;
2392}
2393
2394
2395LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002396 info()->MarkAsRequiresFrame();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002397 LOperand* args = UseRegister(instr->arguments());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002398 LOperand* length;
2399 LOperand* index;
2400 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2401 length = UseRegisterOrConstant(instr->length());
2402 index = UseOrConstant(instr->index());
2403 } else {
2404 length = UseTempRegister(instr->length());
2405 index = Use(instr->index());
2406 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002407 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002408}
2409
2410
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002411LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2412 LOperand* object = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002413 LToFastProperties* result = new(zone()) LToFastProperties(object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002414 return MarkAsCall(DefineFixed(result, rax), instr);
2415}
2416
2417
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002418LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002419 LTypeof* result = new(zone()) LTypeof(UseAtStart(instr->value()));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002420 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002421}
2422
2423
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002424LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002425 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002426}
2427
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002428
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002429LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2430 HIsConstructCallAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002431 return new(zone()) LIsConstructCallAndBranch(TempRegister());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002432}
2433
2434
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002435LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2436 HEnvironment* env = current_block_->last_environment();
2437 ASSERT(env != NULL);
2438
2439 env->set_ast_id(instr->ast_id());
2440
2441 env->Drop(instr->pop_count());
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00002442 for (int i = instr->values()->length() - 1; i >= 0; --i) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002443 HValue* value = instr->values()->at(i);
2444 if (instr->HasAssignedIndexAt(i)) {
2445 env->Bind(instr->GetAssignedIndexAt(i), value);
2446 } else {
2447 env->Push(value);
2448 }
2449 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002450
2451 // If there is an instruction pending deoptimization environment create a
2452 // lazy bailout instruction to capture the environment.
fschneider@chromium.org1df6b472011-01-26 08:23:03 +00002453 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002454 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002455 LInstruction* result = AssignEnvironment(lazy_bailout);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002456 // Store the lazy deopt environment with the instruction if needed. Right
2457 // now it is only used for LInstanceOfKnownGlobal.
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00002458 instruction_pending_deoptimization_environment_->
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002459 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2460 instruction_pending_deoptimization_environment_ = NULL;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002461 pending_deoptimization_ast_id_ = BailoutId::None();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002462 return result;
2463 }
2464
2465 return NULL;
2466}
2467
2468
2469LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002470 info()->MarkAsDeferredCalling();
ager@chromium.org04921a82011-06-27 13:21:41 +00002471 if (instr->is_function_entry()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002472 return MarkAsCall(new(zone()) LStackCheck, instr);
ager@chromium.org04921a82011-06-27 13:21:41 +00002473 } else {
2474 ASSERT(instr->is_backwards_branch());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002475 return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
ager@chromium.org04921a82011-06-27 13:21:41 +00002476 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002477}
2478
2479
2480LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002481 HEnvironment* outer = current_block_->last_environment();
2482 HConstant* undefined = graph()->GetConstantUndefined();
2483 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002484 instr->arguments_count(),
ager@chromium.org378b34e2011-01-28 08:04:38 +00002485 instr->function(),
danno@chromium.org40cb8782011-05-25 07:58:50 +00002486 undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002487 instr->inlining_kind(),
2488 instr->undefined_receiver());
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002489 if (instr->arguments_var() != NULL) {
2490 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00002491 }
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002492 inner->set_entry(instr);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002493 current_block_->UpdateEnvironment(inner);
2494 chunk_->AddInlinedClosure(instr->closure());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002495 return NULL;
2496}
2497
2498
2499LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002500 LInstruction* pop = NULL;
2501
2502 HEnvironment* env = current_block_->last_environment();
2503
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002504 if (env->entry()->arguments_pushed()) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002505 int argument_count = env->arguments_environment()->parameter_count();
2506 pop = new(zone()) LDrop(argument_count);
2507 argument_count_ -= argument_count;
2508 }
2509
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002510 HEnvironment* outer = current_block_->last_environment()->
2511 DiscardInlined(false);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002512 current_block_->UpdateEnvironment(outer);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002513
2514 return pop;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002515}
2516
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002517
2518LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2519 LOperand* key = UseOrConstantAtStart(instr->key());
2520 LOperand* object = UseOrConstantAtStart(instr->object());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002521 LIn* result = new(zone()) LIn(key, object);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002522 return MarkAsCall(DefineFixed(result, rax), instr);
2523}
2524
2525
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002526LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2527 LOperand* object = UseFixed(instr->enumerable(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002528 LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002529 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2530}
2531
2532
2533LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2534 LOperand* map = UseRegister(instr->map());
2535 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002536 new(zone()) LForInCacheArray(map)));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002537}
2538
2539
2540LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2541 LOperand* value = UseRegisterAtStart(instr->value());
2542 LOperand* map = UseRegisterAtStart(instr->map());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002543 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002544}
2545
2546
2547LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2548 LOperand* object = UseRegister(instr->object());
2549 LOperand* index = UseTempRegister(instr->index());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002550 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002551}
2552
2553
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002554} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002555
2556#endif // V8_TARGET_ARCH_X64