blob: 6262e7ede37719d537224d211569a945341ce68b [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000028#include "v8.h"
29
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +000030#if V8_TARGET_ARCH_X64
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000031
ricow@chromium.org83aa5492011-02-07 12:42:56 +000032#include "lithium-allocator-inl.h"
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000033#include "x64/lithium-x64.h"
34#include "x64/lithium-codegen-x64.h"
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000035#include "hydrogen-osr.h"
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +000036
37namespace v8 {
38namespace internal {
39
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000040#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
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +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
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000070void LInstruction::PrintTo(StringStream* stream) {
71 stream->Add("%s ", this->Mnemonic());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000072
73 PrintOutputOperandTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000074
75 PrintDataTo(stream);
76
77 if (HasEnvironment()) {
78 stream->Add(" ");
79 environment()->PrintTo(stream);
80 }
81
82 if (HasPointerMap()) {
83 stream->Add(" ");
84 pointer_map()->PrintTo(stream);
85 }
86}
87
88
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000089void LInstruction::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000090 stream->Add("= ");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000091 for (int i = 0; i < InputCount(); i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000092 if (i > 0) stream->Add(" ");
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +000093 if (InputAt(i) == NULL) {
94 stream->Add("NULL");
95 } else {
96 InputAt(i)->PrintTo(stream);
97 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000098 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000099}
100
101
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000102void LInstruction::PrintOutputOperandTo(StringStream* stream) {
103 if (HasResult()) result()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000104}
105
106
107void LLabel::PrintDataTo(StringStream* stream) {
108 LGap::PrintDataTo(stream);
109 LLabel* rep = replacement();
110 if (rep != NULL) {
111 stream->Add(" Dead block replaced with B%d", rep->block_id());
112 }
113}
114
115
116bool LGap::IsRedundant() const {
117 for (int i = 0; i < 4; i++) {
118 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
119 return false;
120 }
121 }
122
123 return true;
124}
125
126
127void LGap::PrintDataTo(StringStream* stream) {
128 for (int i = 0; i < 4; i++) {
129 stream->Add("(");
130 if (parallel_moves_[i] != NULL) {
131 parallel_moves_[i]->PrintDataTo(stream);
132 }
133 stream->Add(") ");
134 }
135}
136
137
138const char* LArithmeticD::Mnemonic() const {
139 switch (op()) {
140 case Token::ADD: return "add-d";
141 case Token::SUB: return "sub-d";
142 case Token::MUL: return "mul-d";
143 case Token::DIV: return "div-d";
144 case Token::MOD: return "mod-d";
145 default:
146 UNREACHABLE();
147 return NULL;
148 }
149}
150
151
152const char* LArithmeticT::Mnemonic() const {
153 switch (op()) {
154 case Token::ADD: return "add-t";
155 case Token::SUB: return "sub-t";
156 case Token::MUL: return "mul-t";
157 case Token::MOD: return "mod-t";
158 case Token::DIV: return "div-t";
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000159 case Token::BIT_AND: return "bit-and-t";
160 case Token::BIT_OR: return "bit-or-t";
161 case Token::BIT_XOR: return "bit-xor-t";
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000162 case Token::ROR: return "ror-t";
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000163 case Token::SHL: return "sal-t";
164 case Token::SAR: return "sar-t";
165 case Token::SHR: return "shr-t";
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000166 default:
167 UNREACHABLE();
168 return NULL;
169 }
170}
171
172
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000173bool LGoto::HasInterestingComment(LCodeGen* gen) const {
174 return !gen->IsNextEmittedBlock(block_id());
175}
176
177
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000178void LGoto::PrintDataTo(StringStream* stream) {
179 stream->Add("B%d", block_id());
180}
181
182
183void LBranch::PrintDataTo(StringStream* stream) {
184 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000185 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000186}
187
188
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000189void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000190 stream->Add("if ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000191 left()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000192 stream->Add(" %s ", Token::String(op()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000193 right()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000194 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
195}
196
197
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000198void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
199 stream->Add("if is_object(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000200 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000201 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
202}
203
204
erikcorry0ad885c2011-11-21 13:51:57 +0000205void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
206 stream->Add("if is_string(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000207 value()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000208 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
209}
210
211
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000212void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
213 stream->Add("if is_smi(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000214 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000215 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
216}
217
218
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000219void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
220 stream->Add("if is_undetectable(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000221 value()->PrintTo(stream);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000222 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
223}
224
225
erikcorry0ad885c2011-11-21 13:51:57 +0000226void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
227 stream->Add("if string_compare(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000228 left()->PrintTo(stream);
229 right()->PrintTo(stream);
erikcorry0ad885c2011-11-21 13:51:57 +0000230 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
231}
232
233
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000234void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
235 stream->Add("if has_instance_type(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000236 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000237 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
238}
239
240
241void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
242 stream->Add("if has_cached_array_index(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000243 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000244 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
245}
246
247
248void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
249 stream->Add("if class_of_test(");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000250 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000251 stream->Add(", \"%o\") then B%d else B%d",
252 *hydrogen()->class_name(),
253 true_block_id(),
254 false_block_id());
255}
256
257
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000258void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
259 stream->Add("if typeof ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000260 value()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000261 stream->Add(" == \"%s\" then B%d else B%d",
262 *hydrogen()->type_literal()->ToCString(),
263 true_block_id(), false_block_id());
264}
265
266
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000267void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
268 stream->Add(" = ");
269 function()->PrintTo(stream);
270 stream->Add(".code_entry = ");
271 code_object()->PrintTo(stream);
272}
273
274
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000275void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
276 stream->Add(" = ");
277 base_object()->PrintTo(stream);
278 stream->Add(" + %d", offset());
279}
280
281
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000282void LCallConstantFunction::PrintDataTo(StringStream* stream) {
283 stream->Add("#%d / ", arity());
284}
285
286
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000287void LLoadContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000288 context()->PrintTo(stream);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000289 stream->Add("[%d]", slot_index());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000290}
291
292
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000293void LStoreContextSlot::PrintDataTo(StringStream* stream) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000294 context()->PrintTo(stream);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000295 stream->Add("[%d] <- ", slot_index());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000296 value()->PrintTo(stream);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000297}
298
299
danno@chromium.org160a7b02011-04-18 15:51:38 +0000300void LInvokeFunction::PrintDataTo(StringStream* stream) {
301 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000302 function()->PrintTo(stream);
danno@chromium.org160a7b02011-04-18 15:51:38 +0000303 stream->Add(" #%d / ", arity());
304}
305
306
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000307void LCallKeyed::PrintDataTo(StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000308 stream->Add("[rcx] #%d / ", arity());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000309}
310
311
312void LCallNamed::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000313 SmartArrayPointer<char> name_string = name()->ToCString();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000314 stream->Add("%s #%d / ", *name_string, arity());
315}
316
317
318void LCallGlobal::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000319 SmartArrayPointer<char> name_string = name()->ToCString();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000320 stream->Add("%s #%d / ", *name_string, arity());
321}
322
323
324void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
325 stream->Add("#%d / ", arity());
326}
327
328
329void LCallNew::PrintDataTo(StringStream* stream) {
330 stream->Add("= ");
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000331 constructor()->PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000332 stream->Add(" #%d / ", arity());
333}
334
335
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000336void LCallNewArray::PrintDataTo(StringStream* stream) {
337 stream->Add("= ");
338 constructor()->PrintTo(stream);
339 stream->Add(" #%d / ", arity());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000340 ElementsKind kind = hydrogen()->elements_kind();
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000341 stream->Add(" (%s) ", ElementsKindToString(kind));
342}
343
344
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000345void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
346 arguments()->PrintTo(stream);
347
348 stream->Add(" length ");
349 length()->PrintTo(stream);
350
351 stream->Add(" index ");
352 index()->PrintTo(stream);
353}
354
355
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000356int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000357 return spill_slot_count_++;
358}
359
360
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000361LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000362 // All stack slots are Double stack slots on x64.
363 // Alternatively, at some point, start using half-size
364 // stack slots for int32 values.
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000365 int index = GetNextSpillIndex(kind);
366 if (kind == DOUBLE_REGISTERS) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000367 return LDoubleStackSlot::Create(index, zone());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000368 } else {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000369 ASSERT(kind == GENERAL_REGISTERS);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000370 return LStackSlot::Create(index, zone());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000371 }
372}
373
374
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000375void LStoreNamedField::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000376 object()->PrintTo(stream);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000377 hydrogen()->access().PrintTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000378 stream->Add(" <- ");
379 value()->PrintTo(stream);
380}
381
382
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000383void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
384 object()->PrintTo(stream);
385 stream->Add(".");
386 stream->Add(*String::cast(*name())->ToCString());
387 stream->Add(" <- ");
388 value()->PrintTo(stream);
389}
390
391
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000392void LLoadKeyed::PrintDataTo(StringStream* stream) {
393 elements()->PrintTo(stream);
394 stream->Add("[");
395 key()->PrintTo(stream);
396 if (hydrogen()->IsDehoisted()) {
397 stream->Add(" + %d]", additional_index());
398 } else {
399 stream->Add("]");
400 }
401}
402
403
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000404void LStoreKeyed::PrintDataTo(StringStream* stream) {
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000405 elements()->PrintTo(stream);
406 stream->Add("[");
407 key()->PrintTo(stream);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000408 if (hydrogen()->IsDehoisted()) {
409 stream->Add(" + %d] <-", additional_index());
410 } else {
411 stream->Add("] <- ");
412 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000413
414 if (value() == NULL) {
415 ASSERT(hydrogen()->IsConstantHoleStore() &&
416 hydrogen()->value()->representation().IsDouble());
417 stream->Add("<the hole(nan)>");
418 } else {
419 value()->PrintTo(stream);
420 }
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000421}
422
423
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000424void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000425 object()->PrintTo(stream);
426 stream->Add("[");
427 key()->PrintTo(stream);
428 stream->Add("] <- ");
429 value()->PrintTo(stream);
430}
431
432
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000433void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
434 object()->PrintTo(stream);
435 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
436}
437
438
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000439LPlatformChunk* LChunkBuilder::Build() {
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000440 ASSERT(is_unused());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000441 chunk_ = new(zone()) LPlatformChunk(info(), graph());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000442 LPhase phase("L_Building chunk", chunk_);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000443 status_ = BUILDING;
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000444
445 // If compiling for OSR, reserve space for the unoptimized frame,
446 // which will be subsumed into this frame.
447 if (graph()->has_osr()) {
448 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000449 chunk_->GetNextSpillIndex(GENERAL_REGISTERS);
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000450 }
451 }
452
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000453 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
454 for (int i = 0; i < blocks->length(); i++) {
455 HBasicBlock* next = NULL;
456 if (i < blocks->length() - 1) next = blocks->at(i + 1);
457 DoBasicBlock(blocks->at(i), next);
458 if (is_aborted()) return NULL;
459 }
460 status_ = DONE;
461 return chunk_;
462}
463
464
danno@chromium.org59400602013-08-13 17:09:37 +0000465void LCodeGen::Abort(BailoutReason reason) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000466 info()->set_bailout_reason(reason);
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000467 status_ = ABORTED;
468}
469
470
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000471LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000472 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
473 Register::ToAllocationIndex(reg));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000474}
475
476
477LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000478 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
479 XMMRegister::ToAllocationIndex(reg));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000480}
481
482
483LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
484 return Use(value, ToUnallocated(fixed_register));
485}
486
487
488LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
489 return Use(value, ToUnallocated(reg));
490}
491
492
493LOperand* LChunkBuilder::UseRegister(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000494 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000495}
496
497
498LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
499 return Use(value,
ulan@chromium.org812308e2012-02-29 15:58:45 +0000500 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000501 LUnallocated::USED_AT_START));
502}
503
504
505LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000506 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000507}
508
509
510LOperand* LChunkBuilder::Use(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000511 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000512}
513
514
515LOperand* LChunkBuilder::UseAtStart(HValue* value) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000516 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000517 LUnallocated::USED_AT_START));
518}
519
520
521LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
522 return value->IsConstant()
523 ? chunk_->DefineConstantOperand(HConstant::cast(value))
524 : Use(value);
525}
526
527
528LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
529 return value->IsConstant()
530 ? chunk_->DefineConstantOperand(HConstant::cast(value))
531 : UseAtStart(value);
532}
533
534
535LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
536 return value->IsConstant()
537 ? chunk_->DefineConstantOperand(HConstant::cast(value))
538 : UseRegister(value);
539}
540
541
542LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
543 return value->IsConstant()
544 ? chunk_->DefineConstantOperand(HConstant::cast(value))
545 : UseRegisterAtStart(value);
546}
547
548
danno@chromium.orgf005df62013-04-30 16:36:45 +0000549LOperand* LChunkBuilder::UseConstant(HValue* value) {
550 return chunk_->DefineConstantOperand(HConstant::cast(value));
551}
552
553
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000554LOperand* LChunkBuilder::UseAny(HValue* value) {
555 return value->IsConstant()
556 ? chunk_->DefineConstantOperand(HConstant::cast(value))
ulan@chromium.org812308e2012-02-29 15:58:45 +0000557 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000558}
559
560
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000561LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
562 if (value->EmitAtUses()) {
563 HInstruction* instr = HInstruction::cast(value);
564 VisitInstruction(instr);
565 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000566 operand->set_virtual_register(value->id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000567 return operand;
568}
569
570
571template<int I, int T>
572LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
573 LUnallocated* result) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000574 result->set_virtual_register(current_instruction_->id());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000575 instr->set_result(result);
576 return instr;
577}
578
579
580template<int I, int T>
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000581LInstruction* LChunkBuilder::DefineAsRegister(
582 LTemplateInstruction<1, I, T>* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000583 return Define(instr,
584 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000585}
586
587
588template<int I, int T>
589LInstruction* LChunkBuilder::DefineAsSpilled(
590 LTemplateInstruction<1, I, T>* instr,
591 int index) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000592 return Define(instr,
593 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000594}
595
596
597template<int I, int T>
598LInstruction* LChunkBuilder::DefineSameAsFirst(
599 LTemplateInstruction<1, I, T>* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000600 return Define(instr,
601 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000602}
603
604
605template<int I, int T>
606LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
607 Register reg) {
608 return Define(instr, ToUnallocated(reg));
609}
610
611
612template<int I, int T>
613LInstruction* LChunkBuilder::DefineFixedDouble(
614 LTemplateInstruction<1, I, T>* instr,
615 XMMRegister reg) {
616 return Define(instr, ToUnallocated(reg));
617}
618
619
620LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
621 HEnvironment* hydrogen_env = current_block_->last_environment();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000622 int argument_index_accumulator = 0;
danno@chromium.org59400602013-08-13 17:09:37 +0000623 ZoneList<HValue*> objects_to_materialize(0, zone());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000624 instr->set_environment(CreateEnvironment(hydrogen_env,
danno@chromium.org59400602013-08-13 17:09:37 +0000625 &argument_index_accumulator,
626 &objects_to_materialize));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000627 return instr;
628}
629
630
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000631LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
632 HInstruction* hinstr,
633 CanDeoptimize can_deoptimize) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000634 info()->MarkAsNonDeferredCalling();
635
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000636#ifdef DEBUG
637 instr->VerifyCall();
638#endif
639 instr->MarkAsCall();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000640 instr = AssignPointerMap(instr);
641
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000642 if (hinstr->HasObservableSideEffects()) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000643 ASSERT(hinstr->next()->IsSimulate());
644 HSimulate* sim = HSimulate::cast(hinstr->next());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000645 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000646 ASSERT(pending_deoptimization_ast_id_.IsNone());
danno@chromium.org1044a4d2012-04-30 12:34:39 +0000647 instruction_pending_deoptimization_environment_ = instr;
648 pending_deoptimization_ast_id_ = sim->ast_id();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000649 }
650
651 // If instruction does not have side-effects lazy deoptimization
652 // after the call will try to deoptimize to the point before the call.
653 // Thus we still need to attach environment to this call even if
654 // call sequence can not deoptimize eagerly.
655 bool needs_environment =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000656 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
657 !hinstr->HasObservableSideEffects();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000658 if (needs_environment && !instr->HasEnvironment()) {
659 instr = AssignEnvironment(instr);
660 }
661
662 return instr;
663}
664
665
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000666LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
667 ASSERT(!instr->HasPointerMap());
bmeurer@chromium.org71f9fca2013-10-22 08:00:09 +0000668 instr->set_pointer_map(new(zone()) LPointerMap(zone()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000669 return instr;
670}
671
672
673LUnallocated* LChunkBuilder::TempRegister() {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000674 LUnallocated* operand =
675 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000676 int vreg = allocator_->GetVirtualRegister();
677 if (!allocator_->AllocationOk()) {
danno@chromium.org59400602013-08-13 17:09:37 +0000678 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000679 vreg = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000680 }
681 operand->set_virtual_register(vreg);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000682 return operand;
683}
684
685
686LOperand* LChunkBuilder::FixedTemp(Register reg) {
687 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000688 ASSERT(operand->HasFixedPolicy());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000689 return operand;
690}
691
692
693LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
694 LUnallocated* operand = ToUnallocated(reg);
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000695 ASSERT(operand->HasFixedPolicy());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000696 return operand;
697}
698
699
700LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000701 return new(zone()) LLabel(instr->block());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000702}
703
704
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000705LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
706 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
707}
708
709
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000710LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
711 UNREACHABLE();
712 return NULL;
713}
714
715
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000716LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000717 return AssignEnvironment(new(zone()) LDeoptimize);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000718}
719
720
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000721LInstruction* LChunkBuilder::DoShift(Token::Value op,
722 HBitwiseBinaryOperation* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000723 if (instr->representation().IsSmiOrInteger32()) {
724 ASSERT(instr->left()->representation().Equals(instr->representation()));
725 ASSERT(instr->right()->representation().Equals(instr->representation()));
726 LOperand* left = UseRegisterAtStart(instr->left());
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000727
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000728 HValue* right_value = instr->right();
729 LOperand* right = NULL;
730 int constant_value = 0;
731 if (right_value->IsConstant()) {
732 HConstant* constant = HConstant::cast(right_value);
733 right = chunk_->DefineConstantOperand(constant);
734 constant_value = constant->Integer32Value() & 0x1f;
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000735 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000736 right = UseFixed(right_value, rcx);
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000737 }
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +0000738
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000739 // Shift operations can only deoptimize if we do a logical shift by 0 and
740 // the result cannot be truncated to int32.
741 bool does_deopt = false;
742 if (op == Token::SHR && constant_value == 0) {
743 if (FLAG_opt_safe_uint32_operations) {
744 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
745 } else {
746 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
747 }
748 }
749
750 LInstruction* result =
751 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt));
752 return does_deopt ? AssignEnvironment(result) : result;
753 } else {
754 return DoArithmeticT(op, instr);
755 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000756}
757
758
759LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
760 HArithmeticBinaryOperation* instr) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000761 ASSERT(instr->representation().IsDouble());
762 ASSERT(instr->left()->representation().IsDouble());
763 ASSERT(instr->right()->representation().IsDouble());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000764 if (op == Token::MOD) {
765 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
766 LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1);
767 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
768 return MarkAsCall(DefineSameAsFirst(result), instr);
769 } else {
770 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
771 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand());
772 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
773 return DefineSameAsFirst(result);
774 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000775}
776
777
778LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000779 HBinaryOperation* instr) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000780 HValue* left = instr->left();
781 HValue* right = instr->right();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000782 ASSERT(left->representation().IsTagged());
783 ASSERT(right->representation().IsTagged());
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000784 LOperand* left_operand = UseFixed(left, rdx);
785 LOperand* right_operand = UseFixed(right, rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +0000786 LArithmeticT* result =
787 new(zone()) LArithmeticT(op, left_operand, right_operand);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000788 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000789}
790
791
792void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
793 ASSERT(is_building());
794 current_block_ = block;
795 next_block_ = next_block;
796 if (block->IsStartBlock()) {
797 block->UpdateEnvironment(graph_->start_environment());
798 argument_count_ = 0;
799 } else if (block->predecessors()->length() == 1) {
800 // We have a single predecessor => copy environment and outgoing
801 // argument count from the predecessor.
802 ASSERT(block->phis()->length() == 0);
803 HBasicBlock* pred = block->predecessors()->at(0);
804 HEnvironment* last_environment = pred->last_environment();
805 ASSERT(last_environment != NULL);
806 // Only copy the environment, if it is later used again.
807 if (pred->end()->SecondSuccessor() == NULL) {
808 ASSERT(pred->end()->FirstSuccessor() == block);
809 } else {
810 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
811 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
812 last_environment = last_environment->Copy();
813 }
814 }
815 block->UpdateEnvironment(last_environment);
816 ASSERT(pred->argument_count() >= 0);
817 argument_count_ = pred->argument_count();
818 } else {
819 // We are at a state join => process phis.
820 HBasicBlock* pred = block->predecessors()->at(0);
821 // No need to copy the environment, it cannot be used later.
822 HEnvironment* last_environment = pred->last_environment();
823 for (int i = 0; i < block->phis()->length(); ++i) {
824 HPhi* phi = block->phis()->at(i);
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000825 if (phi->HasMergedIndex()) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000826 last_environment->SetValueAt(phi->merged_index(), phi);
827 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000828 }
829 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000830 if (block->deleted_phis()->at(i) < last_environment->length()) {
831 last_environment->SetValueAt(block->deleted_phis()->at(i),
832 graph_->GetConstantUndefined());
833 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000834 }
835 block->UpdateEnvironment(last_environment);
836 // Pick up the outgoing argument count of one of the predecessors.
837 argument_count_ = pred->argument_count();
838 }
839 HInstruction* current = block->first();
840 int start = chunk_->instructions()->length();
841 while (current != NULL && !is_aborted()) {
842 // Code for constants in registers is generated lazily.
843 if (!current->EmitAtUses()) {
844 VisitInstruction(current);
845 }
846 current = current->next();
847 }
848 int end = chunk_->instructions()->length() - 1;
849 if (end >= start) {
850 block->set_first_instruction_index(start);
851 block->set_last_instruction_index(end);
852 }
853 block->set_argument_count(argument_count_);
854 next_block_ = NULL;
855 current_block_ = NULL;
856}
857
858
859void LChunkBuilder::VisitInstruction(HInstruction* current) {
860 HInstruction* old_current = current_instruction_;
861 current_instruction_ = current;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000862
863 LInstruction* instr = NULL;
864 if (current->CanReplaceWithDummyUses()) {
865 HValue* first_operand = current->OperandCount() == 0
866 ? graph()->GetConstant1()
867 : current->OperandAt(0);
868 instr = DefineAsRegister(new(zone()) LDummyUse(UseAny(first_operand)));
869 for (int i = 1; i < current->OperandCount(); ++i) {
870 LInstruction* dummy =
871 new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
872 dummy->set_hydrogen_value(current);
873 chunk_->AddInstruction(dummy, current_block_);
874 }
875 } else {
876 instr = current->CompileToLithium(this);
877 }
878
879 argument_count_ += current->argument_delta();
880 ASSERT(argument_count_ >= 0);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000881
882 if (instr != NULL) {
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000883 // Associate the hydrogen instruction first, since we may need it for
884 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
885 instr->set_hydrogen_value(current);
886
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000887#if DEBUG
888 // Make sure that the lithium instruction has either no fixed register
889 // constraints in temps or the result OR no uses that are only used at
890 // start. If this invariant doesn't hold, the register allocator can decide
891 // to insert a split of a range immediately before the instruction due to an
892 // already allocated register needing to be used for the instruction's fixed
893 // register constraint. In this case, The register allocator won't see an
894 // interference between the split child and the use-at-start (it would if
895 // the it was just a plain use), so it is free to move the split child into
896 // the same register that is used for the use-at-start.
897 // See https://code.google.com/p/chromium/issues/detail?id=201590
898 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
899 int fixed = 0;
900 int used_at_start = 0;
901 for (UseIterator it(instr); !it.Done(); it.Advance()) {
902 LUnallocated* operand = LUnallocated::cast(it.Current());
903 if (operand->IsUsedAtStart()) ++used_at_start;
904 }
905 if (instr->Output() != NULL) {
906 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
907 }
908 for (TempIterator it(instr); !it.Done(); it.Advance()) {
909 LUnallocated* operand = LUnallocated::cast(it.Current());
910 if (operand->HasFixedPolicy()) ++fixed;
911 }
912 ASSERT(fixed == 0 || used_at_start == 0);
913 }
914#endif
915
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000916 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
917 instr = AssignPointerMap(instr);
918 }
919 if (FLAG_stress_environments && !instr->HasEnvironment()) {
920 instr = AssignEnvironment(instr);
921 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000922 chunk_->AddInstruction(instr, current_block_);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000923 }
924 current_instruction_ = old_current;
925}
926
927
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000928LEnvironment* LChunkBuilder::CreateEnvironment(
929 HEnvironment* hydrogen_env,
danno@chromium.org59400602013-08-13 17:09:37 +0000930 int* argument_index_accumulator,
931 ZoneList<HValue*>* objects_to_materialize) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000932 if (hydrogen_env == NULL) return NULL;
933
danno@chromium.org59400602013-08-13 17:09:37 +0000934 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
935 argument_index_accumulator,
936 objects_to_materialize);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000937 BailoutId ast_id = hydrogen_env->ast_id();
938 ASSERT(!ast_id.IsNone() ||
ulan@chromium.org967e2702012-02-28 09:49:15 +0000939 hydrogen_env->frame_type() != JS_FUNCTION);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000940 int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000941 LEnvironment* result = new(zone()) LEnvironment(
942 hydrogen_env->closure(),
943 hydrogen_env->frame_type(),
944 ast_id,
945 hydrogen_env->parameter_count(),
946 argument_count_,
947 value_count,
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000948 outer,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000949 hydrogen_env->entry(),
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000950 zone());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000951 int argument_index = *argument_index_accumulator;
danno@chromium.org59400602013-08-13 17:09:37 +0000952 int object_index = objects_to_materialize->length();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000953 for (int i = 0; i < hydrogen_env->length(); ++i) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000954 if (hydrogen_env->is_special_index(i)) continue;
955
danno@chromium.org59400602013-08-13 17:09:37 +0000956 LOperand* op;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000957 HValue* value = hydrogen_env->values()->at(i);
danno@chromium.org59400602013-08-13 17:09:37 +0000958 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
959 objects_to_materialize->Add(value, zone());
960 op = LEnvironment::materialization_marker();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000961 } else if (value->IsPushArgument()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000962 op = new(zone()) LArgument(argument_index++);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000963 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000964 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000965 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000966 result->AddValue(op,
967 value->representation(),
968 value->CheckFlag(HInstruction::kUint32));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000969 }
970
danno@chromium.org59400602013-08-13 17:09:37 +0000971 for (int i = object_index; i < objects_to_materialize->length(); ++i) {
972 HValue* object_to_materialize = objects_to_materialize->at(i);
973 int previously_materialized_object = -1;
974 for (int prev = 0; prev < i; ++prev) {
975 if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
976 previously_materialized_object = prev;
977 break;
978 }
979 }
980 int length = object_to_materialize->OperandCount();
981 bool is_arguments = object_to_materialize->IsArgumentsObject();
982 if (previously_materialized_object >= 0) {
983 result->AddDuplicateObject(previously_materialized_object);
984 continue;
985 } else {
986 result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
987 }
988 for (int i = is_arguments ? 1 : 0; i < length; ++i) {
989 LOperand* op;
990 HValue* value = object_to_materialize->OperandAt(i);
991 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
992 objects_to_materialize->Add(value, zone());
993 op = LEnvironment::materialization_marker();
994 } else {
995 ASSERT(!value->IsPushArgument());
996 op = UseAny(value);
997 }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000998 result->AddValue(op,
999 value->representation(),
1000 value->CheckFlag(HInstruction::kUint32));
1001 }
1002 }
1003
ulan@chromium.org967e2702012-02-28 09:49:15 +00001004 if (hydrogen_env->frame_type() == JS_FUNCTION) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001005 *argument_index_accumulator = argument_index;
1006 }
1007
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001008 return result;
1009}
1010
1011
1012LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001013 return new(zone()) LGoto(instr->FirstSuccessor());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001014}
1015
1016
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001017LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1018 return new(zone()) LDebugBreak();
1019}
1020
1021
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001022LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001023 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1024 if (goto_instr != NULL) return goto_instr;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001025
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001026 HValue* value = instr->value();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001027 LBranch* result = new(zone()) LBranch(UseRegister(value));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001028 // Tagged values that are not known smis or booleans require a
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001029 // deoptimization environment. If the instruction is generic no
1030 // environment is needed since all cases are handled.
1031 ToBooleanStub::Types expected = instr->expected_input_types();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001032 Representation rep = value->representation();
1033 HType type = value->type();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001034 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() &&
1035 !expected.IsGeneric()) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001036 return AssignEnvironment(result);
1037 }
1038 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001039}
1040
1041
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001042LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001043 ASSERT(instr->value()->representation().IsTagged());
1044 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001045 return new(zone()) LCmpMapAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001046}
1047
1048
1049LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001050 info()->MarkAsRequiresFrame();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001051 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001052}
1053
1054
1055LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001056 info()->MarkAsRequiresFrame();
danno@chromium.orgb2a1c072012-03-23 15:47:56 +00001057 return DefineAsRegister(new(zone()) LArgumentsElements);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001058}
1059
1060
1061LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001062 LOperand* left = UseFixed(instr->left(), rax);
1063 LOperand* right = UseFixed(instr->right(), rdx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001064 LInstanceOf* result = new(zone()) LInstanceOf(left, right);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001065 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001066}
1067
1068
1069LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1070 HInstanceOfKnownGlobal* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001071 LInstanceOfKnownGlobal* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +00001072 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), rax),
1073 FixedTemp(rdi));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001074 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001075}
1076
1077
yangguo@chromium.org154ff992012-03-13 08:09:54 +00001078LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1079 LOperand* receiver = UseRegister(instr->receiver());
1080 LOperand* function = UseRegisterAtStart(instr->function());
1081 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
1082 return AssignEnvironment(DefineSameAsFirst(result));
1083}
1084
1085
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001086LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001087 LOperand* function = UseFixed(instr->function(), rdi);
1088 LOperand* receiver = UseFixed(instr->receiver(), rax);
1089 LOperand* length = UseFixed(instr->length(), rbx);
1090 LOperand* elements = UseFixed(instr->elements(), rcx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001091 LApplyArguments* result = new(zone()) LApplyArguments(function,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001092 receiver,
1093 length,
1094 elements);
1095 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001096}
1097
1098
1099LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001100 LOperand* argument = UseOrConstant(instr->argument());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001101 return new(zone()) LPushArgument(argument);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001102}
1103
1104
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001105LInstruction* LChunkBuilder::DoStoreCodeEntry(
1106 HStoreCodeEntry* store_code_entry) {
1107 LOperand* function = UseRegister(store_code_entry->function());
1108 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1109 return new(zone()) LStoreCodeEntry(function, code_object);
1110}
1111
1112
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001113LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1114 HInnerAllocatedObject* inner_object) {
1115 LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
1116 LInnerAllocatedObject* result =
1117 new(zone()) LInnerAllocatedObject(base_object);
1118 return DefineAsRegister(result);
1119}
1120
1121
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001122LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001123 return instr->HasNoUses()
1124 ? NULL
1125 : DefineAsRegister(new(zone()) LThisFunction);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001126}
1127
1128
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001129LInstruction* LChunkBuilder::DoContext(HContext* instr) {
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001130 // If there is a non-return use, the context must be allocated in a register.
1131 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
1132 if (!it.value()->IsReturn()) {
1133 return DefineAsRegister(new(zone()) LContext);
1134 }
1135 }
1136
1137 return NULL;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001138}
1139
1140
1141LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001142 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001143 return DefineAsRegister(new(zone()) LOuterContext(context));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001144}
1145
1146
yangguo@chromium.org56454712012-02-16 15:33:53 +00001147LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001148 return MarkAsCall(new(zone()) LDeclareGlobals, instr);
yangguo@chromium.org56454712012-02-16 15:33:53 +00001149}
1150
1151
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001152LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001153 return DefineAsRegister(new(zone()) LGlobalObject);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001154}
1155
1156
1157LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001158 LOperand* global_object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001159 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001160}
1161
1162
1163LInstruction* LChunkBuilder::DoCallConstantFunction(
1164 HCallConstantFunction* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001165 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001166}
1167
1168
danno@chromium.org160a7b02011-04-18 15:51:38 +00001169LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1170 LOperand* function = UseFixed(instr->function(), rdi);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001171 LInvokeFunction* result = new(zone()) LInvokeFunction(function);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001172 return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1173}
1174
1175
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001176LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001177 switch (instr->op()) {
1178 case kMathFloor: return DoMathFloor(instr);
1179 case kMathRound: return DoMathRound(instr);
1180 case kMathAbs: return DoMathAbs(instr);
1181 case kMathLog: return DoMathLog(instr);
1182 case kMathSin: return DoMathSin(instr);
1183 case kMathCos: return DoMathCos(instr);
1184 case kMathTan: return DoMathTan(instr);
1185 case kMathExp: return DoMathExp(instr);
1186 case kMathSqrt: return DoMathSqrt(instr);
1187 case kMathPowHalf: return DoMathPowHalf(instr);
1188 default:
1189 UNREACHABLE();
1190 return NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001191 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001192}
1193
1194
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001195LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1196 LOperand* input = UseRegisterAtStart(instr->value());
1197 LMathFloor* result = new(zone()) LMathFloor(input);
1198 return AssignEnvironment(DefineAsRegister(result));
1199}
1200
1201
1202LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1203 LOperand* input = UseRegisterAtStart(instr->value());
1204 LMathRound* result = new(zone()) LMathRound(input);
1205 return AssignEnvironment(DefineAsRegister(result));
1206}
1207
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001208
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001209LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1210 LOperand* input = UseRegisterAtStart(instr->value());
1211 LMathAbs* result = new(zone()) LMathAbs(input);
1212 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1213}
1214
1215
1216LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +00001217 ASSERT(instr->representation().IsDouble());
1218 ASSERT(instr->value()->representation().IsDouble());
1219 LOperand* input = UseRegisterAtStart(instr->value());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001220 LMathLog* result = new(zone()) LMathLog(input);
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +00001221 return DefineSameAsFirst(result);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001222}
1223
1224
1225LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1226 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1227 LMathSin* result = new(zone()) LMathSin(input);
1228 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1229}
1230
1231
1232LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1233 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1234 LMathCos* result = new(zone()) LMathCos(input);
1235 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1236}
1237
1238
1239LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
1240 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1241 LMathTan* result = new(zone()) LMathTan(input);
1242 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1243}
1244
1245
1246LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1247 ASSERT(instr->representation().IsDouble());
1248 ASSERT(instr->value()->representation().IsDouble());
1249 LOperand* value = UseTempRegister(instr->value());
1250 LOperand* temp1 = TempRegister();
1251 LOperand* temp2 = TempRegister();
1252 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1253 return DefineAsRegister(result);
1254}
1255
1256
1257LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1258 LOperand* input = UseRegisterAtStart(instr->value());
1259 LMathSqrt* result = new(zone()) LMathSqrt(input);
1260 return DefineSameAsFirst(result);
1261}
1262
1263
1264LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1265 LOperand* input = UseRegisterAtStart(instr->value());
1266 LMathPowHalf* result = new(zone()) LMathPowHalf(input);
1267 return DefineSameAsFirst(result);
1268}
1269
1270
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001271LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001272 ASSERT(instr->key()->representation().IsTagged());
1273 LOperand* key = UseFixed(instr->key(), rcx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001274 LCallKeyed* result = new(zone()) LCallKeyed(key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001275 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001276}
1277
1278
1279LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001280 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001281}
1282
1283
1284LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001285 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001286}
1287
1288
1289LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001290 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001291}
1292
1293
1294LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001295 LOperand* constructor = UseFixed(instr->constructor(), rdi);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001296 LCallNew* result = new(zone()) LCallNew(constructor);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001297 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001298}
1299
1300
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001301LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001302 LOperand* constructor = UseFixed(instr->constructor(), rdi);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001303 LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1304 return MarkAsCall(DefineFixed(result, rax), instr);
1305}
1306
1307
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001308LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
danno@chromium.orgc612e022011-11-10 11:38:15 +00001309 LOperand* function = UseFixed(instr->function(), rdi);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001310 LCallFunction* result = new(zone()) LCallFunction(function);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001311 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001312}
1313
1314
1315LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001316 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001317}
1318
1319
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001320LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1321 return DoShift(Token::ROR, instr);
1322}
1323
1324
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001325LInstruction* LChunkBuilder::DoShr(HShr* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001326 return DoShift(Token::SHR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001327}
1328
1329
1330LInstruction* LChunkBuilder::DoSar(HSar* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001331 return DoShift(Token::SAR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001332}
1333
1334
1335LInstruction* LChunkBuilder::DoShl(HShl* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001336 return DoShift(Token::SHL, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001337}
1338
1339
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001340LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001341 if (instr->representation().IsSmiOrInteger32()) {
1342 ASSERT(instr->left()->representation().Equals(instr->representation()));
1343 ASSERT(instr->right()->representation().Equals(instr->representation()));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001344 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001345
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001346 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1347 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001348 return DefineSameAsFirst(new(zone()) LBitI(left, right));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001349 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001350 return DoArithmeticT(instr->op(), instr);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001351 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001352}
1353
1354
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001355LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001356 if (instr->representation().IsSmiOrInteger32()) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001357 ASSERT(instr->left()->representation().Equals(instr->representation()));
1358 ASSERT(instr->right()->representation().Equals(instr->representation()));
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001359 if (instr->HasPowerOf2Divisor()) {
1360 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1361 LOperand* value = UseRegisterAtStart(instr->left());
1362 LDivI* div =
1363 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1364 return AssignEnvironment(DefineSameAsFirst(div));
1365 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001366 // The temporary operand is necessary to ensure that right is not allocated
1367 // into rdx.
1368 LOperand* temp = FixedTemp(rdx);
1369 LOperand* dividend = UseFixed(instr->left(), rax);
1370 LOperand* divisor = UseRegister(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001371 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001372 return AssignEnvironment(DefineFixed(result, rax));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001373 } else if (instr->representation().IsDouble()) {
1374 return DoArithmeticD(Token::DIV, instr);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001375 } else {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001376 return DoArithmeticT(Token::DIV, instr);
1377 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001378}
1379
1380
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001381HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1382 if (divisor->IsConstant() &&
1383 HConstant::cast(divisor)->HasInteger32Value()) {
1384 HConstant* constant_val = HConstant::cast(divisor);
1385 return constant_val->CopyToRepresentation(Representation::Integer32(),
1386 divisor->block()->zone());
1387 }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001388 // A value with an integer representation does not need to be transformed.
1389 if (divisor->representation().IsInteger32()) {
1390 return divisor;
1391 // A change from an integer32 can be replaced by the integer32 value.
1392 } else if (divisor->IsChange() &&
1393 HChange::cast(divisor)->from().IsInteger32()) {
1394 return HChange::cast(divisor)->value();
1395 }
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001396 return NULL;
1397}
1398
1399
1400LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1401 HValue* right = instr->right();
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001402 if (!right->IsConstant()) {
1403 ASSERT(right->representation().IsInteger32());
1404 // The temporary operand is necessary to ensure that right is not allocated
1405 // into rdx.
1406 LOperand* temp = FixedTemp(rdx);
1407 LOperand* dividend = UseFixed(instr->left(), rax);
1408 LOperand* divisor = UseRegister(instr->right());
1409 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp);
1410 return AssignEnvironment(DefineFixed(flooring_div, rax));
1411 }
1412
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001413 ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value());
1414 LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
1415 int32_t divisor_si = HConstant::cast(right)->Integer32Value();
1416 if (divisor_si == 0) {
1417 LOperand* dividend = UseRegister(instr->left());
1418 return AssignEnvironment(DefineAsRegister(
1419 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
1420 } else if (IsPowerOf2(abs(divisor_si))) {
1421 LOperand* dividend = UseRegisterAtStart(instr->left());
1422 LInstruction* result = DefineAsRegister(
1423 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
1424 return divisor_si < 0 ? AssignEnvironment(result) : result;
1425 } else {
1426 // use two r64
1427 LOperand* dividend = UseRegisterAtStart(instr->left());
1428 LOperand* temp = TempRegister();
1429 LInstruction* result = DefineAsRegister(
1430 new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
1431 return divisor_si < 0 ? AssignEnvironment(result) : result;
1432 }
1433}
1434
1435
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001436LInstruction* LChunkBuilder::DoMod(HMod* instr) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001437 HValue* left = instr->left();
1438 HValue* right = instr->right();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001439 if (instr->representation().IsSmiOrInteger32()) {
1440 ASSERT(left->representation().Equals(instr->representation()));
1441 ASSERT(right->representation().Equals(instr->representation()));
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001442 if (instr->HasPowerOf2Divisor()) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001443 ASSERT(!right->CanBeZero());
1444 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1445 UseOrConstant(right),
1446 NULL);
1447 LInstruction* result = DefineSameAsFirst(mod);
1448 return (left->CanBeNegative() &&
1449 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1450 ? AssignEnvironment(result)
1451 : result;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001452 } else if (instr->fixed_right_arg().has_value) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001453 LModI* mod = new(zone()) LModI(UseRegister(left),
1454 UseRegisterAtStart(right),
1455 NULL);
1456 return AssignEnvironment(DefineSameAsFirst(mod));
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001457 } else {
1458 // The temporary operand is necessary to ensure that right is not
1459 // allocated into edx.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001460 LModI* mod = new(zone()) LModI(UseFixed(left, rax),
1461 UseRegister(right),
1462 FixedTemp(rdx));
1463 LInstruction* result = DefineFixed(mod, rdx);
1464 return (right->CanBeZero() ||
1465 (left->RangeCanInclude(kMinInt) &&
1466 right->RangeCanInclude(-1) &&
1467 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1468 (left->CanBeNegative() &&
1469 instr->CanBeZero() &&
1470 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1471 ? AssignEnvironment(result)
1472 : result;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001473 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001474 } else if (instr->representation().IsDouble()) {
1475 return DoArithmeticD(Token::MOD, instr);
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +00001476 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001477 return DoArithmeticT(Token::MOD, instr);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001478 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001479}
1480
1481
1482LInstruction* LChunkBuilder::DoMul(HMul* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001483 if (instr->representation().IsSmiOrInteger32()) {
1484 ASSERT(instr->left()->representation().Equals(instr->representation()));
1485 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001486 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1487 LOperand* right = UseOrConstant(instr->BetterRightOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001488 LMulI* mul = new(zone()) LMulI(left, right);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001489 if (instr->CheckFlag(HValue::kCanOverflow) ||
1490 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1491 AssignEnvironment(mul);
1492 }
1493 return DefineSameAsFirst(mul);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001494 } else if (instr->representation().IsDouble()) {
1495 return DoArithmeticD(Token::MUL, instr);
1496 } else {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001497 return DoArithmeticT(Token::MUL, instr);
1498 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001499}
1500
1501
1502LInstruction* LChunkBuilder::DoSub(HSub* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001503 if (instr->representation().IsSmiOrInteger32()) {
1504 ASSERT(instr->left()->representation().Equals(instr->representation()));
1505 ASSERT(instr->right()->representation().Equals(instr->representation()));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001506 LOperand* left = UseRegisterAtStart(instr->left());
1507 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001508 LSubI* sub = new(zone()) LSubI(left, right);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001509 LInstruction* result = DefineSameAsFirst(sub);
1510 if (instr->CheckFlag(HValue::kCanOverflow)) {
1511 result = AssignEnvironment(result);
1512 }
1513 return result;
1514 } else if (instr->representation().IsDouble()) {
1515 return DoArithmeticD(Token::SUB, instr);
1516 } else {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001517 return DoArithmeticT(Token::SUB, instr);
1518 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001519}
1520
1521
1522LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001523 if (instr->representation().IsSmiOrInteger32()) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001524 // Check to see if it would be advantageous to use an lea instruction rather
1525 // than an add. This is the case when no overflow check is needed and there
1526 // are multiple uses of the add's inputs, so using a 3-register add will
1527 // preserve all input values for later uses.
1528 bool use_lea = LAddI::UseLea(instr);
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001529 ASSERT(instr->left()->representation().Equals(instr->representation()));
1530 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001531 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1532 HValue* right_candidate = instr->BetterRightOperand();
1533 LOperand* right = use_lea
1534 ? UseRegisterOrConstantAtStart(right_candidate)
1535 : UseOrConstantAtStart(right_candidate);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001536 LAddI* add = new(zone()) LAddI(left, right);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001537 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1538 LInstruction* result = use_lea
1539 ? DefineAsRegister(add)
1540 : DefineSameAsFirst(add);
1541 if (can_overflow) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001542 result = AssignEnvironment(result);
1543 }
1544 return result;
1545 } else if (instr->representation().IsDouble()) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001546 return DoArithmeticD(Token::ADD, instr);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001547 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001548 return DoArithmeticT(Token::ADD, instr);
1549 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001550 return NULL;
1551}
1552
1553
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001554LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1555 LOperand* left = NULL;
1556 LOperand* right = NULL;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001557 if (instr->representation().IsSmiOrInteger32()) {
1558 ASSERT(instr->left()->representation().Equals(instr->representation()));
1559 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001560 left = UseRegisterAtStart(instr->BetterLeftOperand());
1561 right = UseOrConstantAtStart(instr->BetterRightOperand());
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001562 } else {
1563 ASSERT(instr->representation().IsDouble());
1564 ASSERT(instr->left()->representation().IsDouble());
1565 ASSERT(instr->right()->representation().IsDouble());
1566 left = UseRegisterAtStart(instr->left());
1567 right = UseRegisterAtStart(instr->right());
1568 }
1569 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right);
1570 return DefineSameAsFirst(minmax);
1571}
1572
1573
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001574LInstruction* LChunkBuilder::DoPower(HPower* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001575 ASSERT(instr->representation().IsDouble());
1576 // We call a C function for double power. It can't trigger a GC.
1577 // We need to use fixed result register for the call.
1578 Representation exponent_type = instr->right()->representation();
1579 ASSERT(instr->left()->representation().IsDouble());
1580 LOperand* left = UseFixedDouble(instr->left(), xmm2);
1581 LOperand* right = exponent_type.IsDouble() ?
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001582 UseFixedDouble(instr->right(), xmm1) : UseFixed(instr->right(), rdx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001583 LPower* result = new(zone()) LPower(left, right);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001584 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001585 CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001586}
1587
1588
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001589LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1590 ASSERT(instr->representation().IsDouble());
1591 ASSERT(instr->global_object()->representation().IsTagged());
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001592 LOperand* global_object = UseTempRegister(instr->global_object());
1593 LOperand* scratch = TempRegister();
1594 LOperand* scratch2 = TempRegister();
1595 LOperand* scratch3 = TempRegister();
1596 LRandom* result = new(zone()) LRandom(
1597 global_object, scratch, scratch2, scratch3);
1598 return DefineFixedDouble(result, xmm1);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001599}
1600
1601
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001602LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001603 ASSERT(instr->left()->representation().IsTagged());
1604 ASSERT(instr->right()->representation().IsTagged());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001605 LOperand* left = UseFixed(instr->left(), rdx);
1606 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001607 LCmpT* result = new(zone()) LCmpT(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001608 return MarkAsCall(DefineFixed(result, rax), instr);
1609}
1610
1611
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001612LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1613 HCompareNumericAndBranch* instr) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001614 Representation r = instr->representation();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001615 if (r.IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001616 ASSERT(instr->left()->representation().Equals(r));
1617 ASSERT(instr->right()->representation().Equals(r));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001618 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001619 LOperand* right = UseOrConstantAtStart(instr->right());
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001620 return new(zone()) LCompareNumericAndBranch(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001621 } else {
1622 ASSERT(r.IsDouble());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001623 ASSERT(instr->left()->representation().IsDouble());
1624 ASSERT(instr->right()->representation().IsDouble());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001625 LOperand* left;
1626 LOperand* right;
1627 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1628 left = UseRegisterOrConstantAtStart(instr->left());
1629 right = UseRegisterOrConstantAtStart(instr->right());
1630 } else {
1631 left = UseRegisterAtStart(instr->left());
1632 right = UseRegisterAtStart(instr->right());
1633 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001634 return new(zone()) LCompareNumericAndBranch(left, right);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001635 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001636}
1637
1638
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001639LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1640 HCompareObjectEqAndBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001641 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1642 if (goto_instr != NULL) return goto_instr;
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001643 LOperand* left = UseRegisterAtStart(instr->left());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001644 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001645 return new(zone()) LCmpObjectEqAndBranch(left, right);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001646}
1647
1648
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001649LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1650 HCompareHoleAndBranch* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001651 LOperand* value = UseRegisterAtStart(instr->value());
1652 return new(zone()) LCmpHoleAndBranch(value);
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001653}
1654
1655
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001656LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001657 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001658 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001659}
1660
1661
erikcorry0ad885c2011-11-21 13:51:57 +00001662LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1663 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001664 LOperand* value = UseRegisterAtStart(instr->value());
erikcorry0ad885c2011-11-21 13:51:57 +00001665 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001666 return new(zone()) LIsStringAndBranch(value, temp);
erikcorry0ad885c2011-11-21 13:51:57 +00001667}
1668
1669
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001670LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001671 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001672 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001673}
1674
1675
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001676LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1677 HIsUndetectableAndBranch* instr) {
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001678 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001679 LOperand* value = UseRegisterAtStart(instr->value());
1680 LOperand* temp = TempRegister();
1681 return new(zone()) LIsUndetectableAndBranch(value, temp);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001682}
1683
1684
erikcorry0ad885c2011-11-21 13:51:57 +00001685LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1686 HStringCompareAndBranch* instr) {
1687
1688 ASSERT(instr->left()->representation().IsTagged());
1689 ASSERT(instr->right()->representation().IsTagged());
1690 LOperand* left = UseFixed(instr->left(), rdx);
1691 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001692 LStringCompareAndBranch* result =
1693 new(zone()) LStringCompareAndBranch(left, right);
erikcorry0ad885c2011-11-21 13:51:57 +00001694
1695 return MarkAsCall(result, instr);
1696}
1697
1698
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001699LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1700 HHasInstanceTypeAndBranch* instr) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001701 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001702 LOperand* value = UseRegisterAtStart(instr->value());
1703 return new(zone()) LHasInstanceTypeAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001704}
1705
1706
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001707LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1708 HGetCachedArrayIndex* instr) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001709 ASSERT(instr->value()->representation().IsTagged());
1710 LOperand* value = UseRegisterAtStart(instr->value());
1711
ulan@chromium.org812308e2012-02-29 15:58:45 +00001712 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001713}
1714
1715
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001716LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1717 HHasCachedArrayIndexAndBranch* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001718 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001719 LOperand* value = UseRegisterAtStart(instr->value());
1720 return new(zone()) LHasCachedArrayIndexAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001721}
1722
1723
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001724LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1725 HClassOfTestAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001726 LOperand* value = UseRegister(instr->value());
1727 return new(zone()) LClassOfTestAndBranch(value,
1728 TempRegister(),
1729 TempRegister());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001730}
1731
1732
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001733LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1734 LOperand* map = UseRegisterAtStart(instr->value());
1735 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1736}
1737
1738
whesse@chromium.org7b260152011-06-20 15:33:18 +00001739LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1740 LOperand* object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001741 return DefineAsRegister(new(zone()) LElementsKind(object));
whesse@chromium.org7b260152011-06-20 15:33:18 +00001742}
1743
1744
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001745LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001746 LOperand* object = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001747 LValueOf* result = new(zone()) LValueOf(object);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001748 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001749}
1750
1751
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001752LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1753 LOperand* object = UseFixed(instr->value(), rax);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001754 LDateField* result = new(zone()) LDateField(object, instr->index());
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001755 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001756}
1757
1758
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001759LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1760 LOperand* string = UseRegister(instr->string());
1761 LOperand* index = UseRegister(instr->index());
1762 ASSERT(rcx.is_byte_register());
1763 LOperand* value = UseFixed(instr->value(), rcx);
1764 LSeqStringSetChar* result =
1765 new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1766 return DefineSameAsFirst(result);
1767}
1768
1769
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001770LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001771 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1772 LOperand* length = Use(instr->length());
1773 return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001774}
1775
1776
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001777LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1778 HBoundsCheckBaseIndexInformation* instr) {
1779 UNREACHABLE();
1780 return NULL;
1781}
1782
1783
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00001784LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1785 // The control instruction marking the end of a block that completed
1786 // abruptly (e.g., threw an exception). There is nothing specific to do.
1787 return NULL;
1788}
1789
1790
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001791LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001792 LOperand* value = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001793 return MarkAsCall(new(zone()) LThrow(value), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001794}
1795
1796
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001797LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1798 return NULL;
1799}
1800
1801
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001802LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1803 // All HForceRepresentation instructions should be eliminated in the
1804 // representation change phase of Hydrogen.
1805 UNREACHABLE();
1806 return NULL;
1807}
1808
1809
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001810LInstruction* LChunkBuilder::DoChange(HChange* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001811 Representation from = instr->from();
1812 Representation to = instr->to();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001813 if (from.IsSmi()) {
1814 if (to.IsTagged()) {
1815 LOperand* value = UseRegister(instr->value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001816 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1817 }
1818 from = Representation::Tagged();
1819 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001820 // Only mark conversions that might need to allocate as calling rather than
1821 // all changes. This makes simple, non-allocating conversion not have to force
1822 // building a stack frame.
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001823 if (from.IsTagged()) {
1824 if (to.IsDouble()) {
1825 LOperand* value = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001826 LNumberUntagD* res = new(zone()) LNumberUntagD(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001827 return AssignEnvironment(DefineAsRegister(res));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001828 } else if (to.IsSmi()) {
1829 HValue* val = instr->value();
1830 LOperand* value = UseRegister(val);
1831 if (val->type().IsSmi()) {
1832 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1833 }
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001834 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001835 } else {
1836 ASSERT(to.IsInteger32());
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001837 HValue* val = instr->value();
1838 LOperand* value = UseRegister(val);
1839 if (val->type().IsSmi() || val->representation().IsSmi()) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001840 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001841 } else {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001842 bool truncating = instr->CanTruncateToInt32();
1843 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001844 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001845 return AssignEnvironment(DefineSameAsFirst(res));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001846 }
1847 }
1848 } else if (from.IsDouble()) {
1849 if (to.IsTagged()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001850 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001851 LOperand* value = UseRegister(instr->value());
1852 LOperand* temp = TempRegister();
1853
1854 // Make sure that temp and result_temp are different registers.
1855 LUnallocated* result_temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001856 LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001857 return AssignPointerMap(Define(result, result_temp));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001858 } else if (to.IsSmi()) {
1859 LOperand* value = UseRegister(instr->value());
1860 return AssignEnvironment(
1861 DefineAsRegister(new(zone()) LDoubleToSmi(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001862 } else {
1863 ASSERT(to.IsInteger32());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001864 LOperand* value = UseRegister(instr->value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001865 return AssignEnvironment(
1866 DefineAsRegister(new(zone()) LDoubleToI(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001867 }
1868 } else if (from.IsInteger32()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001869 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001870 if (to.IsTagged()) {
1871 HValue* val = instr->value();
1872 LOperand* value = UseRegister(val);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001873 if (val->CheckFlag(HInstruction::kUint32)) {
1874 LOperand* temp = FixedTemp(xmm1);
1875 LNumberTagU* result = new(zone()) LNumberTagU(value, temp);
1876 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1877 } else if (val->HasRange() && val->range()->IsInSmiRange()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001878 return DefineSameAsFirst(new(zone()) LSmiTag(value));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001879 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001880 LNumberTagI* result = new(zone()) LNumberTagI(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001881 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1882 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001883 } else if (to.IsSmi()) {
1884 HValue* val = instr->value();
1885 LOperand* value = UseRegister(val);
machenbach@chromium.orged29eb22013-10-31 13:30:00 +00001886 LInstruction* result = NULL;
1887 if (val->CheckFlag(HInstruction::kUint32)) {
1888 result = DefineAsRegister(new(zone()) LUint32ToSmi(value));
1889 if (val->HasRange() && val->range()->IsInSmiRange() &&
1890 val->range()->upper() != kMaxInt) {
1891 return result;
1892 }
1893 } else {
1894 result = DefineAsRegister(new(zone()) LInteger32ToSmi(value));
1895 if (val->HasRange() && val->range()->IsInSmiRange()) {
1896 return result;
1897 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001898 }
1899 return AssignEnvironment(result);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001900 } else {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001901 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1902 LOperand* temp = FixedTemp(xmm1);
1903 return DefineAsRegister(
1904 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
1905 } else {
1906 ASSERT(to.IsDouble());
1907 LOperand* value = Use(instr->value());
1908 return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
1909 }
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001910 }
1911 }
1912 UNREACHABLE();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001913 return NULL;
1914}
1915
1916
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001917LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001918 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001919 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001920}
1921
1922
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001923LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1924 LOperand* value = UseRegisterAtStart(instr->value());
1925 return AssignEnvironment(new(zone()) LCheckSmi(value));
1926}
1927
1928
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001929LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001930 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001931 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001932 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001933}
1934
1935
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00001936LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001937 LOperand* value = UseRegisterAtStart(instr->value());
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00001938 return AssignEnvironment(new(zone()) LCheckValue(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001939}
1940
1941
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001942LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001943 LOperand* value = NULL;
danno@chromium.org59400602013-08-13 17:09:37 +00001944 if (!instr->CanOmitMapChecks()) {
1945 value = UseRegisterAtStart(instr->value());
1946 if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
1947 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001948 LCheckMaps* result = new(zone()) LCheckMaps(value);
danno@chromium.org59400602013-08-13 17:09:37 +00001949 if (!instr->CanOmitMapChecks()) {
1950 AssignEnvironment(result);
1951 if (instr->has_migration_target()) return AssignPointerMap(result);
1952 }
1953 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001954}
1955
1956
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001957LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1958 HValue* value = instr->value();
1959 Representation input_rep = value->representation();
1960 LOperand* reg = UseRegister(value);
1961 if (input_rep.IsDouble()) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001962 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001963 } else if (input_rep.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001964 return DefineSameAsFirst(new(zone()) LClampIToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001965 } else {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001966 ASSERT(input_rep.IsSmiOrTagged());
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001967 // Register allocator doesn't (yet) support allocation of double
1968 // temps. Reserve xmm1 explicitly.
ulan@chromium.org812308e2012-02-29 15:58:45 +00001969 LClampTToUint8* result = new(zone()) LClampTToUint8(reg,
ulan@chromium.org812308e2012-02-29 15:58:45 +00001970 FixedTemp(xmm1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001971 return AssignEnvironment(DefineSameAsFirst(result));
1972 }
1973}
1974
1975
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001976LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001977 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1978 return new(zone()) LReturn(UseFixed(instr->value(), rax),
1979 parameter_count);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001980}
1981
1982
1983LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1984 Representation r = instr->representation();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001985 if (r.IsSmi()) {
1986 return DefineAsRegister(new(zone()) LConstantS);
1987 } else if (r.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001988 return DefineAsRegister(new(zone()) LConstantI);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001989 } else if (r.IsDouble()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001990 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001991 return DefineAsRegister(new(zone()) LConstantD(temp));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001992 } else if (r.IsExternal()) {
1993 return DefineAsRegister(new(zone()) LConstantE);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001994 } else if (r.IsTagged()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001995 return DefineAsRegister(new(zone()) LConstantT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001996 } else {
1997 UNREACHABLE();
1998 return NULL;
1999 }
2000}
2001
2002
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002003LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002004 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002005 return instr->RequiresHoleCheck()
ager@chromium.org378b34e2011-01-28 08:04:38 +00002006 ? AssignEnvironment(DefineAsRegister(result))
2007 : DefineAsRegister(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002008}
2009
2010
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002011LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
2012 LOperand* global_object = UseFixed(instr->global_object(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002013 LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002014 return MarkAsCall(DefineFixed(result, rax), instr);
2015}
2016
2017
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002018LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00002019 LOperand* value = UseRegister(instr->value());
2020 // Use a temp to avoid reloading the cell value address in the case where
2021 // we perform a hole check.
2022 return instr->RequiresHoleCheck()
ulan@chromium.org812308e2012-02-29 15:58:45 +00002023 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
2024 : new(zone()) LStoreGlobalCell(value, NULL);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002025}
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002026
2027
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002028LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
2029 LOperand* global_object = UseFixed(instr->global_object(), rdx);
2030 LOperand* value = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002031 LStoreGlobalGeneric* result = new(zone()) LStoreGlobalGeneric(global_object,
2032 value);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002033 return MarkAsCall(result, instr);
2034}
2035
2036
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002037LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002038 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002039 LInstruction* result =
2040 DefineAsRegister(new(zone()) LLoadContextSlot(context));
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002041 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002042}
2043
2044
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002045LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002046 LOperand* context;
2047 LOperand* value;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002048 LOperand* temp;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002049 if (instr->NeedsWriteBarrier()) {
2050 context = UseTempRegister(instr->context());
2051 value = UseTempRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002052 temp = TempRegister();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002053 } else {
2054 context = UseRegister(instr->context());
2055 value = UseRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002056 temp = NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002057 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002058 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002059 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002060}
2061
2062
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002063LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00002064 // Use the special mov rax, moffs64 encoding for external
2065 // memory accesses with 64-bit word-sized values.
2066 if (instr->access().IsExternalMemory() &&
2067 instr->access().offset() == 0 &&
2068 (instr->access().representation().IsSmi() ||
2069 instr->access().representation().IsTagged() ||
2070 instr->access().representation().IsHeapObject() ||
2071 instr->access().representation().IsExternal())) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002072 LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
2073 return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
2074 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002075 LOperand* obj = UseRegisterAtStart(instr->object());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002076 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002077}
2078
2079
2080LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002081 LOperand* object = UseFixed(instr->object(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002082 LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(object);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002083 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002084}
2085
2086
2087LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2088 HLoadFunctionPrototype* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002089 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002090 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002091}
2092
2093
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002094LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2095 return DefineAsRegister(new(zone()) LLoadRoot);
2096}
2097
2098
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002099LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2100 HLoadExternalArrayPointer* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002101 LOperand* input = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002102 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002103}
2104
2105
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002106LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002107 ASSERT(instr->key()->representation().IsInteger32());
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002108 ElementsKind elements_kind = instr->elements_kind();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002109 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002110 LLoadKeyed* result = NULL;
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002111
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002112 if (!instr->is_external()) {
2113 LOperand* obj = UseRegisterAtStart(instr->elements());
2114 result = new(zone()) LLoadKeyed(obj, key);
2115 } else {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002116 ASSERT(
2117 (instr->representation().IsInteger32() &&
2118 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2119 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2120 (instr->representation().IsDouble() &&
2121 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2122 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002123 LOperand* external_pointer = UseRegister(instr->elements());
2124 result = new(zone()) LLoadKeyed(external_pointer, key);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002125 }
2126
2127 DefineAsRegister(result);
2128 bool can_deoptimize = instr->RequiresHoleCheck() ||
2129 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002130 // An unsigned int array load might overflow and cause a deopt, make sure it
2131 // has an environment.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002132 return can_deoptimize ? AssignEnvironment(result) : result;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002133}
2134
2135
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002136LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002137 LOperand* object = UseFixed(instr->object(), rdx);
2138 LOperand* key = UseFixed(instr->key(), rax);
2139
ulan@chromium.org812308e2012-02-29 15:58:45 +00002140 LLoadKeyedGeneric* result = new(zone()) LLoadKeyedGeneric(object, key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002141 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002142}
2143
2144
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002145LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002146 ElementsKind elements_kind = instr->elements_kind();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002147
2148 if (!instr->is_external()) {
2149 ASSERT(instr->elements()->representation().IsTagged());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002150 bool needs_write_barrier = instr->NeedsWriteBarrier();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002151 LOperand* object = NULL;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002152 LOperand* key = NULL;
2153 LOperand* val = NULL;
2154
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002155 if (instr->value()->representation().IsDouble()) {
2156 object = UseRegisterAtStart(instr->elements());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002157 val = UseTempRegister(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002158 key = UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002159 } else {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002160 ASSERT(instr->value()->representation().IsSmiOrTagged());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002161 object = UseTempRegister(instr->elements());
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002162 if (needs_write_barrier) {
2163 val = UseTempRegister(instr->value());
2164 key = UseTempRegister(instr->key());
2165 } else {
danno@chromium.orgf005df62013-04-30 16:36:45 +00002166 val = UseRegisterOrConstantAtStart(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002167 key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002168 }
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002169 }
2170
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002171 return new(zone()) LStoreKeyed(object, key, val);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002172 }
2173
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002174 ASSERT(
2175 (instr->value()->representation().IsInteger32() &&
2176 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2177 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2178 (instr->value()->representation().IsDouble() &&
2179 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2180 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2181 ASSERT(instr->elements()->representation().IsExternal());
2182 bool val_is_temp_register =
2183 elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2184 elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2185 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2186 : UseRegister(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002187 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002188 LOperand* external_pointer = UseRegister(instr->elements());
2189 return new(zone()) LStoreKeyed(external_pointer, key, val);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002190}
2191
2192
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002193LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002194 LOperand* object = UseFixed(instr->object(), rdx);
2195 LOperand* key = UseFixed(instr->key(), rcx);
2196 LOperand* value = UseFixed(instr->value(), rax);
2197
2198 ASSERT(instr->object()->representation().IsTagged());
2199 ASSERT(instr->key()->representation().IsTagged());
2200 ASSERT(instr->value()->representation().IsTagged());
2201
ulan@chromium.org812308e2012-02-29 15:58:45 +00002202 LStoreKeyedGeneric* result =
2203 new(zone()) LStoreKeyedGeneric(object, key, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002204 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002205}
2206
2207
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002208LInstruction* LChunkBuilder::DoTransitionElementsKind(
2209 HTransitionElementsKind* instr) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002210 LOperand* object = UseRegister(instr->object());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002211 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002212 LOperand* object = UseRegister(instr->object());
2213 LOperand* new_map_reg = TempRegister();
2214 LOperand* temp_reg = TempRegister();
2215 LTransitionElementsKind* result =
ulan@chromium.org812308e2012-02-29 15:58:45 +00002216 new(zone()) LTransitionElementsKind(object, new_map_reg, temp_reg);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002217 return result;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002218 } else {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002219 LTransitionElementsKind* result =
2220 new(zone()) LTransitionElementsKind(object, NULL, NULL);
2221 return AssignPointerMap(result);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002222 }
2223}
2224
2225
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002226LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2227 HTrapAllocationMemento* instr) {
2228 LOperand* object = UseRegister(instr->object());
2229 LOperand* temp = TempRegister();
2230 LTrapAllocationMemento* result =
2231 new(zone()) LTrapAllocationMemento(object, temp);
2232 return AssignEnvironment(result);
2233}
2234
2235
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002236LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002237 bool is_in_object = instr->access().IsInobject();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002238 bool is_external_location = instr->access().IsExternalMemory() &&
2239 instr->access().offset() == 0;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002240 bool needs_write_barrier = instr->NeedsWriteBarrier();
danno@chromium.org59400602013-08-13 17:09:37 +00002241 bool needs_write_barrier_for_map = instr->has_transition() &&
verwaest@chromium.org37141392012-05-31 13:27:02 +00002242 instr->NeedsWriteBarrierForMap();
ager@chromium.org378b34e2011-01-28 08:04:38 +00002243
verwaest@chromium.org37141392012-05-31 13:27:02 +00002244 LOperand* obj;
2245 if (needs_write_barrier) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002246 obj = is_in_object
verwaest@chromium.org37141392012-05-31 13:27:02 +00002247 ? UseRegister(instr->object())
2248 : UseTempRegister(instr->object());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002249 } else if (is_external_location) {
2250 ASSERT(!is_in_object);
2251 ASSERT(!needs_write_barrier);
2252 ASSERT(!needs_write_barrier_for_map);
2253 obj = UseRegisterOrConstant(instr->object());
verwaest@chromium.org37141392012-05-31 13:27:02 +00002254 } else {
2255 obj = needs_write_barrier_for_map
2256 ? UseRegister(instr->object())
2257 : UseRegisterAtStart(instr->object());
2258 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002259
danno@chromium.orgf005df62013-04-30 16:36:45 +00002260 bool can_be_constant = instr->value()->IsConstant() &&
2261 HConstant::cast(instr->value())->NotInNewSpace() &&
2262 !(FLAG_track_double_fields && instr->field_representation().IsDouble());
2263
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002264 LOperand* val;
2265 if (needs_write_barrier) {
2266 val = UseTempRegister(instr->value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002267 } else if (is_external_location) {
2268 val = UseFixed(instr->value(), rax);
danno@chromium.orgf005df62013-04-30 16:36:45 +00002269 } else if (can_be_constant) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002270 val = UseRegisterOrConstant(instr->value());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002271 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) {
2272 val = UseTempRegister(instr->value());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002273 } else if (FLAG_track_double_fields &&
2274 instr->field_representation().IsDouble()) {
2275 val = UseRegisterAtStart(instr->value());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002276 } else {
2277 val = UseRegister(instr->value());
2278 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002279
2280 // We only need a scratch register if we have a write barrier or we
2281 // have a store into the properties array (not in-object-property).
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002282 LOperand* temp = (!is_in_object || needs_write_barrier ||
verwaest@chromium.org37141392012-05-31 13:27:02 +00002283 needs_write_barrier_for_map) ? TempRegister() : NULL;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002284
danno@chromium.orgf005df62013-04-30 16:36:45 +00002285 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002286 if (FLAG_track_heap_object_fields &&
2287 instr->field_representation().IsHeapObject()) {
2288 if (!instr->value()->type().IsHeapObject()) {
2289 return AssignEnvironment(result);
2290 }
danno@chromium.orgf005df62013-04-30 16:36:45 +00002291 }
2292 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002293}
2294
2295
2296LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002297 LOperand* object = UseFixed(instr->object(), rdx);
2298 LOperand* value = UseFixed(instr->value(), rax);
2299
ulan@chromium.org812308e2012-02-29 15:58:45 +00002300 LStoreNamedGeneric* result = new(zone()) LStoreNamedGeneric(object, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002301 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002302}
2303
2304
danno@chromium.org160a7b02011-04-18 15:51:38 +00002305LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2306 LOperand* left = UseOrConstantAtStart(instr->left());
2307 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002308 return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), rax),
2309 instr);
danno@chromium.org160a7b02011-04-18 15:51:38 +00002310}
2311
2312
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002313LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
ricow@chromium.org4668a2c2011-08-29 10:41:00 +00002314 LOperand* string = UseTempRegister(instr->string());
2315 LOperand* index = UseTempRegister(instr->index());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002316 LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002317 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002318}
2319
2320
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002321LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2322 LOperand* char_code = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002323 LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002324 return AssignPointerMap(DefineAsRegister(result));
2325}
2326
2327
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002328LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2329 info()->MarkAsDeferredCalling();
danno@chromium.orgf005df62013-04-30 16:36:45 +00002330 LOperand* size = instr->size()->IsConstant()
2331 ? UseConstant(instr->size())
2332 : UseTempRegister(instr->size());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002333 LOperand* temp = TempRegister();
2334 LAllocate* result = new(zone()) LAllocate(size, temp);
2335 return AssignPointerMap(DefineAsRegister(result));
2336}
2337
2338
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002339LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002340 return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002341}
2342
2343
2344LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002345 return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002346}
2347
2348
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002349LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002350 ASSERT(argument_count_ == 0);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002351 allocator_->MarkAsOsrEntry();
2352 current_block_->last_environment()->set_ast_id(instr->ast_id());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002353 return AssignEnvironment(new(zone()) LOsrEntry);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002354}
2355
2356
2357LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002358 LParameter* result = new(zone()) LParameter;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002359 if (instr->kind() == HParameter::STACK_PARAMETER) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002360 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2361 return DefineAsSpilled(result, spill_index);
2362 } else {
2363 ASSERT(info()->IsStub());
2364 CodeStubInterfaceDescriptor* descriptor =
2365 info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002366 int index = static_cast<int>(instr->index());
2367 Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002368 return DefineFixed(result, reg);
2369 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002370}
2371
2372
2373LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +00002374 // Use an index that corresponds to the location in the unoptimized frame,
2375 // which the optimized frame will subsume.
2376 int env_index = instr->index();
2377 int spill_index = 0;
2378 if (instr->environment()->is_parameter_index(env_index)) {
2379 spill_index = chunk()->GetParameterStackSlot(env_index);
2380 } else {
2381 spill_index = env_index - instr->environment()->first_local_index();
2382 if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2383 Abort(kTooManySpillSlotsNeededForOSR);
2384 spill_index = 0;
2385 }
ager@chromium.org04921a82011-06-27 13:21:41 +00002386 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002387 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002388}
2389
2390
2391LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002392 return MarkAsCall(DefineFixed(new(zone()) LCallStub, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002393}
2394
2395
2396LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002397 // There are no real uses of the arguments object.
2398 // arguments.length and element access are supported directly on
2399 // stack arguments, and any real arguments object use causes a bailout.
2400 // So this value is never used.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002401 return NULL;
2402}
2403
2404
danno@chromium.org59400602013-08-13 17:09:37 +00002405LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002406 instr->ReplayEnvironment(current_block_->last_environment());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00002407
danno@chromium.org59400602013-08-13 17:09:37 +00002408 // There are no real uses of a captured object.
2409 return NULL;
2410}
2411
2412
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002413LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002414 info()->MarkAsRequiresFrame();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002415 LOperand* args = UseRegister(instr->arguments());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002416 LOperand* length;
2417 LOperand* index;
2418 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2419 length = UseRegisterOrConstant(instr->length());
2420 index = UseOrConstant(instr->index());
2421 } else {
2422 length = UseTempRegister(instr->length());
2423 index = Use(instr->index());
2424 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002425 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002426}
2427
2428
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002429LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2430 LOperand* object = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002431 LToFastProperties* result = new(zone()) LToFastProperties(object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002432 return MarkAsCall(DefineFixed(result, rax), instr);
2433}
2434
2435
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002436LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002437 LTypeof* result = new(zone()) LTypeof(UseAtStart(instr->value()));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002438 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002439}
2440
2441
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002442LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002443 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002444}
2445
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002446
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002447LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2448 HIsConstructCallAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002449 return new(zone()) LIsConstructCallAndBranch(TempRegister());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002450}
2451
2452
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002453LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002454 instr->ReplayEnvironment(current_block_->last_environment());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002455
2456 // If there is an instruction pending deoptimization environment create a
2457 // lazy bailout instruction to capture the environment.
fschneider@chromium.org1df6b472011-01-26 08:23:03 +00002458 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002459 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002460 LInstruction* result = AssignEnvironment(lazy_bailout);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002461 // Store the lazy deopt environment with the instruction if needed. Right
2462 // now it is only used for LInstanceOfKnownGlobal.
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00002463 instruction_pending_deoptimization_environment_->
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002464 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2465 instruction_pending_deoptimization_environment_ = NULL;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002466 pending_deoptimization_ast_id_ = BailoutId::None();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002467 return result;
2468 }
2469
2470 return NULL;
2471}
2472
2473
2474LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002475 info()->MarkAsDeferredCalling();
ager@chromium.org04921a82011-06-27 13:21:41 +00002476 if (instr->is_function_entry()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002477 return MarkAsCall(new(zone()) LStackCheck, instr);
ager@chromium.org04921a82011-06-27 13:21:41 +00002478 } else {
2479 ASSERT(instr->is_backwards_branch());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002480 return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
ager@chromium.org04921a82011-06-27 13:21:41 +00002481 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002482}
2483
2484
2485LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002486 HEnvironment* outer = current_block_->last_environment();
2487 HConstant* undefined = graph()->GetConstantUndefined();
2488 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002489 instr->arguments_count(),
ager@chromium.org378b34e2011-01-28 08:04:38 +00002490 instr->function(),
danno@chromium.org40cb8782011-05-25 07:58:50 +00002491 undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002492 instr->inlining_kind(),
2493 instr->undefined_receiver());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002494 // Only replay binding of arguments object if it wasn't removed from graph.
2495 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2496 inner->Bind(instr->arguments_var(), instr->arguments_object());
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00002497 }
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002498 inner->set_entry(instr);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002499 current_block_->UpdateEnvironment(inner);
2500 chunk_->AddInlinedClosure(instr->closure());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002501 return NULL;
2502}
2503
2504
2505LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002506 LInstruction* pop = NULL;
2507
2508 HEnvironment* env = current_block_->last_environment();
2509
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002510 if (env->entry()->arguments_pushed()) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002511 int argument_count = env->arguments_environment()->parameter_count();
2512 pop = new(zone()) LDrop(argument_count);
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00002513 ASSERT(instr->argument_delta() == -argument_count);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002514 }
2515
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002516 HEnvironment* outer = current_block_->last_environment()->
2517 DiscardInlined(false);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002518 current_block_->UpdateEnvironment(outer);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002519
2520 return pop;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002521}
2522
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002523
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002524LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2525 LOperand* object = UseFixed(instr->enumerable(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002526 LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002527 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2528}
2529
2530
2531LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2532 LOperand* map = UseRegister(instr->map());
2533 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002534 new(zone()) LForInCacheArray(map)));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002535}
2536
2537
2538LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2539 LOperand* value = UseRegisterAtStart(instr->value());
2540 LOperand* map = UseRegisterAtStart(instr->map());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002541 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002542}
2543
2544
2545LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2546 LOperand* object = UseRegister(instr->object());
2547 LOperand* index = UseTempRegister(instr->index());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002548 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002549}
2550
2551
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002552} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002553
2554#endif // V8_TARGET_ARCH_X64