blob: 278d60030464f8ba83de548fcc6196ed7cb11342 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +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
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000030#if V8_TARGET_ARCH_IA32
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000031
ricow@chromium.org83aa5492011-02-07 12:42:56 +000032#include "lithium-allocator-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000033#include "ia32/lithium-ia32.h"
34#include "ia32/lithium-codegen-ia32.h"
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000035#include "hydrogen-osr.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036
37namespace v8 {
38namespace internal {
39
40#define DEFINE_COMPILE(type) \
41 void L##type::CompileToNative(LCodeGen* generator) { \
42 generator->Do##type(this); \
43 }
44LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
45#undef DEFINE_COMPILE
46
kasperl@chromium.orga5551262010-12-07 12:49:48 +000047
ricow@chromium.org83aa5492011-02-07 12:42:56 +000048#ifdef DEBUG
49void LInstruction::VerifyCall() {
danno@chromium.org160a7b02011-04-18 15:51:38 +000050 // Call instructions can use only fixed registers as temporaries and
51 // outputs because all registers are blocked by the calling convention.
52 // Inputs operands must use a fixed register or use-at-start policy or
53 // a non-register policy.
ricow@chromium.org83aa5492011-02-07 12:42:56 +000054 ASSERT(Output() == NULL ||
55 LUnallocated::cast(Output())->HasFixedPolicy() ||
56 !LUnallocated::cast(Output())->HasRegisterPolicy());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000057 for (UseIterator it(this); !it.Done(); it.Advance()) {
58 LUnallocated* operand = LUnallocated::cast(it.Current());
danno@chromium.org160a7b02011-04-18 15:51:38 +000059 ASSERT(operand->HasFixedPolicy() ||
60 operand->IsUsedAtStart());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000061 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000062 for (TempIterator it(this); !it.Done(); it.Advance()) {
63 LUnallocated* operand = LUnallocated::cast(it.Current());
danno@chromium.org160a7b02011-04-18 15:51:38 +000064 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000065 }
66}
67#endif
68
69
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000070bool LInstruction::HasDoubleRegisterResult() {
71 return HasResult() && result()->IsDoubleRegister();
72}
73
74
75bool LInstruction::HasDoubleRegisterInput() {
76 for (int i = 0; i < InputCount(); i++) {
77 LOperand* op = InputAt(i);
danno@chromium.orgca29dd82013-04-26 11:59:48 +000078 if (op != NULL && op->IsDoubleRegister()) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000079 return true;
80 }
81 }
82 return false;
83}
84
85
danno@chromium.org169691d2013-07-15 08:01:13 +000086bool LInstruction::IsDoubleInput(X87Register reg, LCodeGen* cgen) {
87 for (int i = 0; i < InputCount(); i++) {
88 LOperand* op = InputAt(i);
89 if (op != NULL && op->IsDoubleRegister()) {
90 if (cgen->ToX87Register(op).is(reg)) return true;
91 }
92 }
93 return false;
94}
95
96
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000097void LInstruction::PrintTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000098 stream->Add("%s ", this->Mnemonic());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000099
100 PrintOutputOperandTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000101
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 PrintDataTo(stream);
103
104 if (HasEnvironment()) {
105 stream->Add(" ");
106 environment()->PrintTo(stream);
107 }
108
109 if (HasPointerMap()) {
110 stream->Add(" ");
111 pointer_map()->PrintTo(stream);
112 }
113}
114
115
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000116void LInstruction::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000117 stream->Add("= ");
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000118 for (int i = 0; i < InputCount(); i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000119 if (i > 0) stream->Add(" ");
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +0000120 if (InputAt(i) == NULL) {
121 stream->Add("NULL");
122 } else {
123 InputAt(i)->PrintTo(stream);
124 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000125 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000126}
127
128
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000129void LInstruction::PrintOutputOperandTo(StringStream* stream) {
130 if (HasResult()) result()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000131}
132
133
134void LLabel::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 LGap::PrintDataTo(stream);
136 LLabel* rep = replacement();
137 if (rep != NULL) {
138 stream->Add(" Dead block replaced with B%d", rep->block_id());
139 }
140}
141
142
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143bool LGap::IsRedundant() const {
144 for (int i = 0; i < 4; i++) {
145 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
146 return false;
147 }
148 }
149
150 return true;
151}
152
153
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000154void LGap::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 for (int i = 0; i < 4; i++) {
156 stream->Add("(");
157 if (parallel_moves_[i] != NULL) {
158 parallel_moves_[i]->PrintDataTo(stream);
159 }
160 stream->Add(") ");
161 }
162}
163
164
165const char* LArithmeticD::Mnemonic() const {
166 switch (op()) {
167 case Token::ADD: return "add-d";
168 case Token::SUB: return "sub-d";
169 case Token::MUL: return "mul-d";
170 case Token::DIV: return "div-d";
171 case Token::MOD: return "mod-d";
172 default:
173 UNREACHABLE();
174 return NULL;
175 }
176}
177
178
179const char* LArithmeticT::Mnemonic() const {
180 switch (op()) {
181 case Token::ADD: return "add-t";
182 case Token::SUB: return "sub-t";
183 case Token::MUL: return "mul-t";
184 case Token::MOD: return "mod-t";
185 case Token::DIV: return "div-t";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000186 case Token::BIT_AND: return "bit-and-t";
187 case Token::BIT_OR: return "bit-or-t";
188 case Token::BIT_XOR: return "bit-xor-t";
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000189 case Token::ROR: return "ror-t";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000190 case Token::SHL: return "sal-t";
191 case Token::SAR: return "sar-t";
192 case Token::SHR: return "shr-t";
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000193 default:
194 UNREACHABLE();
195 return NULL;
196 }
197}
198
199
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000200bool LGoto::HasInterestingComment(LCodeGen* gen) const {
201 return !gen->IsNextEmittedBlock(block_id());
202}
203
204
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000205void LGoto::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000206 stream->Add("B%d", block_id());
207}
208
209
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000210void LBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000211 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000212 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000213}
214
215
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000216void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000217 stream->Add("if ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000218 left()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219 stream->Add(" %s ", Token::String(op()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000220 right()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
222}
223
224
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000225void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000226 stream->Add("if is_object(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000227 value()->PrintTo(stream);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000228 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
229}
230
231
erikcorry0ad885c2011-11-21 13:51:57 +0000232void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
233 stream->Add("if is_string(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000234 value()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000235 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
236}
237
238
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000239void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000240 stream->Add("if is_smi(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000241 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000242 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
243}
244
245
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000246void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
247 stream->Add("if is_undetectable(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000248 value()->PrintTo(stream);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000249 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
250}
251
252
erikcorry0ad885c2011-11-21 13:51:57 +0000253void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
254 stream->Add("if string_compare(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000255 left()->PrintTo(stream);
256 right()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000257 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
258}
259
260
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000261void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262 stream->Add("if has_instance_type(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000263 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000264 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
265}
266
267
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000268void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 stream->Add("if has_cached_array_index(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000270 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000271 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
272}
273
274
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000275void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000276 stream->Add("if class_of_test(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000277 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000278 stream->Add(", \"%o\") then B%d else B%d",
279 *hydrogen()->class_name(),
280 true_block_id(),
281 false_block_id());
282}
283
284
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000285void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000286 stream->Add("if typeof ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000287 value()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000288 stream->Add(" == \"%s\" then B%d else B%d",
289 *hydrogen()->type_literal()->ToCString(),
290 true_block_id(), false_block_id());
291}
292
293
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000294void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
295 stream->Add(" = ");
296 function()->PrintTo(stream);
297 stream->Add(".code_entry = ");
298 code_object()->PrintTo(stream);
299}
300
301
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000302void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
303 stream->Add(" = ");
304 base_object()->PrintTo(stream);
305 stream->Add(" + %d", offset());
306}
307
308
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000309void LCallConstantFunction::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000310 stream->Add("#%d / ", arity());
311}
312
313
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000314void LLoadContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000315 context()->PrintTo(stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000316 stream->Add("[%d]", slot_index());
317}
318
319
320void LStoreContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000321 context()->PrintTo(stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000322 stream->Add("[%d] <- ", slot_index());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000323 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000324}
325
326
danno@chromium.org160a7b02011-04-18 15:51:38 +0000327void LInvokeFunction::PrintDataTo(StringStream* stream) {
328 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000329 context()->PrintTo(stream);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000330 stream->Add(" ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000331 function()->PrintTo(stream);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000332 stream->Add(" #%d / ", arity());
333}
334
335
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000336void LCallKeyed::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000337 stream->Add("[ecx] #%d / ", arity());
338}
339
340
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000341void LCallNamed::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000342 SmartArrayPointer<char> name_string = name()->ToCString();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000343 stream->Add("%s #%d / ", *name_string, arity());
344}
345
346
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000347void LCallGlobal::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000348 SmartArrayPointer<char> name_string = name()->ToCString();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000349 stream->Add("%s #%d / ", *name_string, arity());
350}
351
352
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000353void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000354 stream->Add("#%d / ", arity());
355}
356
357
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000358void LCallNew::PrintDataTo(StringStream* stream) {
359 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000360 context()->PrintTo(stream);
361 stream->Add(" ");
362 constructor()->PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000363 stream->Add(" #%d / ", arity());
364}
365
366
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000367void LCallNewArray::PrintDataTo(StringStream* stream) {
368 stream->Add("= ");
369 context()->PrintTo(stream);
370 stream->Add(" ");
371 constructor()->PrintTo(stream);
372 stream->Add(" #%d / ", arity());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000373 ElementsKind kind = hydrogen()->elements_kind();
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000374 stream->Add(" (%s) ", ElementsKindToString(kind));
375}
376
377
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000378void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000379 arguments()->PrintTo(stream);
380
381 stream->Add(" length ");
382 length()->PrintTo(stream);
383
384 stream->Add(" index ");
385 index()->PrintTo(stream);
386}
387
388
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000389int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000390 // Skip a slot if for a double-width slot.
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000391 if (kind == DOUBLE_REGISTERS) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000392 spill_slot_count_++;
393 spill_slot_count_ |= 1;
394 num_double_slots_++;
395 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000396 return spill_slot_count_++;
397}
398
399
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000400LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
401 int index = GetNextSpillIndex(kind);
402 if (kind == DOUBLE_REGISTERS) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000403 return LDoubleStackSlot::Create(index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404 } else {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000405 ASSERT(kind == GENERAL_REGISTERS);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000406 return LStackSlot::Create(index, zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000407 }
408}
409
410
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000411void LStoreNamedField::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000412 object()->PrintTo(stream);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000413 hydrogen()->access().PrintTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000414 stream->Add(" <- ");
415 value()->PrintTo(stream);
416}
417
418
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000419void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
420 object()->PrintTo(stream);
421 stream->Add(".");
422 stream->Add(*String::cast(*name())->ToCString());
423 stream->Add(" <- ");
424 value()->PrintTo(stream);
425}
426
427
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000428void LLoadKeyed::PrintDataTo(StringStream* stream) {
429 elements()->PrintTo(stream);
430 stream->Add("[");
431 key()->PrintTo(stream);
432 if (hydrogen()->IsDehoisted()) {
433 stream->Add(" + %d]", additional_index());
434 } else {
435 stream->Add("]");
436 }
437}
438
439
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000440void LStoreKeyed::PrintDataTo(StringStream* stream) {
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000441 elements()->PrintTo(stream);
442 stream->Add("[");
443 key()->PrintTo(stream);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000444 if (hydrogen()->IsDehoisted()) {
445 stream->Add(" + %d] <-", additional_index());
446 } else {
447 stream->Add("] <- ");
448 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000449
450 if (value() == NULL) {
451 ASSERT(hydrogen()->IsConstantHoleStore() &&
452 hydrogen()->value()->representation().IsDouble());
453 stream->Add("<the hole(nan)>");
454 } else {
455 value()->PrintTo(stream);
456 }
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000457}
458
459
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000460void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000461 object()->PrintTo(stream);
462 stream->Add("[");
463 key()->PrintTo(stream);
464 stream->Add("] <- ");
465 value()->PrintTo(stream);
466}
467
468
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000469void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
470 object()->PrintTo(stream);
471 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
472}
473
474
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000475LPlatformChunk* LChunkBuilder::Build() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000476 ASSERT(is_unused());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000477 chunk_ = new(zone()) LPlatformChunk(info(), graph());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000478 LPhase phase("L_Building chunk", chunk_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000479 status_ = BUILDING;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000480
481 // Reserve the first spill slot for the state of dynamic alignment.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000482 if (info()->IsOptimizing()) {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000483 int alignment_state_index = chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000484 ASSERT_EQ(alignment_state_index, 0);
485 USE(alignment_state_index);
486 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000487
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000488 // If compiling for OSR, reserve space for the unoptimized frame,
489 // which will be subsumed into this frame.
490 if (graph()->has_osr()) {
491 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000492 chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000493 }
494 }
495
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000496 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
497 for (int i = 0; i < blocks->length(); i++) {
498 HBasicBlock* next = NULL;
499 if (i < blocks->length() - 1) next = blocks->at(i + 1);
500 DoBasicBlock(blocks->at(i), next);
501 if (is_aborted()) return NULL;
502 }
503 status_ = DONE;
504 return chunk_;
505}
506
507
danno@chromium.org59400602013-08-13 17:09:37 +0000508void LChunkBuilder::Abort(BailoutReason reason) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000509 info()->set_bailout_reason(reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000510 status_ = ABORTED;
511}
512
513
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000515 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
516 Register::ToAllocationIndex(reg));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000517}
518
519
520LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000521 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
522 XMMRegister::ToAllocationIndex(reg));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000523}
524
525
526LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
527 return Use(value, ToUnallocated(fixed_register));
528}
529
530
531LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
532 return Use(value, ToUnallocated(reg));
533}
534
535
536LOperand* LChunkBuilder::UseRegister(HValue* value) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000537 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000538}
539
540
541LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
542 return Use(value,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000543 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
544 LUnallocated::USED_AT_START));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000545}
546
547
548LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000549 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000550}
551
552
553LOperand* LChunkBuilder::Use(HValue* value) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000554 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000555}
556
557
558LOperand* LChunkBuilder::UseAtStart(HValue* value) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000559 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
560 LUnallocated::USED_AT_START));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000561}
562
563
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000564static inline bool CanBeImmediateConstant(HValue* value) {
565 return value->IsConstant() && HConstant::cast(value)->NotInNewSpace();
566}
567
568
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000569LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000570 return CanBeImmediateConstant(value)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000571 ? chunk_->DefineConstantOperand(HConstant::cast(value))
572 : Use(value);
573}
574
575
576LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000577 return CanBeImmediateConstant(value)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000578 ? chunk_->DefineConstantOperand(HConstant::cast(value))
579 : UseAtStart(value);
580}
581
582
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000583LOperand* LChunkBuilder::UseFixedOrConstant(HValue* value,
584 Register fixed_register) {
585 return CanBeImmediateConstant(value)
586 ? chunk_->DefineConstantOperand(HConstant::cast(value))
587 : UseFixed(value, fixed_register);
588}
589
590
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000591LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000592 return CanBeImmediateConstant(value)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000593 ? chunk_->DefineConstantOperand(HConstant::cast(value))
594 : UseRegister(value);
595}
596
597
598LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000599 return CanBeImmediateConstant(value)
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000600 ? chunk_->DefineConstantOperand(HConstant::cast(value))
601 : UseRegisterAtStart(value);
602}
603
604
danno@chromium.orgf005df62013-04-30 16:36:45 +0000605LOperand* LChunkBuilder::UseConstant(HValue* value) {
606 return chunk_->DefineConstantOperand(HConstant::cast(value));
607}
608
609
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000610LOperand* LChunkBuilder::UseAny(HValue* value) {
611 return value->IsConstant()
612 ? chunk_->DefineConstantOperand(HConstant::cast(value))
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000613 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000614}
615
616
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000617LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
618 if (value->EmitAtUses()) {
619 HInstruction* instr = HInstruction::cast(value);
620 VisitInstruction(instr);
621 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000622 operand->set_virtual_register(value->id());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000623 return operand;
624}
625
626
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000627template<int I, int T>
628LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
629 LUnallocated* result) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000630 result->set_virtual_register(current_instruction_->id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000631 instr->set_result(result);
632 return instr;
633}
634
635
636template<int I, int T>
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000637LInstruction* LChunkBuilder::DefineAsRegister(
638 LTemplateInstruction<1, I, T>* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000639 return Define(instr,
640 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000641}
642
643
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000644template<int I, int T>
645LInstruction* LChunkBuilder::DefineAsSpilled(
646 LTemplateInstruction<1, I, T>* instr,
647 int index) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000648 return Define(instr,
649 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000650}
651
652
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000653template<int I, int T>
654LInstruction* LChunkBuilder::DefineSameAsFirst(
655 LTemplateInstruction<1, I, T>* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000656 return Define(instr,
657 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000658}
659
660
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000661template<int I, int T>
662LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
663 Register reg) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000664 return Define(instr, ToUnallocated(reg));
665}
666
667
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000668template<int I, int T>
669LInstruction* LChunkBuilder::DefineFixedDouble(
670 LTemplateInstruction<1, I, T>* instr,
671 XMMRegister reg) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672 return Define(instr, ToUnallocated(reg));
673}
674
675
676LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
677 HEnvironment* hydrogen_env = current_block_->last_environment();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000678 int argument_index_accumulator = 0;
danno@chromium.org59400602013-08-13 17:09:37 +0000679 ZoneList<HValue*> objects_to_materialize(0, zone());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000680 instr->set_environment(CreateEnvironment(hydrogen_env,
danno@chromium.org59400602013-08-13 17:09:37 +0000681 &argument_index_accumulator,
682 &objects_to_materialize));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000683 return instr;
684}
685
686
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000687LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
688 HInstruction* hinstr,
689 CanDeoptimize can_deoptimize) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000690 info()->MarkAsNonDeferredCalling();
691
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000692#ifdef DEBUG
693 instr->VerifyCall();
694#endif
695 instr->MarkAsCall();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000696 instr = AssignPointerMap(instr);
697
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000698 if (hinstr->HasObservableSideEffects()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000699 ASSERT(hinstr->next()->IsSimulate());
700 HSimulate* sim = HSimulate::cast(hinstr->next());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000701 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000702 ASSERT(pending_deoptimization_ast_id_.IsNone());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000703 instruction_pending_deoptimization_environment_ = instr;
704 pending_deoptimization_ast_id_ = sim->ast_id();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000705 }
706
707 // If instruction does not have side-effects lazy deoptimization
708 // after the call will try to deoptimize to the point before the call.
709 // Thus we still need to attach environment to this call even if
710 // call sequence can not deoptimize eagerly.
711 bool needs_environment =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000712 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
713 !hinstr->HasObservableSideEffects();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000714 if (needs_environment && !instr->HasEnvironment()) {
715 instr = AssignEnvironment(instr);
716 }
717
718 return instr;
719}
720
721
722LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
723 ASSERT(!instr->HasPointerMap());
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000724 instr->set_pointer_map(new(zone()) LPointerMap(zone()));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000725 return instr;
726}
727
728
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000729LUnallocated* LChunkBuilder::TempRegister() {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000730 LUnallocated* operand =
731 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000732 int vreg = allocator_->GetVirtualRegister();
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000733 if (!allocator_->AllocationOk()) {
danno@chromium.org59400602013-08-13 17:09:37 +0000734 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000735 vreg = 0;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000736 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000737 operand->set_virtual_register(vreg);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000738 return operand;
739}
740
741
742LOperand* LChunkBuilder::FixedTemp(Register reg) {
743 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000744 ASSERT(operand->HasFixedPolicy());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000745 return operand;
746}
747
748
749LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
750 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000751 ASSERT(operand->HasFixedPolicy());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000752 return operand;
753}
754
755
756LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000757 return new(zone()) LLabel(instr->block());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000758}
759
760
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000761LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
762 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
763}
764
765
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000766LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
767 UNREACHABLE();
768 return NULL;
769}
770
771
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000772LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000773 return AssignEnvironment(new(zone()) LDeoptimize);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000774}
775
776
777LInstruction* LChunkBuilder::DoShift(Token::Value op,
778 HBitwiseBinaryOperation* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000779 if (instr->representation().IsSmiOrInteger32()) {
780 ASSERT(instr->left()->representation().Equals(instr->representation()));
781 ASSERT(instr->right()->representation().Equals(instr->representation()));
782 LOperand* left = UseRegisterAtStart(instr->left());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000783
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000784 HValue* right_value = instr->right();
785 LOperand* right = NULL;
786 int constant_value = 0;
787 bool does_deopt = false;
788 if (right_value->IsConstant()) {
789 HConstant* constant = HConstant::cast(right_value);
790 right = chunk_->DefineConstantOperand(constant);
791 constant_value = constant->Integer32Value() & 0x1f;
792 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
793 // truncated to smi.
794 if (instr->representation().IsSmi() && constant_value > 0) {
795 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
796 }
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000797 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000798 right = UseFixed(right_value, ecx);
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000799 }
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000800
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000801 // Shift operations can only deoptimize if we do a logical shift by 0 and
802 // the result cannot be truncated to int32.
803 if (op == Token::SHR && constant_value == 0) {
804 if (FLAG_opt_safe_uint32_operations) {
805 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
806 } else {
807 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
808 }
809 }
810
811 LInstruction* result =
812 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
813 return does_deopt ? AssignEnvironment(result) : result;
814 } else {
815 return DoArithmeticT(op, instr);
816 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000817}
818
819
820LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
821 HArithmeticBinaryOperation* instr) {
822 ASSERT(instr->representation().IsDouble());
823 ASSERT(instr->left()->representation().IsDouble());
824 ASSERT(instr->right()->representation().IsDouble());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000825 if (op == Token::MOD) {
826 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
827 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
828 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
829 return MarkAsCall(DefineSameAsFirst(result), instr);
830 } else {
831 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
832 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
833 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
834 return DefineSameAsFirst(result);
835 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000836}
837
838
839LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000840 HBinaryOperation* instr) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000841 HValue* left = instr->left();
842 HValue* right = instr->right();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000843 ASSERT(left->representation().IsTagged());
844 ASSERT(right->representation().IsTagged());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000845 LOperand* context = UseFixed(instr->context(), esi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000846 LOperand* left_operand = UseFixed(left, edx);
847 LOperand* right_operand = UseFixed(right, eax);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000848 LArithmeticT* result =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000849 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000850 return MarkAsCall(DefineFixed(result, eax), instr);
851}
852
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000853
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000854void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
855 ASSERT(is_building());
856 current_block_ = block;
857 next_block_ = next_block;
858 if (block->IsStartBlock()) {
859 block->UpdateEnvironment(graph_->start_environment());
860 argument_count_ = 0;
861 } else if (block->predecessors()->length() == 1) {
862 // We have a single predecessor => copy environment and outgoing
863 // argument count from the predecessor.
864 ASSERT(block->phis()->length() == 0);
865 HBasicBlock* pred = block->predecessors()->at(0);
866 HEnvironment* last_environment = pred->last_environment();
867 ASSERT(last_environment != NULL);
868 // Only copy the environment, if it is later used again.
869 if (pred->end()->SecondSuccessor() == NULL) {
870 ASSERT(pred->end()->FirstSuccessor() == block);
871 } else {
872 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
873 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
874 last_environment = last_environment->Copy();
875 }
876 }
877 block->UpdateEnvironment(last_environment);
878 ASSERT(pred->argument_count() >= 0);
879 argument_count_ = pred->argument_count();
880 } else {
881 // We are at a state join => process phis.
882 HBasicBlock* pred = block->predecessors()->at(0);
883 // No need to copy the environment, it cannot be used later.
884 HEnvironment* last_environment = pred->last_environment();
885 for (int i = 0; i < block->phis()->length(); ++i) {
886 HPhi* phi = block->phis()->at(i);
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000887 if (phi->HasMergedIndex()) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000888 last_environment->SetValueAt(phi->merged_index(), phi);
889 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000890 }
891 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000892 if (block->deleted_phis()->at(i) < last_environment->length()) {
893 last_environment->SetValueAt(block->deleted_phis()->at(i),
894 graph_->GetConstantUndefined());
895 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000896 }
897 block->UpdateEnvironment(last_environment);
898 // Pick up the outgoing argument count of one of the predecessors.
899 argument_count_ = pred->argument_count();
900 }
901 HInstruction* current = block->first();
902 int start = chunk_->instructions()->length();
903 while (current != NULL && !is_aborted()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000904 // Code for constants in registers is generated lazily.
905 if (!current->EmitAtUses()) {
906 VisitInstruction(current);
907 }
908 current = current->next();
909 }
910 int end = chunk_->instructions()->length() - 1;
911 if (end >= start) {
912 block->set_first_instruction_index(start);
913 block->set_last_instruction_index(end);
914 }
915 block->set_argument_count(argument_count_);
916 next_block_ = NULL;
917 current_block_ = NULL;
918}
919
920
921void LChunkBuilder::VisitInstruction(HInstruction* current) {
922 HInstruction* old_current = current_instruction_;
923 current_instruction_ = current;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000924
925 LInstruction* instr = NULL;
926 if (current->CanReplaceWithDummyUses()) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000927 if (current->OperandCount() == 0) {
928 instr = DefineAsRegister(new(zone()) LDummy());
929 } else {
930 instr = DefineAsRegister(new(zone())
931 LDummyUse(UseAny(current->OperandAt(0))));
932 }
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000933 for (int i = 1; i < current->OperandCount(); ++i) {
934 LInstruction* dummy =
935 new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
936 dummy->set_hydrogen_value(current);
937 chunk_->AddInstruction(dummy, current_block_);
938 }
939 } else {
940 instr = current->CompileToLithium(this);
941 }
942
943 argument_count_ += current->argument_delta();
944 ASSERT(argument_count_ >= 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000945
946 if (instr != NULL) {
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000947 // Associate the hydrogen instruction first, since we may need it for
948 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
949 instr->set_hydrogen_value(current);
950
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000951#if DEBUG
952 // Make sure that the lithium instruction has either no fixed register
953 // constraints in temps or the result OR no uses that are only used at
954 // start. If this invariant doesn't hold, the register allocator can decide
955 // to insert a split of a range immediately before the instruction due to an
956 // already allocated register needing to be used for the instruction's fixed
957 // register constraint. In this case, The register allocator won't see an
958 // interference between the split child and the use-at-start (it would if
959 // the it was just a plain use), so it is free to move the split child into
960 // the same register that is used for the use-at-start.
961 // See https://code.google.com/p/chromium/issues/detail?id=201590
962 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
963 int fixed = 0;
964 int used_at_start = 0;
965 for (UseIterator it(instr); !it.Done(); it.Advance()) {
966 LUnallocated* operand = LUnallocated::cast(it.Current());
967 if (operand->IsUsedAtStart()) ++used_at_start;
968 }
969 if (instr->Output() != NULL) {
970 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
971 }
972 for (TempIterator it(instr); !it.Done(); it.Advance()) {
973 LUnallocated* operand = LUnallocated::cast(it.Current());
974 if (operand->HasFixedPolicy()) ++fixed;
975 }
976 ASSERT(fixed == 0 || used_at_start == 0);
977 }
978#endif
979
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000980 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
981 instr = AssignPointerMap(instr);
982 }
983 if (FLAG_stress_environments && !instr->HasEnvironment()) {
984 instr = AssignEnvironment(instr);
985 }
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000986 if (!CpuFeatures::IsSafeForSnapshot(SSE2) && instr->IsGoto() &&
987 LGoto::cast(instr)->jumps_to_join()) {
988 // TODO(olivf) Since phis of spilled values are joined as registers
989 // (not in the stack slot), we need to allow the goto gaps to keep one
990 // x87 register alive. To ensure all other values are still spilled, we
991 // insert a fpu register barrier right before.
992 LClobberDoubles* clobber = new(zone()) LClobberDoubles();
993 clobber->set_hydrogen_value(current);
994 chunk_->AddInstruction(clobber, current_block_);
995 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000996 chunk_->AddInstruction(instr, current_block_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000997 }
998 current_instruction_ = old_current;
999}
1000
1001
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001002LEnvironment* LChunkBuilder::CreateEnvironment(
1003 HEnvironment* hydrogen_env,
danno@chromium.org59400602013-08-13 17:09:37 +00001004 int* argument_index_accumulator,
1005 ZoneList<HValue*>* objects_to_materialize) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001006 if (hydrogen_env == NULL) return NULL;
1007
danno@chromium.org59400602013-08-13 17:09:37 +00001008 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
1009 argument_index_accumulator,
1010 objects_to_materialize);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001011 BailoutId ast_id = hydrogen_env->ast_id();
1012 ASSERT(!ast_id.IsNone() ||
ulan@chromium.org967e2702012-02-28 09:49:15 +00001013 hydrogen_env->frame_type() != JS_FUNCTION);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001014 int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001015 LEnvironment* result =
1016 new(zone()) LEnvironment(hydrogen_env->closure(),
ulan@chromium.org967e2702012-02-28 09:49:15 +00001017 hydrogen_env->frame_type(),
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001018 ast_id,
1019 hydrogen_env->parameter_count(),
1020 argument_count_,
1021 value_count,
rossberg@chromium.org400388e2012-06-06 09:29:22 +00001022 outer,
ulan@chromium.org56c14af2012-09-20 12:51:09 +00001023 hydrogen_env->entry(),
rossberg@chromium.org400388e2012-06-06 09:29:22 +00001024 zone());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001025 int argument_index = *argument_index_accumulator;
danno@chromium.org59400602013-08-13 17:09:37 +00001026 int object_index = objects_to_materialize->length();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001027 for (int i = 0; i < hydrogen_env->length(); ++i) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001028 if (hydrogen_env->is_special_index(i)) continue;
1029
danno@chromium.org59400602013-08-13 17:09:37 +00001030 LOperand* op;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001031 HValue* value = hydrogen_env->values()->at(i);
danno@chromium.org59400602013-08-13 17:09:37 +00001032 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
1033 objects_to_materialize->Add(value, zone());
1034 op = LEnvironment::materialization_marker();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001035 } else if (value->IsPushArgument()) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001036 op = new(zone()) LArgument(argument_index++);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001037 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001038 op = UseAny(value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001039 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001040 result->AddValue(op,
1041 value->representation(),
1042 value->CheckFlag(HInstruction::kUint32));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001043 }
1044
danno@chromium.org59400602013-08-13 17:09:37 +00001045 for (int i = object_index; i < objects_to_materialize->length(); ++i) {
1046 HValue* object_to_materialize = objects_to_materialize->at(i);
1047 int previously_materialized_object = -1;
1048 for (int prev = 0; prev < i; ++prev) {
1049 if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
1050 previously_materialized_object = prev;
1051 break;
1052 }
1053 }
1054 int length = object_to_materialize->OperandCount();
1055 bool is_arguments = object_to_materialize->IsArgumentsObject();
1056 if (previously_materialized_object >= 0) {
1057 result->AddDuplicateObject(previously_materialized_object);
1058 continue;
1059 } else {
1060 result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
1061 }
1062 for (int i = is_arguments ? 1 : 0; i < length; ++i) {
1063 LOperand* op;
1064 HValue* value = object_to_materialize->OperandAt(i);
1065 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
1066 objects_to_materialize->Add(value, zone());
1067 op = LEnvironment::materialization_marker();
1068 } else {
1069 ASSERT(!value->IsPushArgument());
1070 op = UseAny(value);
1071 }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001072 result->AddValue(op,
1073 value->representation(),
1074 value->CheckFlag(HInstruction::kUint32));
1075 }
1076 }
1077
ulan@chromium.org967e2702012-02-28 09:49:15 +00001078 if (hydrogen_env->frame_type() == JS_FUNCTION) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001079 *argument_index_accumulator = argument_index;
1080 }
1081
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001082 return result;
1083}
1084
1085
1086LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001087 return new(zone()) LGoto(instr->FirstSuccessor());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001088}
1089
1090
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001091LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001092 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1093 if (goto_instr != NULL) return goto_instr;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001094
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001095 ToBooleanStub::Types expected = instr->expected_input_types();
1096
1097 // Tagged values that are not known smis or booleans require a
1098 // deoptimization environment. If the instruction is generic no
1099 // environment is needed since all cases are handled.
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001100 HValue* value = instr->value();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001101 Representation rep = value->representation();
1102 HType type = value->type();
1103 if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) {
1104 return new(zone()) LBranch(UseRegister(value), NULL);
1105 }
1106
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001107 bool needs_temp = expected.NeedsMap() || expected.IsEmpty();
1108 LOperand* temp = needs_temp ? TempRegister() : NULL;
1109
1110 // The Generic stub does not have a deopt, so we need no environment.
1111 if (expected.IsGeneric()) {
1112 return new(zone()) LBranch(UseRegister(value), temp);
1113 }
1114
vegorov@chromium.org7943d462011-08-01 11:41:52 +00001115 // We need a temporary register when we have to access the map *or* we have
1116 // no type info yet, in which case we handle all cases (including the ones
1117 // involving maps).
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001118 return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001119}
1120
1121
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001122LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1123 return new(zone()) LDebugBreak();
1124}
1125
1126
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001127LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001128 ASSERT(instr->value()->representation().IsTagged());
1129 LOperand* value = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001130 return new(zone()) LCmpMapAndBranch(value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001131}
1132
1133
1134LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001135 info()->MarkAsRequiresFrame();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001136 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001137}
1138
1139
1140LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001141 info()->MarkAsRequiresFrame();
danno@chromium.orgb2a1c072012-03-23 15:47:56 +00001142 return DefineAsRegister(new(zone()) LArgumentsElements);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001143}
1144
1145
1146LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001147 LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
1148 LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
1149 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001150 LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001151 return MarkAsCall(DefineFixed(result, eax), instr);
1152}
1153
1154
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001155LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1156 HInstanceOfKnownGlobal* instr) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001157 LInstanceOfKnownGlobal* result =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001158 new(zone()) LInstanceOfKnownGlobal(
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001159 UseFixed(instr->context(), esi),
1160 UseFixed(instr->left(), InstanceofStub::left()),
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001161 FixedTemp(edi));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001162 return MarkAsCall(DefineFixed(result, eax), instr);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00001163}
1164
1165
yangguo@chromium.org154ff992012-03-13 08:09:54 +00001166LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1167 LOperand* receiver = UseRegister(instr->receiver());
1168 LOperand* function = UseRegisterAtStart(instr->function());
1169 LOperand* temp = TempRegister();
1170 LWrapReceiver* result =
1171 new(zone()) LWrapReceiver(receiver, function, temp);
1172 return AssignEnvironment(DefineSameAsFirst(result));
1173}
1174
1175
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001176LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1177 LOperand* function = UseFixed(instr->function(), edi);
1178 LOperand* receiver = UseFixed(instr->receiver(), eax);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001179 LOperand* length = UseFixed(instr->length(), ebx);
1180 LOperand* elements = UseFixed(instr->elements(), ecx);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001181 LApplyArguments* result = new(zone()) LApplyArguments(function,
1182 receiver,
1183 length,
yangguo@chromium.org154ff992012-03-13 08:09:54 +00001184 elements);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001185 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1186}
1187
1188
1189LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001190 LOperand* argument = UseAny(instr->argument());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001191 return new(zone()) LPushArgument(argument);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001192}
1193
1194
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001195LInstruction* LChunkBuilder::DoStoreCodeEntry(
1196 HStoreCodeEntry* store_code_entry) {
1197 LOperand* function = UseRegister(store_code_entry->function());
1198 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1199 return new(zone()) LStoreCodeEntry(function, code_object);
1200}
1201
1202
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001203LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1204 HInnerAllocatedObject* inner_object) {
1205 LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
1206 LInnerAllocatedObject* result =
1207 new(zone()) LInnerAllocatedObject(base_object);
1208 return DefineAsRegister(result);
1209}
1210
1211
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001212LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001213 return instr->HasNoUses()
1214 ? NULL
1215 : DefineAsRegister(new(zone()) LThisFunction);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001216}
1217
1218
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001219LInstruction* LChunkBuilder::DoContext(HContext* instr) {
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001220 if (instr->HasNoUses()) return NULL;
1221
1222 if (info()->IsStub()) {
1223 return DefineFixed(new(zone()) LContext, esi);
1224 }
1225
1226 return DefineAsRegister(new(zone()) LContext);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001227}
1228
1229
1230LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1231 LOperand* context = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001232 return DefineAsRegister(new(zone()) LOuterContext(context));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001233}
1234
1235
yangguo@chromium.org56454712012-02-16 15:33:53 +00001236LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1237 LOperand* context = UseFixed(instr->context(), esi);
1238 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
1239}
1240
1241
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001242LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001243 LOperand* context = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001244 return DefineAsRegister(new(zone()) LGlobalObject(context));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001245}
1246
1247
1248LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001249 LOperand* global_object = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001250 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001251}
1252
1253
1254LInstruction* LChunkBuilder::DoCallConstantFunction(
1255 HCallConstantFunction* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001256 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001257}
1258
1259
danno@chromium.org160a7b02011-04-18 15:51:38 +00001260LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1261 LOperand* context = UseFixed(instr->context(), esi);
1262 LOperand* function = UseFixed(instr->function(), edi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001263 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001264 return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1265}
1266
1267
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001268LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001269 switch (instr->op()) {
1270 case kMathFloor: return DoMathFloor(instr);
1271 case kMathRound: return DoMathRound(instr);
1272 case kMathAbs: return DoMathAbs(instr);
1273 case kMathLog: return DoMathLog(instr);
1274 case kMathSin: return DoMathSin(instr);
1275 case kMathCos: return DoMathCos(instr);
1276 case kMathTan: return DoMathTan(instr);
1277 case kMathExp: return DoMathExp(instr);
1278 case kMathSqrt: return DoMathSqrt(instr);
1279 case kMathPowHalf: return DoMathPowHalf(instr);
1280 default:
1281 UNREACHABLE();
1282 return NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001283 }
1284}
1285
1286
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001287LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1288 LOperand* input = UseRegisterAtStart(instr->value());
1289 LMathFloor* result = new(zone()) LMathFloor(input);
1290 return AssignEnvironment(DefineAsRegister(result));
1291}
1292
1293
1294LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001295 LOperand* input = UseRegister(instr->value());
1296 LOperand* temp = FixedTemp(xmm4);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001297 LMathRound* result = new(zone()) LMathRound(input, temp);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001298 return AssignEnvironment(DefineAsRegister(result));
1299}
1300
1301
1302LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1303 LOperand* context = UseAny(instr->context()); // Deferred use.
1304 LOperand* input = UseRegisterAtStart(instr->value());
1305 LMathAbs* result = new(zone()) LMathAbs(context, input);
1306 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1307}
1308
1309
1310LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1311 ASSERT(instr->representation().IsDouble());
1312 ASSERT(instr->value()->representation().IsDouble());
1313 LOperand* input = UseRegisterAtStart(instr->value());
1314 LMathLog* result = new(zone()) LMathLog(input);
1315 return DefineSameAsFirst(result);
1316}
1317
1318
1319LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1320 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1321 LMathSin* result = new(zone()) LMathSin(input);
1322 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1323}
1324
1325
1326LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1327 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1328 LMathCos* result = new(zone()) LMathCos(input);
1329 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1330}
1331
1332
1333LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
1334 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1335 LMathTan* result = new(zone()) LMathTan(input);
1336 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1337}
1338
1339
1340LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1341 ASSERT(instr->representation().IsDouble());
1342 ASSERT(instr->value()->representation().IsDouble());
1343 LOperand* value = UseTempRegister(instr->value());
1344 LOperand* temp1 = TempRegister();
1345 LOperand* temp2 = TempRegister();
1346 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1347 return DefineAsRegister(result);
1348}
1349
1350
1351LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1352 LOperand* input = UseRegisterAtStart(instr->value());
1353 LMathSqrt* result = new(zone()) LMathSqrt(input);
1354 return DefineSameAsFirst(result);
1355}
1356
1357
1358LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001359 LOperand* input = UseRegisterAtStart(instr->value());
1360 LOperand* temp = TempRegister();
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001361 LMathPowHalf* result = new(zone()) LMathPowHalf(input, temp);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001362 return DefineSameAsFirst(result);
1363}
1364
1365
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001366LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1367 ASSERT(instr->key()->representation().IsTagged());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001368 LOperand* context = UseFixed(instr->context(), esi);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001369 LOperand* key = UseFixed(instr->key(), ecx);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001370 LCallKeyed* result = new(zone()) LCallKeyed(context, key);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001371 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001372}
1373
1374
1375LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001376 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001377 LCallNamed* result = new(zone()) LCallNamed(context);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001378 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001379}
1380
1381
1382LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001383 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001384 LCallGlobal* result = new(zone()) LCallGlobal(context);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001385 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001386}
1387
1388
1389LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001390 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001391}
1392
1393
1394LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001395 LOperand* context = UseFixed(instr->context(), esi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001396 LOperand* constructor = UseFixed(instr->constructor(), edi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001397 LCallNew* result = new(zone()) LCallNew(context, constructor);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001398 return MarkAsCall(DefineFixed(result, eax), instr);
1399}
1400
1401
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001402LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001403 LOperand* context = UseFixed(instr->context(), esi);
1404 LOperand* constructor = UseFixed(instr->constructor(), edi);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001405 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
1406 return MarkAsCall(DefineFixed(result, eax), instr);
1407}
1408
1409
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001410LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001411 LOperand* context = UseFixed(instr->context(), esi);
danno@chromium.orgc612e022011-11-10 11:38:15 +00001412 LOperand* function = UseFixed(instr->function(), edi);
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001413 LCallFunction* call = new(zone()) LCallFunction(context, function);
1414 LInstruction* result = DefineFixed(call, eax);
1415 if (instr->IsTailCall()) return result;
1416 return MarkAsCall(result, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001417}
1418
1419
1420LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001421 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001422 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001423}
1424
1425
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001426LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1427 return DoShift(Token::ROR, instr);
1428}
1429
1430
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001431LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1432 return DoShift(Token::SHR, instr);
1433}
1434
1435
1436LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1437 return DoShift(Token::SAR, instr);
1438}
1439
1440
1441LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1442 return DoShift(Token::SHL, instr);
1443}
1444
1445
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001446LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001447 if (instr->representation().IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001448 ASSERT(instr->left()->representation().Equals(instr->representation()));
1449 ASSERT(instr->right()->representation().Equals(instr->representation()));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001450 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001451
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001452 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1453 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001454 return DefineSameAsFirst(new(zone()) LBitI(left, right));
1455 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001456 return DoArithmeticT(instr->op(), instr);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001457 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001458}
1459
1460
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001461LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001462 if (instr->representation().IsSmiOrInteger32()) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001463 ASSERT(instr->left()->representation().Equals(instr->representation()));
1464 ASSERT(instr->right()->representation().Equals(instr->representation()));
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001465 if (instr->HasPowerOf2Divisor()) {
1466 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1467 LOperand* value = UseRegisterAtStart(instr->left());
1468 LDivI* div =
1469 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1470 return AssignEnvironment(DefineSameAsFirst(div));
1471 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001472 // The temporary operand is necessary to ensure that right is not allocated
1473 // into edx.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001474 LOperand* temp = FixedTemp(edx);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001475 LOperand* dividend = UseFixed(instr->left(), eax);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001476 LOperand* divisor = UseRegister(instr->right());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001477 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001478 return AssignEnvironment(DefineFixed(result, eax));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001479 } else if (instr->representation().IsDouble()) {
1480 return DoArithmeticD(Token::DIV, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001481 } else {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001482 return DoArithmeticT(Token::DIV, instr);
1483 }
1484}
1485
1486
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001487HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1488 if (divisor->IsConstant() &&
1489 HConstant::cast(divisor)->HasInteger32Value()) {
1490 HConstant* constant_val = HConstant::cast(divisor);
1491 return constant_val->CopyToRepresentation(Representation::Integer32(),
1492 divisor->block()->zone());
1493 }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001494 // A value with an integer representation does not need to be transformed.
1495 if (divisor->representation().IsInteger32()) {
1496 return divisor;
1497 // A change from an integer32 can be replaced by the integer32 value.
1498 } else if (divisor->IsChange() &&
1499 HChange::cast(divisor)->from().IsInteger32()) {
1500 return HChange::cast(divisor)->value();
1501 }
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001502 return NULL;
1503}
1504
1505
1506LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1507 HValue* right = instr->right();
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001508 if (!right->IsConstant()) {
1509 ASSERT(right->representation().IsInteger32());
1510 // The temporary operand is necessary to ensure that right is not allocated
1511 // into edx.
1512 LOperand* temp = FixedTemp(edx);
1513 LOperand* dividend = UseFixed(instr->left(), eax);
1514 LOperand* divisor = UseRegister(instr->right());
1515 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp);
1516 return AssignEnvironment(DefineFixed(flooring_div, eax));
1517 }
1518
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001519 ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value());
1520 LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
1521 int32_t divisor_si = HConstant::cast(right)->Integer32Value();
1522 if (divisor_si == 0) {
1523 LOperand* dividend = UseRegister(instr->left());
1524 return AssignEnvironment(DefineAsRegister(
1525 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
1526 } else if (IsPowerOf2(abs(divisor_si))) {
1527 // use dividend as temp if divisor < 0 && divisor != -1
1528 LOperand* dividend = divisor_si < -1 ? UseTempRegister(instr->left()) :
1529 UseRegisterAtStart(instr->left());
1530 LInstruction* result = DefineAsRegister(
1531 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
1532 return divisor_si < 0 ? AssignEnvironment(result) : result;
1533 } else {
1534 // needs edx:eax, plus a temp
1535 LOperand* dividend = UseFixed(instr->left(), eax);
1536 LOperand* temp = TempRegister();
1537 LInstruction* result = DefineFixed(
1538 new(zone()) LMathFloorOfDiv(dividend, divisor, temp), edx);
1539 return divisor_si < 0 ? AssignEnvironment(result) : result;
1540 }
1541}
1542
1543
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001544LInstruction* LChunkBuilder::DoMod(HMod* instr) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001545 HValue* left = instr->left();
1546 HValue* right = instr->right();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001547 if (instr->representation().IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001548 ASSERT(instr->left()->representation().Equals(instr->representation()));
1549 ASSERT(instr->right()->representation().Equals(instr->representation()));
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001550
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001551 if (instr->HasPowerOf2Divisor()) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001552 ASSERT(!right->CanBeZero());
1553 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1554 UseOrConstant(right),
1555 NULL);
1556 LInstruction* result = DefineSameAsFirst(mod);
1557 return (left->CanBeNegative() &&
1558 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1559 ? AssignEnvironment(result)
1560 : result;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001561 } else if (instr->fixed_right_arg().has_value) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001562 LModI* mod = new(zone()) LModI(UseRegister(left),
1563 UseRegisterAtStart(right),
1564 NULL);
1565 return AssignEnvironment(DefineSameAsFirst(mod));
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001566 } else {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001567 // The temporary operand is necessary to ensure that right is not
1568 // allocated into edx.
1569 LModI* mod = new(zone()) LModI(UseFixed(left, eax),
1570 UseRegister(right),
1571 FixedTemp(edx));
1572 LInstruction* result = DefineFixed(mod, edx);
1573 return (right->CanBeZero() ||
1574 (left->RangeCanInclude(kMinInt) &&
1575 right->RangeCanInclude(-1) &&
1576 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1577 (left->CanBeNegative() &&
1578 instr->CanBeZero() &&
1579 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1580 ? AssignEnvironment(result)
1581 : result;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001582 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001583 } else if (instr->representation().IsDouble()) {
1584 return DoArithmeticD(Token::MOD, instr);
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +00001585 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001586 return DoArithmeticT(Token::MOD, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001587 }
1588}
1589
1590
1591LInstruction* LChunkBuilder::DoMul(HMul* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001592 if (instr->representation().IsSmiOrInteger32()) {
1593 ASSERT(instr->left()->representation().Equals(instr->representation()));
1594 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001595 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1596 LOperand* right = UseOrConstant(instr->BetterRightOperand());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001597 LOperand* temp = NULL;
1598 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1599 temp = TempRegister();
1600 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001601 LMulI* mul = new(zone()) LMulI(left, right, temp);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001602 if (instr->CheckFlag(HValue::kCanOverflow) ||
1603 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1604 AssignEnvironment(mul);
1605 }
1606 return DefineSameAsFirst(mul);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001607 } else if (instr->representation().IsDouble()) {
danno@chromium.org169691d2013-07-15 08:01:13 +00001608 return DoArithmeticD(Token::MUL, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001609 } else {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001610 return DoArithmeticT(Token::MUL, instr);
1611 }
1612}
1613
1614
1615LInstruction* LChunkBuilder::DoSub(HSub* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001616 if (instr->representation().IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001617 ASSERT(instr->left()->representation().Equals(instr->representation()));
1618 ASSERT(instr->right()->representation().Equals(instr->representation()));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001619 LOperand* left = UseRegisterAtStart(instr->left());
1620 LOperand* right = UseOrConstantAtStart(instr->right());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001621 LSubI* sub = new(zone()) LSubI(left, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001622 LInstruction* result = DefineSameAsFirst(sub);
1623 if (instr->CheckFlag(HValue::kCanOverflow)) {
1624 result = AssignEnvironment(result);
1625 }
1626 return result;
1627 } else if (instr->representation().IsDouble()) {
1628 return DoArithmeticD(Token::SUB, instr);
1629 } else {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001630 return DoArithmeticT(Token::SUB, instr);
1631 }
1632}
1633
1634
1635LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001636 if (instr->representation().IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001637 ASSERT(instr->left()->representation().Equals(instr->representation()));
1638 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001639 // Check to see if it would be advantageous to use an lea instruction rather
1640 // than an add. This is the case when no overflow check is needed and there
1641 // are multiple uses of the add's inputs, so using a 3-register add will
1642 // preserve all input values for later uses.
1643 bool use_lea = LAddI::UseLea(instr);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001644 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1645 HValue* right_candidate = instr->BetterRightOperand();
1646 LOperand* right = use_lea
1647 ? UseRegisterOrConstantAtStart(right_candidate)
1648 : UseOrConstantAtStart(right_candidate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001649 LAddI* add = new(zone()) LAddI(left, right);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001650 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1651 LInstruction* result = use_lea
1652 ? DefineAsRegister(add)
1653 : DefineSameAsFirst(add);
1654 if (can_overflow) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001655 result = AssignEnvironment(result);
1656 }
1657 return result;
1658 } else if (instr->representation().IsDouble()) {
1659 return DoArithmeticD(Token::ADD, instr);
1660 } else {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001661 return DoArithmeticT(Token::ADD, instr);
1662 }
1663}
1664
1665
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001666LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1667 LOperand* left = NULL;
1668 LOperand* right = NULL;
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001669 if (instr->representation().IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001670 ASSERT(instr->left()->representation().Equals(instr->representation()));
1671 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001672 left = UseRegisterAtStart(instr->BetterLeftOperand());
1673 right = UseOrConstantAtStart(instr->BetterRightOperand());
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001674 } else {
1675 ASSERT(instr->representation().IsDouble());
1676 ASSERT(instr->left()->representation().IsDouble());
1677 ASSERT(instr->right()->representation().IsDouble());
1678 left = UseRegisterAtStart(instr->left());
1679 right = UseRegisterAtStart(instr->right());
1680 }
1681 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right);
1682 return DefineSameAsFirst(minmax);
1683}
1684
1685
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001686LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1687 ASSERT(instr->representation().IsDouble());
1688 // We call a C function for double power. It can't trigger a GC.
1689 // We need to use fixed result register for the call.
1690 Representation exponent_type = instr->right()->representation();
1691 ASSERT(instr->left()->representation().IsDouble());
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001692 LOperand* left = UseFixedDouble(instr->left(), xmm2);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001693 LOperand* right = exponent_type.IsDouble() ?
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001694 UseFixedDouble(instr->right(), xmm1) :
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001695 UseFixed(instr->right(), eax);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001696 LPower* result = new(zone()) LPower(left, right);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001697 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
1698 CAN_DEOPTIMIZE_EAGERLY);
1699}
1700
1701
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001702LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1703 ASSERT(instr->representation().IsDouble());
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001704 ASSERT(instr->global_object()->representation().IsTagged());
1705 LOperand* global_object = UseTempRegister(instr->global_object());
1706 LOperand* scratch = TempRegister();
1707 LOperand* scratch2 = TempRegister();
1708 LOperand* scratch3 = TempRegister();
1709 LRandom* result = new(zone()) LRandom(
1710 global_object, scratch, scratch2, scratch3);
1711 return DefineFixedDouble(result, xmm1);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001712}
1713
1714
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001715LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001716 ASSERT(instr->left()->representation().IsSmiOrTagged());
1717 ASSERT(instr->right()->representation().IsSmiOrTagged());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001718 LOperand* context = UseFixed(instr->context(), esi);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001719 LOperand* left = UseFixed(instr->left(), edx);
1720 LOperand* right = UseFixed(instr->right(), eax);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001721 LCmpT* result = new(zone()) LCmpT(context, left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001722 return MarkAsCall(DefineFixed(result, eax), instr);
1723}
1724
1725
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001726LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1727 HCompareNumericAndBranch* instr) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001728 Representation r = instr->representation();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001729 if (r.IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001730 ASSERT(instr->left()->representation().Equals(r));
1731 ASSERT(instr->right()->representation().Equals(r));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001732 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001733 LOperand* right = UseOrConstantAtStart(instr->right());
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001734 return new(zone()) LCompareNumericAndBranch(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001735 } else {
1736 ASSERT(r.IsDouble());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001737 ASSERT(instr->left()->representation().IsDouble());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001738 ASSERT(instr->right()->representation().IsDouble());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001739 LOperand* left;
1740 LOperand* right;
jkummerow@chromium.org4000f222013-10-29 14:58:08 +00001741 if (CanBeImmediateConstant(instr->left()) &&
1742 CanBeImmediateConstant(instr->right())) {
1743 // The code generator requires either both inputs to be constant
1744 // operands, or neither.
1745 left = UseConstant(instr->left());
1746 right = UseConstant(instr->right());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001747 } else {
1748 left = UseRegisterAtStart(instr->left());
1749 right = UseRegisterAtStart(instr->right());
1750 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001751 return new(zone()) LCompareNumericAndBranch(left, right);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001752 }
1753}
1754
1755
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001756LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1757 HCompareObjectEqAndBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001758 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1759 if (goto_instr != NULL) return goto_instr;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001760 LOperand* left = UseRegisterAtStart(instr->left());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001761 LOperand* right = UseOrConstantAtStart(instr->right());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001762 return new(zone()) LCmpObjectEqAndBranch(left, right);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001763}
1764
1765
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001766LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1767 HCompareHoleAndBranch* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001768 LOperand* value = UseRegisterAtStart(instr->value());
1769 return new(zone()) LCmpHoleAndBranch(value);
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001770}
1771
1772
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001773LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1774 HCompareMinusZeroAndBranch* instr) {
1775 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1776 if (goto_instr != NULL) return goto_instr;
1777 LOperand* value = UseRegister(instr->value());
1778 LOperand* scratch = TempRegister();
1779 return new(zone()) LCompareMinusZeroAndBranch(value, scratch);
1780}
1781
1782
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001783LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001784 ASSERT(instr->value()->representation().IsSmiOrTagged());
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001785 LOperand* temp = TempRegister();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001786 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001787}
1788
1789
erikcorry0ad885c2011-11-21 13:51:57 +00001790LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1791 ASSERT(instr->value()->representation().IsTagged());
1792 LOperand* temp = TempRegister();
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001793 return new(zone()) LIsStringAndBranch(UseRegister(instr->value()), temp);
erikcorry0ad885c2011-11-21 13:51:57 +00001794}
1795
1796
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001797LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001798 ASSERT(instr->value()->representation().IsTagged());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001799 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001800}
1801
1802
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001803LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1804 HIsUndetectableAndBranch* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001805 ASSERT(instr->value()->representation().IsTagged());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001806 return new(zone()) LIsUndetectableAndBranch(
1807 UseRegisterAtStart(instr->value()), TempRegister());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001808}
1809
1810
erikcorry0ad885c2011-11-21 13:51:57 +00001811LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1812 HStringCompareAndBranch* instr) {
1813 ASSERT(instr->left()->representation().IsTagged());
1814 ASSERT(instr->right()->representation().IsTagged());
1815 LOperand* context = UseFixed(instr->context(), esi);
1816 LOperand* left = UseFixed(instr->left(), edx);
1817 LOperand* right = UseFixed(instr->right(), eax);
1818
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001819 LStringCompareAndBranch* result = new(zone())
erikcorry0ad885c2011-11-21 13:51:57 +00001820 LStringCompareAndBranch(context, left, right);
1821
1822 return MarkAsCall(result, instr);
1823}
1824
1825
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001826LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1827 HHasInstanceTypeAndBranch* instr) {
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001828 ASSERT(instr->value()->representation().IsTagged());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001829 return new(zone()) LHasInstanceTypeAndBranch(
1830 UseRegisterAtStart(instr->value()),
1831 TempRegister());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001832}
1833
1834
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001835LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1836 HGetCachedArrayIndex* instr) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001837 ASSERT(instr->value()->representation().IsTagged());
1838 LOperand* value = UseRegisterAtStart(instr->value());
1839
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001840 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001841}
1842
1843
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001844LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1845 HHasCachedArrayIndexAndBranch* instr) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001846 ASSERT(instr->value()->representation().IsTagged());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001847 return new(zone()) LHasCachedArrayIndexAndBranch(
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001848 UseRegisterAtStart(instr->value()));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001849}
1850
1851
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001852LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1853 HClassOfTestAndBranch* instr) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001854 ASSERT(instr->value()->representation().IsTagged());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001855 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1856 TempRegister(),
1857 TempRegister());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001858}
1859
1860
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001861LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1862 LOperand* map = UseRegisterAtStart(instr->value());
1863 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1864}
1865
1866
whesse@chromium.org7b260152011-06-20 15:33:18 +00001867LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1868 LOperand* object = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001869 return DefineAsRegister(new(zone()) LElementsKind(object));
whesse@chromium.org7b260152011-06-20 15:33:18 +00001870}
1871
1872
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001873LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1874 LOperand* object = UseRegister(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001875 LValueOf* result = new(zone()) LValueOf(object, TempRegister());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001876 return DefineSameAsFirst(result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001877}
1878
1879
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001880LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1881 LOperand* date = UseFixed(instr->value(), eax);
1882 LDateField* result =
1883 new(zone()) LDateField(date, FixedTemp(ecx), instr->index());
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001884 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001885}
1886
1887
machenbach@chromium.orge8412be2013-11-08 10:23:52 +00001888LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1889 LOperand* string = UseRegisterAtStart(instr->string());
1890 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1891 return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
1892}
1893
1894
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001895LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +00001896 LOperand* string = UseRegisterAtStart(instr->string());
1897 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1898 LOperand* value = (instr->encoding() == String::ONE_BYTE_ENCODING)
1899 ? UseFixedOrConstant(instr->value(), eax)
1900 : UseRegisterOrConstantAtStart(instr->value());
1901 return new(zone()) LSeqStringSetChar(string, index, value);
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001902}
1903
1904
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001905LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001906 return AssignEnvironment(new(zone()) LBoundsCheck(
danno@chromium.orgb6451162011-08-17 14:33:23 +00001907 UseRegisterOrConstantAtStart(instr->index()),
1908 UseAtStart(instr->length())));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001909}
1910
1911
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001912LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1913 HBoundsCheckBaseIndexInformation* instr) {
1914 UNREACHABLE();
1915 return NULL;
1916}
1917
1918
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00001919LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1920 // The control instruction marking the end of a block that completed
1921 // abruptly (e.g., threw an exception). There is nothing specific to do.
1922 return NULL;
1923}
1924
1925
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001926LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001927 LOperand* context = UseFixed(instr->context(), esi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001928 LOperand* value = UseFixed(instr->value(), eax);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001929 return MarkAsCall(new(zone()) LThrow(context, value), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001930}
1931
1932
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001933LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1934 return NULL;
1935}
1936
1937
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001938LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1939 // All HForceRepresentation instructions should be eliminated in the
1940 // representation change phase of Hydrogen.
1941 UNREACHABLE();
1942 return NULL;
1943}
1944
1945
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001946LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1947 Representation from = instr->from();
1948 Representation to = instr->to();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001949 if (from.IsSmi()) {
1950 if (to.IsTagged()) {
1951 LOperand* value = UseRegister(instr->value());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001952 return DefineSameAsFirst(new(zone()) LDummyUse(value));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001953 }
1954 from = Representation::Tagged();
1955 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001956 // Only mark conversions that might need to allocate as calling rather than
1957 // all changes. This makes simple, non-allocating conversion not have to force
1958 // building a stack frame.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001959 if (from.IsTagged()) {
1960 if (to.IsDouble()) {
1961 LOperand* value = UseRegister(instr->value());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001962 // Temp register only necessary for minus zero check.
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001963 LOperand* temp = TempRegister();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001964 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
danno@chromium.org169691d2013-07-15 08:01:13 +00001965 return AssignEnvironment(DefineAsRegister(res));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001966 } else if (to.IsSmi()) {
1967 HValue* val = instr->value();
1968 LOperand* value = UseRegister(val);
1969 if (val->type().IsSmi()) {
1970 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1971 }
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001972 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001973 } else {
1974 ASSERT(to.IsInteger32());
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001975 HValue* val = instr->value();
1976 if (val->type().IsSmi() || val->representation().IsSmi()) {
1977 LOperand* value = UseRegister(val);
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001978 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001979 } else {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001980 bool truncating = instr->CanTruncateToInt32();
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +00001981 LOperand* xmm_temp =
1982 (CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating)
1983 ? FixedTemp(xmm1) : NULL;
1984 LTaggedToI* res = new(zone()) LTaggedToI(UseRegister(val), xmm_temp);
1985 return AssignEnvironment(DefineSameAsFirst(res));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001986 }
1987 }
1988 } else if (from.IsDouble()) {
1989 if (to.IsTagged()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001990 info()->MarkAsDeferredCalling();
danno@chromium.org169691d2013-07-15 08:01:13 +00001991 LOperand* value = UseRegisterAtStart(instr->value());
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +00001992 LOperand* temp = FLAG_inline_new ? TempRegister() : NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001993
1994 // Make sure that temp and result_temp are different registers.
1995 LUnallocated* result_temp = TempRegister();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001996 LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001997 return AssignPointerMap(Define(result, result_temp));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001998 } else if (to.IsSmi()) {
1999 LOperand* value = UseRegister(instr->value());
2000 return AssignEnvironment(
2001 DefineAsRegister(new(zone()) LDoubleToSmi(value)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002002 } else {
2003 ASSERT(to.IsInteger32());
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00002004 bool truncating = instr->CanTruncateToInt32();
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +00002005 bool needs_temp = CpuFeatures::IsSafeForSnapshot(SSE2) && !truncating;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002006 LOperand* value = needs_temp ?
2007 UseTempRegister(instr->value()) : UseRegister(instr->value());
2008 LOperand* temp = needs_temp ? TempRegister() : NULL;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002009 return AssignEnvironment(
2010 DefineAsRegister(new(zone()) LDoubleToI(value, temp)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002011 }
2012 } else if (from.IsInteger32()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002013 info()->MarkAsDeferredCalling();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002014 if (to.IsTagged()) {
2015 HValue* val = instr->value();
2016 LOperand* value = UseRegister(val);
2017 if (val->HasRange() && val->range()->IsInSmiRange()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002018 return DefineSameAsFirst(new(zone()) LSmiTag(value));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002019 } else if (val->CheckFlag(HInstruction::kUint32)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002020 LOperand* temp = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1)
2021 : NULL;
2022 LNumberTagU* result = new(zone()) LNumberTagU(value, temp);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002023 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002024 } else {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002025 LNumberTagI* result = new(zone()) LNumberTagI(value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002026 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
2027 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002028 } else if (to.IsSmi()) {
2029 HValue* val = instr->value();
2030 LOperand* value = UseRegister(val);
machenbach@chromium.orged29eb22013-10-31 13:30:00 +00002031 LInstruction* result = val->CheckFlag(HInstruction::kUint32)
2032 ? DefineSameAsFirst(new(zone()) LUint32ToSmi(value))
2033 : DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002034 if (val->HasRange() && val->range()->IsInSmiRange()) {
2035 return result;
2036 }
2037 return AssignEnvironment(result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002038 } else {
2039 ASSERT(to.IsDouble());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00002040 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
2041 LOperand* temp = FixedTemp(xmm1);
2042 return DefineAsRegister(
2043 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
2044 } else {
2045 return DefineAsRegister(
2046 new(zone()) LInteger32ToDouble(Use(instr->value())));
2047 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002048 }
2049 }
2050 UNREACHABLE();
2051 return NULL;
2052}
2053
2054
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002055LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002056 LOperand* value = UseAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002057 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002058}
2059
2060
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002061LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
2062 LOperand* value = UseRegisterAtStart(instr->value());
2063 return AssignEnvironment(new(zone()) LCheckSmi(value));
2064}
2065
2066
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002067LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
2068 LOperand* value = UseRegisterAtStart(instr->value());
2069 LOperand* temp = TempRegister();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002070 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002071 return AssignEnvironment(result);
2072}
2073
2074
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00002075LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
2076 // If the object is in new space, we'll emit a global cell compare and so
2077 // want the value in a register. If the object gets promoted before we
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002078 // emit code, we will still get the register but will do an immediate
2079 // compare instead of the cell compare. This is safe.
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00002080 LOperand* value = instr->object_in_new_space()
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002081 ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value());
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00002082 return AssignEnvironment(new(zone()) LCheckValue(value));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002083}
2084
2085
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002086LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00002087 LOperand* value = NULL;
danno@chromium.org59400602013-08-13 17:09:37 +00002088 if (!instr->CanOmitMapChecks()) {
2089 value = UseRegisterAtStart(instr->value());
2090 if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
2091 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002092 LCheckMaps* result = new(zone()) LCheckMaps(value);
danno@chromium.org59400602013-08-13 17:09:37 +00002093 if (!instr->CanOmitMapChecks()) {
2094 AssignEnvironment(result);
2095 if (instr->has_migration_target()) return AssignPointerMap(result);
2096 }
2097 return result;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002098}
2099
2100
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002101LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
2102 HValue* value = instr->value();
2103 Representation input_rep = value->representation();
2104 if (input_rep.IsDouble()) {
2105 LOperand* reg = UseRegister(value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002106 return DefineFixed(new(zone()) LClampDToUint8(reg), eax);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002107 } else if (input_rep.IsInteger32()) {
2108 LOperand* reg = UseFixed(value, eax);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002109 return DefineFixed(new(zone()) LClampIToUint8(reg), eax);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002110 } else {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002111 ASSERT(input_rep.IsSmiOrTagged());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002112 if (CpuFeatures::IsSupported(SSE2)) {
2113 LOperand* reg = UseFixed(value, eax);
2114 // Register allocator doesn't (yet) support allocation of double
2115 // temps. Reserve xmm1 explicitly.
2116 LOperand* temp = FixedTemp(xmm1);
2117 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, temp);
2118 return AssignEnvironment(DefineFixed(result, eax));
2119 } else {
2120 LOperand* value = UseRegister(instr->value());
2121 LClampTToUint8NoSSE2* res =
2122 new(zone()) LClampTToUint8NoSSE2(value, TempRegister(),
2123 TempRegister(), TempRegister());
2124 return AssignEnvironment(DefineFixed(res, ecx));
2125 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002126 }
2127}
2128
2129
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002130LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002131 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), esi) : NULL;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00002132 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002133 return new(zone()) LReturn(
2134 UseFixed(instr->value(), eax), context, parameter_count);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002135}
2136
2137
2138LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2139 Representation r = instr->representation();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002140 if (r.IsSmi()) {
2141 return DefineAsRegister(new(zone()) LConstantS);
2142 } else if (r.IsInteger32()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002143 return DefineAsRegister(new(zone()) LConstantI);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002144 } else if (r.IsDouble()) {
2145 double value = instr->DoubleValue();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002146 bool value_is_zero = BitCast<uint64_t, double>(value) == 0;
danno@chromium.org169691d2013-07-15 08:01:13 +00002147 LOperand* temp = value_is_zero ? NULL : TempRegister();
2148 return DefineAsRegister(new(zone()) LConstantD(temp));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002149 } else if (r.IsExternal()) {
2150 return DefineAsRegister(new(zone()) LConstantE);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002151 } else if (r.IsTagged()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002152 return DefineAsRegister(new(zone()) LConstantT);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002153 } else {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002154 UNREACHABLE();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002155 return NULL;
2156 }
2157}
2158
2159
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002160LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002161 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002162 return instr->RequiresHoleCheck()
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002163 ? AssignEnvironment(DefineAsRegister(result))
2164 : DefineAsRegister(result);
2165}
2166
2167
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002168LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2169 LOperand* context = UseFixed(instr->context(), esi);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002170 LOperand* global_object = UseFixed(instr->global_object(), edx);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002171 LLoadGlobalGeneric* result =
2172 new(zone()) LLoadGlobalGeneric(context, global_object);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002173 return MarkAsCall(DefineFixed(result, eax), instr);
2174}
2175
2176
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002177LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
2178 LStoreGlobalCell* result =
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00002179 new(zone()) LStoreGlobalCell(UseRegister(instr->value()));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002180 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002181}
2182
2183
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002184LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
2185 LOperand* context = UseFixed(instr->context(), esi);
2186 LOperand* global_object = UseFixed(instr->global_object(), edx);
2187 LOperand* value = UseFixed(instr->value(), eax);
2188 LStoreGlobalGeneric* result =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002189 new(zone()) LStoreGlobalGeneric(context, global_object, value);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002190 return MarkAsCall(result, instr);
2191}
2192
2193
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002194LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002195 LOperand* context = UseRegisterAtStart(instr->value());
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002196 LInstruction* result =
2197 DefineAsRegister(new(zone()) LLoadContextSlot(context));
2198 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002199}
2200
2201
2202LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002203 LOperand* value;
2204 LOperand* temp;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002205 LOperand* context = UseRegister(instr->context());
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002206 if (instr->NeedsWriteBarrier()) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002207 value = UseTempRegister(instr->value());
2208 temp = TempRegister();
2209 } else {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002210 value = UseRegister(instr->value());
2211 temp = NULL;
2212 }
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002213 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
2214 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002215}
2216
2217
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002218LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002219 LOperand* obj = (instr->access().IsExternalMemory() &&
2220 instr->access().offset() == 0)
2221 ? UseRegisterOrConstantAtStart(instr->object())
2222 : UseRegisterAtStart(instr->object());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002223 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002224}
2225
2226
2227LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002228 LOperand* context = UseFixed(instr->context(), esi);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002229 LOperand* object = UseFixed(instr->object(), edx);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002230 LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002231 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002232}
2233
2234
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002235LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2236 HLoadFunctionPrototype* instr) {
2237 return AssignEnvironment(DefineAsRegister(
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002238 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()),
2239 TempRegister())));
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002240}
2241
2242
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002243LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2244 return DefineAsRegister(new(zone()) LLoadRoot);
2245}
2246
2247
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002248LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2249 HLoadExternalArrayPointer* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002250 LOperand* input = UseRegisterAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002251 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002252}
2253
2254
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002255LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002256 ASSERT(instr->key()->representation().IsSmiOrInteger32());
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002257 ElementsKind elements_kind = instr->elements_kind();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002258 bool clobbers_key = ExternalArrayOpRequiresTemp(
2259 instr->key()->representation(), elements_kind);
2260 LOperand* key = clobbers_key
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002261 ? UseTempRegister(instr->key())
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002262 : UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002263 LLoadKeyed* result = NULL;
yangguo@chromium.org304cc332012-07-24 07:59:48 +00002264
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002265 if (!instr->is_external()) {
2266 LOperand* obj = UseRegisterAtStart(instr->elements());
2267 result = new(zone()) LLoadKeyed(obj, key);
2268 } else {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002269 ASSERT(
2270 (instr->representation().IsInteger32() &&
2271 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2272 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2273 (instr->representation().IsDouble() &&
2274 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2275 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002276 LOperand* external_pointer = UseRegister(instr->elements());
2277 result = new(zone()) LLoadKeyed(external_pointer, key);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002278 }
2279
2280 DefineAsRegister(result);
2281 bool can_deoptimize = instr->RequiresHoleCheck() ||
2282 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002283 // An unsigned int array load might overflow and cause a deopt, make sure it
2284 // has an environment.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002285 return can_deoptimize ? AssignEnvironment(result) : result;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002286}
2287
2288
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002289LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002290 LOperand* context = UseFixed(instr->context(), esi);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002291 LOperand* object = UseFixed(instr->object(), edx);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002292 LOperand* key = UseFixed(instr->key(), ecx);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002293
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002294 LLoadKeyedGeneric* result =
2295 new(zone()) LLoadKeyedGeneric(context, object, key);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002296 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002297}
2298
2299
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002300LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
2301 ElementsKind elements_kind = instr->elements_kind();
2302
2303 // Determine if we need a byte register in this case for the value.
2304 bool val_is_fixed_register =
2305 elements_kind == EXTERNAL_BYTE_ELEMENTS ||
2306 elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
2307 elements_kind == EXTERNAL_PIXEL_ELEMENTS;
2308 if (val_is_fixed_register) {
2309 return UseFixed(instr->value(), eax);
2310 }
2311
2312 if (!CpuFeatures::IsSafeForSnapshot(SSE2) &&
2313 IsDoubleOrFloatElementsKind(elements_kind)) {
2314 return UseRegisterAtStart(instr->value());
2315 }
2316
2317 return UseRegister(instr->value());
2318}
2319
2320
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002321LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002322 if (!instr->is_external()) {
2323 ASSERT(instr->elements()->representation().IsTagged());
2324 ASSERT(instr->key()->representation().IsInteger32() ||
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002325 instr->key()->representation().IsSmi());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002326
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002327 if (instr->value()->representation().IsDouble()) {
2328 LOperand* object = UseRegisterAtStart(instr->elements());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002329 LOperand* val = NULL;
danno@chromium.org169691d2013-07-15 08:01:13 +00002330 val = UseRegisterAtStart(instr->value());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002331 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002332 return new(zone()) LStoreKeyed(object, key, val);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002333 } else {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002334 ASSERT(instr->value()->representation().IsSmiOrTagged());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002335 bool needs_write_barrier = instr->NeedsWriteBarrier();
2336
2337 LOperand* obj = UseRegister(instr->elements());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002338 LOperand* val;
2339 LOperand* key;
2340 if (needs_write_barrier) {
2341 val = UseTempRegister(instr->value());
2342 key = UseTempRegister(instr->key());
2343 } else {
danno@chromium.orgf005df62013-04-30 16:36:45 +00002344 val = UseRegisterOrConstantAtStart(instr->value());
2345 key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002346 }
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002347 return new(zone()) LStoreKeyed(obj, key, val);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002348 }
lrn@chromium.org7516f052011-03-30 08:52:27 +00002349 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002350
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002351 ElementsKind elements_kind = instr->elements_kind();
2352 ASSERT(
2353 (instr->value()->representation().IsInteger32() &&
2354 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2355 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2356 (instr->value()->representation().IsDouble() &&
2357 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2358 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2359 ASSERT(instr->elements()->representation().IsExternal());
2360
2361 LOperand* external_pointer = UseRegister(instr->elements());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002362 LOperand* val = GetStoreKeyedValueOperand(instr);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002363 bool clobbers_key = ExternalArrayOpRequiresTemp(
2364 instr->key()->representation(), elements_kind);
2365 LOperand* key = clobbers_key
2366 ? UseTempRegister(instr->key())
2367 : UseRegisterOrConstantAtStart(instr->key());
2368 return new(zone()) LStoreKeyed(external_pointer,
2369 key,
2370 val);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002371}
2372
2373
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002374LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002375 LOperand* context = UseFixed(instr->context(), esi);
2376 LOperand* object = UseFixed(instr->object(), edx);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002377 LOperand* key = UseFixed(instr->key(), ecx);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002378 LOperand* value = UseFixed(instr->value(), eax);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002379
2380 ASSERT(instr->object()->representation().IsTagged());
2381 ASSERT(instr->key()->representation().IsTagged());
2382 ASSERT(instr->value()->representation().IsTagged());
2383
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002384 LStoreKeyedGeneric* result =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002385 new(zone()) LStoreKeyedGeneric(context, object, key, value);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002386 return MarkAsCall(result, instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002387}
2388
2389
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002390LInstruction* LChunkBuilder::DoTransitionElementsKind(
2391 HTransitionElementsKind* instr) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002392 LOperand* object = UseRegister(instr->object());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002393 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002394 LOperand* object = UseRegister(instr->object());
2395 LOperand* new_map_reg = TempRegister();
2396 LOperand* temp_reg = TempRegister();
2397 LTransitionElementsKind* result =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002398 new(zone()) LTransitionElementsKind(object, NULL,
2399 new_map_reg, temp_reg);
2400 return result;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002401 } else {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002402 LOperand* context = UseRegister(instr->context());
2403 LTransitionElementsKind* result =
2404 new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
2405 return AssignPointerMap(result);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002406 }
2407}
2408
2409
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002410LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2411 HTrapAllocationMemento* instr) {
2412 LOperand* object = UseRegister(instr->object());
2413 LOperand* temp = TempRegister();
2414 LTrapAllocationMemento* result =
2415 new(zone()) LTrapAllocationMemento(object, temp);
2416 return AssignEnvironment(result);
2417}
2418
2419
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002420LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002421 bool is_in_object = instr->access().IsInobject();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002422 bool is_external_location = instr->access().IsExternalMemory() &&
2423 instr->access().offset() == 0;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +00002424 bool needs_write_barrier = instr->NeedsWriteBarrier();
danno@chromium.org59400602013-08-13 17:09:37 +00002425 bool needs_write_barrier_for_map = instr->has_transition() &&
verwaest@chromium.org37141392012-05-31 13:27:02 +00002426 instr->NeedsWriteBarrierForMap();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002427
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002428 LOperand* obj;
2429 if (needs_write_barrier) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002430 obj = is_in_object
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002431 ? UseRegister(instr->object())
2432 : UseTempRegister(instr->object());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002433 } else if (is_external_location) {
2434 ASSERT(!is_in_object);
2435 ASSERT(!needs_write_barrier);
2436 ASSERT(!needs_write_barrier_for_map);
2437 obj = UseRegisterOrConstant(instr->object());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002438 } else {
verwaest@chromium.org37141392012-05-31 13:27:02 +00002439 obj = needs_write_barrier_for_map
2440 ? UseRegister(instr->object())
2441 : UseRegisterAtStart(instr->object());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002442 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002443
danno@chromium.orgf005df62013-04-30 16:36:45 +00002444 bool can_be_constant = instr->value()->IsConstant() &&
2445 HConstant::cast(instr->value())->NotInNewSpace() &&
2446 !(FLAG_track_double_fields && instr->field_representation().IsDouble());
2447
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002448 LOperand* val;
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002449 if (instr->field_representation().IsInteger8() ||
2450 instr->field_representation().IsUInteger8()) {
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +00002451 // mov_b requires a byte register (i.e. any of eax, ebx, ecx, edx).
2452 // Just force the value to be in eax and we're safe here.
2453 val = UseFixed(instr->value(), eax);
2454 } else if (needs_write_barrier) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002455 val = UseTempRegister(instr->value());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002456 } else if (can_be_constant) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002457 val = UseRegisterOrConstant(instr->value());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002458 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) {
2459 val = UseTempRegister(instr->value());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002460 } else if (FLAG_track_double_fields &&
2461 instr->field_representation().IsDouble()) {
danno@chromium.org169691d2013-07-15 08:01:13 +00002462 val = UseRegisterAtStart(instr->value());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002463 } else {
2464 val = UseRegister(instr->value());
2465 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002466
2467 // We only need a scratch register if we have a write barrier or we
2468 // have a store into the properties array (not in-object-property).
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002469 LOperand* temp = (!is_in_object || needs_write_barrier ||
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002470 needs_write_barrier_for_map) ? TempRegister() : NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002471
verwaest@chromium.org37141392012-05-31 13:27:02 +00002472 // We need a temporary register for write barrier of the map field.
2473 LOperand* temp_map = needs_write_barrier_for_map ? TempRegister() : NULL;
2474
danno@chromium.orgf005df62013-04-30 16:36:45 +00002475 LStoreNamedField* result =
2476 new(zone()) LStoreNamedField(obj, val, temp, temp_map);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002477 if (FLAG_track_heap_object_fields &&
2478 instr->field_representation().IsHeapObject()) {
2479 if (!instr->value()->type().IsHeapObject()) {
2480 return AssignEnvironment(result);
2481 }
danno@chromium.orgf005df62013-04-30 16:36:45 +00002482 }
2483 return result;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002484}
2485
2486
2487LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002488 LOperand* context = UseFixed(instr->context(), esi);
2489 LOperand* object = UseFixed(instr->object(), edx);
2490 LOperand* value = UseFixed(instr->value(), eax);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002491
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002492 LStoreNamedGeneric* result =
2493 new(zone()) LStoreNamedGeneric(context, object, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002494 return MarkAsCall(result, instr);
2495}
2496
2497
danno@chromium.org160a7b02011-04-18 15:51:38 +00002498LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002499 LOperand* context = UseFixed(instr->context(), esi);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002500 LOperand* left = FLAG_new_string_add
2501 ? UseFixed(instr->left(), edx)
2502 : UseOrConstantAtStart(instr->left());
2503 LOperand* right = FLAG_new_string_add
2504 ? UseFixed(instr->right(), eax)
2505 : UseOrConstantAtStart(instr->right());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002506 LStringAdd* string_add = new(zone()) LStringAdd(context, left, right);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002507 return MarkAsCall(DefineFixed(string_add, eax), instr);
danno@chromium.org160a7b02011-04-18 15:51:38 +00002508}
2509
2510
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002511LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
ricow@chromium.org4668a2c2011-08-29 10:41:00 +00002512 LOperand* string = UseTempRegister(instr->string());
2513 LOperand* index = UseTempRegister(instr->index());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002514 LOperand* context = UseAny(instr->context());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002515 LStringCharCodeAt* result =
2516 new(zone()) LStringCharCodeAt(context, string, index);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002517 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2518}
2519
2520
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002521LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2522 LOperand* char_code = UseRegister(instr->value());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002523 LOperand* context = UseAny(instr->context());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002524 LStringCharFromCode* result =
2525 new(zone()) LStringCharFromCode(context, char_code);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002526 return AssignPointerMap(DefineAsRegister(result));
2527}
2528
2529
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002530LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2531 info()->MarkAsDeferredCalling();
2532 LOperand* context = UseAny(instr->context());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002533 LOperand* size = instr->size()->IsConstant()
2534 ? UseConstant(instr->size())
2535 : UseTempRegister(instr->size());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002536 LOperand* temp = TempRegister();
2537 LAllocate* result = new(zone()) LAllocate(context, size, temp);
2538 return AssignPointerMap(DefineAsRegister(result));
2539}
2540
2541
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002542LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002543 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002544 return MarkAsCall(
2545 DefineFixed(new(zone()) LRegExpLiteral(context), eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002546}
2547
2548
2549LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002550 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002551 return MarkAsCall(
2552 DefineFixed(new(zone()) LFunctionLiteral(context), eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002553}
2554
2555
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002556LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002557 ASSERT(argument_count_ == 0);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002558 allocator_->MarkAsOsrEntry();
2559 current_block_->last_environment()->set_ast_id(instr->ast_id());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002560 return AssignEnvironment(new(zone()) LOsrEntry);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002561}
2562
2563
2564LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002565 LParameter* result = new(zone()) LParameter;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002566 if (instr->kind() == HParameter::STACK_PARAMETER) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002567 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2568 return DefineAsSpilled(result, spill_index);
2569 } else {
2570 ASSERT(info()->IsStub());
2571 CodeStubInterfaceDescriptor* descriptor =
2572 info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002573 int index = static_cast<int>(instr->index());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002574 Register reg = descriptor->GetParameterRegister(index);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002575 return DefineFixed(result, reg);
2576 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002577}
2578
2579
2580LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +00002581 // Use an index that corresponds to the location in the unoptimized frame,
2582 // which the optimized frame will subsume.
2583 int env_index = instr->index();
2584 int spill_index = 0;
2585 if (instr->environment()->is_parameter_index(env_index)) {
2586 spill_index = chunk()->GetParameterStackSlot(env_index);
2587 } else {
2588 spill_index = env_index - instr->environment()->first_local_index();
2589 if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2590 Abort(kNotEnoughSpillSlotsForOsr);
2591 spill_index = 0;
2592 }
2593 if (spill_index == 0) {
2594 // The dynamic frame alignment state overwrites the first local.
2595 // The first local is saved at the end of the unoptimized frame.
2596 spill_index = graph()->osr()->UnoptimizedFrameSlots();
2597 }
ager@chromium.org04921a82011-06-27 13:21:41 +00002598 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002599 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002600}
2601
2602
2603LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002604 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002605 LCallStub* result = new(zone()) LCallStub(context);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002606 return MarkAsCall(DefineFixed(result, eax), instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002607}
2608
2609
2610LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002611 // There are no real uses of the arguments object.
2612 // arguments.length and element access are supported directly on
2613 // stack arguments, and any real arguments object use causes a bailout.
2614 // So this value is never used.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002615 return NULL;
2616}
2617
2618
danno@chromium.org59400602013-08-13 17:09:37 +00002619LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002620 instr->ReplayEnvironment(current_block_->last_environment());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00002621
danno@chromium.org59400602013-08-13 17:09:37 +00002622 // There are no real uses of a captured object.
2623 return NULL;
2624}
2625
2626
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002627LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002628 info()->MarkAsRequiresFrame();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002629 LOperand* args = UseRegister(instr->arguments());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002630 LOperand* length;
2631 LOperand* index;
2632 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2633 length = UseRegisterOrConstant(instr->length());
2634 index = UseOrConstant(instr->index());
2635 } else {
2636 length = UseTempRegister(instr->length());
2637 index = Use(instr->index());
2638 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002639 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002640}
2641
2642
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002643LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2644 LOperand* object = UseFixed(instr->value(), eax);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002645 LToFastProperties* result = new(zone()) LToFastProperties(object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002646 return MarkAsCall(DefineFixed(result, eax), instr);
2647}
2648
2649
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002650LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002651 LOperand* context = UseFixed(instr->context(), esi);
2652 LOperand* value = UseAtStart(instr->value());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002653 LTypeof* result = new(zone()) LTypeof(context, value);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002654 return MarkAsCall(DefineFixed(result, eax), instr);
2655}
2656
2657
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002658LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002659 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002660}
2661
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002662
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002663LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2664 HIsConstructCallAndBranch* instr) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002665 return new(zone()) LIsConstructCallAndBranch(TempRegister());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002666}
2667
2668
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002669LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002670 instr->ReplayEnvironment(current_block_->last_environment());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002671
2672 // If there is an instruction pending deoptimization environment create a
2673 // lazy bailout instruction to capture the environment.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002674 if (!pending_deoptimization_ast_id_.IsNone()) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00002675 ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002676 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002677 LInstruction* result = AssignEnvironment(lazy_bailout);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002678 // Store the lazy deopt environment with the instruction if needed. Right
2679 // now it is only used for LInstanceOfKnownGlobal.
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00002680 instruction_pending_deoptimization_environment_->
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002681 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2682 instruction_pending_deoptimization_environment_ = NULL;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002683 pending_deoptimization_ast_id_ = BailoutId::None();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002684 return result;
2685 }
2686
2687 return NULL;
2688}
2689
2690
2691LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002692 info()->MarkAsDeferredCalling();
ager@chromium.org04921a82011-06-27 13:21:41 +00002693 if (instr->is_function_entry()) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002694 LOperand* context = UseFixed(instr->context(), esi);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002695 return MarkAsCall(new(zone()) LStackCheck(context), instr);
ager@chromium.org04921a82011-06-27 13:21:41 +00002696 } else {
2697 ASSERT(instr->is_backwards_branch());
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00002698 LOperand* context = UseAny(instr->context());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002699 return AssignEnvironment(
2700 AssignPointerMap(new(zone()) LStackCheck(context)));
ager@chromium.org04921a82011-06-27 13:21:41 +00002701 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002702}
2703
2704
2705LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2706 HEnvironment* outer = current_block_->last_environment();
2707 HConstant* undefined = graph()->GetConstantUndefined();
2708 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002709 instr->arguments_count(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002710 instr->function(),
danno@chromium.org40cb8782011-05-25 07:58:50 +00002711 undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002712 instr->inlining_kind(),
2713 instr->undefined_receiver());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002714 // Only replay binding of arguments object if it wasn't removed from graph.
2715 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2716 inner->Bind(instr->arguments_var(), instr->arguments_object());
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00002717 }
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002718 inner->set_entry(instr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002719 current_block_->UpdateEnvironment(inner);
2720 chunk_->AddInlinedClosure(instr->closure());
2721 return NULL;
2722}
2723
2724
2725LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002726 LInstruction* pop = NULL;
2727
2728 HEnvironment* env = current_block_->last_environment();
2729
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002730 if (env->entry()->arguments_pushed()) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002731 int argument_count = env->arguments_environment()->parameter_count();
2732 pop = new(zone()) LDrop(argument_count);
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00002733 ASSERT(instr->argument_delta() == -argument_count);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002734 }
2735
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002736 HEnvironment* outer = current_block_->last_environment()->
2737 DiscardInlined(false);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002738 current_block_->UpdateEnvironment(outer);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002739 return pop;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002740}
2741
2742
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002743LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2744 LOperand* context = UseFixed(instr->context(), esi);
2745 LOperand* object = UseFixed(instr->enumerable(), eax);
2746 LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
2747 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
2748}
2749
2750
2751LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2752 LOperand* map = UseRegister(instr->map());
2753 return AssignEnvironment(DefineAsRegister(
2754 new(zone()) LForInCacheArray(map)));
2755}
2756
2757
2758LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2759 LOperand* value = UseRegisterAtStart(instr->value());
2760 LOperand* map = UseRegisterAtStart(instr->map());
2761 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
2762}
2763
2764
2765LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2766 LOperand* object = UseRegister(instr->object());
2767 LOperand* index = UseTempRegister(instr->index());
2768 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
2769}
2770
2771
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002772} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002773
2774#endif // V8_TARGET_ARCH_IA32