blob: b911c48252eb440da9979350f174be5e9c22125c [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());
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000784 LOperand* context = UseFixed(instr->context(), rsi);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000785 LOperand* left_operand = UseFixed(left, rdx);
786 LOperand* right_operand = UseFixed(right, rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +0000787 LArithmeticT* result =
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000788 new(zone()) LArithmeticT(op, context, left_operand, right_operand);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000789 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000790}
791
792
793void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
794 ASSERT(is_building());
795 current_block_ = block;
796 next_block_ = next_block;
797 if (block->IsStartBlock()) {
798 block->UpdateEnvironment(graph_->start_environment());
799 argument_count_ = 0;
800 } else if (block->predecessors()->length() == 1) {
801 // We have a single predecessor => copy environment and outgoing
802 // argument count from the predecessor.
803 ASSERT(block->phis()->length() == 0);
804 HBasicBlock* pred = block->predecessors()->at(0);
805 HEnvironment* last_environment = pred->last_environment();
806 ASSERT(last_environment != NULL);
807 // Only copy the environment, if it is later used again.
808 if (pred->end()->SecondSuccessor() == NULL) {
809 ASSERT(pred->end()->FirstSuccessor() == block);
810 } else {
811 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
812 pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
813 last_environment = last_environment->Copy();
814 }
815 }
816 block->UpdateEnvironment(last_environment);
817 ASSERT(pred->argument_count() >= 0);
818 argument_count_ = pred->argument_count();
819 } else {
820 // We are at a state join => process phis.
821 HBasicBlock* pred = block->predecessors()->at(0);
822 // No need to copy the environment, it cannot be used later.
823 HEnvironment* last_environment = pred->last_environment();
824 for (int i = 0; i < block->phis()->length(); ++i) {
825 HPhi* phi = block->phis()->at(i);
danno@chromium.orgad75d6f2013-08-12 16:57:59 +0000826 if (phi->HasMergedIndex()) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000827 last_environment->SetValueAt(phi->merged_index(), phi);
828 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000829 }
830 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +0000831 if (block->deleted_phis()->at(i) < last_environment->length()) {
832 last_environment->SetValueAt(block->deleted_phis()->at(i),
833 graph_->GetConstantUndefined());
834 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000835 }
836 block->UpdateEnvironment(last_environment);
837 // Pick up the outgoing argument count of one of the predecessors.
838 argument_count_ = pred->argument_count();
839 }
840 HInstruction* current = block->first();
841 int start = chunk_->instructions()->length();
842 while (current != NULL && !is_aborted()) {
843 // Code for constants in registers is generated lazily.
844 if (!current->EmitAtUses()) {
845 VisitInstruction(current);
846 }
847 current = current->next();
848 }
849 int end = chunk_->instructions()->length() - 1;
850 if (end >= start) {
851 block->set_first_instruction_index(start);
852 block->set_last_instruction_index(end);
853 }
854 block->set_argument_count(argument_count_);
855 next_block_ = NULL;
856 current_block_ = NULL;
857}
858
859
860void LChunkBuilder::VisitInstruction(HInstruction* current) {
861 HInstruction* old_current = current_instruction_;
862 current_instruction_ = current;
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000863
864 LInstruction* instr = NULL;
865 if (current->CanReplaceWithDummyUses()) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000866 if (current->OperandCount() == 0) {
867 instr = DefineAsRegister(new(zone()) LDummy());
868 } else {
869 instr = DefineAsRegister(new(zone())
870 LDummyUse(UseAny(current->OperandAt(0))));
871 }
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000872 for (int i = 1; i < current->OperandCount(); ++i) {
873 LInstruction* dummy =
874 new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
875 dummy->set_hydrogen_value(current);
876 chunk_->AddInstruction(dummy, current_block_);
877 }
878 } else {
879 instr = current->CompileToLithium(this);
880 }
881
882 argument_count_ += current->argument_delta();
883 ASSERT(argument_count_ >= 0);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000884
885 if (instr != NULL) {
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000886 // Associate the hydrogen instruction first, since we may need it for
887 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
888 instr->set_hydrogen_value(current);
889
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000890#if DEBUG
891 // Make sure that the lithium instruction has either no fixed register
892 // constraints in temps or the result OR no uses that are only used at
893 // start. If this invariant doesn't hold, the register allocator can decide
894 // to insert a split of a range immediately before the instruction due to an
895 // already allocated register needing to be used for the instruction's fixed
896 // register constraint. In this case, The register allocator won't see an
897 // interference between the split child and the use-at-start (it would if
898 // the it was just a plain use), so it is free to move the split child into
899 // the same register that is used for the use-at-start.
900 // See https://code.google.com/p/chromium/issues/detail?id=201590
901 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
902 int fixed = 0;
903 int used_at_start = 0;
904 for (UseIterator it(instr); !it.Done(); it.Advance()) {
905 LUnallocated* operand = LUnallocated::cast(it.Current());
906 if (operand->IsUsedAtStart()) ++used_at_start;
907 }
908 if (instr->Output() != NULL) {
909 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
910 }
911 for (TempIterator it(instr); !it.Done(); it.Advance()) {
912 LUnallocated* operand = LUnallocated::cast(it.Current());
913 if (operand->HasFixedPolicy()) ++fixed;
914 }
915 ASSERT(fixed == 0 || used_at_start == 0);
916 }
917#endif
918
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000919 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
920 instr = AssignPointerMap(instr);
921 }
922 if (FLAG_stress_environments && !instr->HasEnvironment()) {
923 instr = AssignEnvironment(instr);
924 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000925 chunk_->AddInstruction(instr, current_block_);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000926 }
927 current_instruction_ = old_current;
928}
929
930
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000931LEnvironment* LChunkBuilder::CreateEnvironment(
932 HEnvironment* hydrogen_env,
danno@chromium.org59400602013-08-13 17:09:37 +0000933 int* argument_index_accumulator,
934 ZoneList<HValue*>* objects_to_materialize) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000935 if (hydrogen_env == NULL) return NULL;
936
danno@chromium.org59400602013-08-13 17:09:37 +0000937 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer(),
938 argument_index_accumulator,
939 objects_to_materialize);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000940 BailoutId ast_id = hydrogen_env->ast_id();
941 ASSERT(!ast_id.IsNone() ||
ulan@chromium.org967e2702012-02-28 09:49:15 +0000942 hydrogen_env->frame_type() != JS_FUNCTION);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000943 int value_count = hydrogen_env->length() - hydrogen_env->specials_count();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000944 LEnvironment* result = new(zone()) LEnvironment(
945 hydrogen_env->closure(),
946 hydrogen_env->frame_type(),
947 ast_id,
948 hydrogen_env->parameter_count(),
949 argument_count_,
950 value_count,
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000951 outer,
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000952 hydrogen_env->entry(),
rossberg@chromium.org400388e2012-06-06 09:29:22 +0000953 zone());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000954 int argument_index = *argument_index_accumulator;
danno@chromium.org59400602013-08-13 17:09:37 +0000955 int object_index = objects_to_materialize->length();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000956 for (int i = 0; i < hydrogen_env->length(); ++i) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000957 if (hydrogen_env->is_special_index(i)) continue;
958
danno@chromium.org59400602013-08-13 17:09:37 +0000959 LOperand* op;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000960 HValue* value = hydrogen_env->values()->at(i);
danno@chromium.org59400602013-08-13 17:09:37 +0000961 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
962 objects_to_materialize->Add(value, zone());
963 op = LEnvironment::materialization_marker();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000964 } else if (value->IsPushArgument()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000965 op = new(zone()) LArgument(argument_index++);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000966 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000967 op = UseAny(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000968 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000969 result->AddValue(op,
970 value->representation(),
971 value->CheckFlag(HInstruction::kUint32));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000972 }
973
danno@chromium.org59400602013-08-13 17:09:37 +0000974 for (int i = object_index; i < objects_to_materialize->length(); ++i) {
975 HValue* object_to_materialize = objects_to_materialize->at(i);
976 int previously_materialized_object = -1;
977 for (int prev = 0; prev < i; ++prev) {
978 if (objects_to_materialize->at(prev) == objects_to_materialize->at(i)) {
979 previously_materialized_object = prev;
980 break;
981 }
982 }
983 int length = object_to_materialize->OperandCount();
984 bool is_arguments = object_to_materialize->IsArgumentsObject();
985 if (previously_materialized_object >= 0) {
986 result->AddDuplicateObject(previously_materialized_object);
987 continue;
988 } else {
989 result->AddNewObject(is_arguments ? length - 1 : length, is_arguments);
990 }
991 for (int i = is_arguments ? 1 : 0; i < length; ++i) {
992 LOperand* op;
993 HValue* value = object_to_materialize->OperandAt(i);
994 if (value->IsArgumentsObject() || value->IsCapturedObject()) {
995 objects_to_materialize->Add(value, zone());
996 op = LEnvironment::materialization_marker();
997 } else {
998 ASSERT(!value->IsPushArgument());
999 op = UseAny(value);
1000 }
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001001 result->AddValue(op,
1002 value->representation(),
1003 value->CheckFlag(HInstruction::kUint32));
1004 }
1005 }
1006
ulan@chromium.org967e2702012-02-28 09:49:15 +00001007 if (hydrogen_env->frame_type() == JS_FUNCTION) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001008 *argument_index_accumulator = argument_index;
1009 }
1010
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001011 return result;
1012}
1013
1014
1015LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001016 return new(zone()) LGoto(instr->FirstSuccessor());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001017}
1018
1019
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +00001020LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1021 return new(zone()) LDebugBreak();
1022}
1023
1024
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001025LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001026 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1027 if (goto_instr != NULL) return goto_instr;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001028
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001029 HValue* value = instr->value();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001030 LBranch* result = new(zone()) LBranch(UseRegister(value));
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001031 // Tagged values that are not known smis or booleans require a
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001032 // deoptimization environment. If the instruction is generic no
1033 // environment is needed since all cases are handled.
1034 ToBooleanStub::Types expected = instr->expected_input_types();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001035 Representation rep = value->representation();
1036 HType type = value->type();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001037 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() &&
1038 !expected.IsGeneric()) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001039 return AssignEnvironment(result);
1040 }
1041 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001042}
1043
1044
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001045LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001046 ASSERT(instr->value()->representation().IsTagged());
1047 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001048 return new(zone()) LCmpMapAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001049}
1050
1051
1052LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001053 info()->MarkAsRequiresFrame();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001054 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value())));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001055}
1056
1057
1058LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00001059 info()->MarkAsRequiresFrame();
danno@chromium.orgb2a1c072012-03-23 15:47:56 +00001060 return DefineAsRegister(new(zone()) LArgumentsElements);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001061}
1062
1063
1064LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001065 LOperand* left = UseFixed(instr->left(), rax);
1066 LOperand* right = UseFixed(instr->right(), rdx);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001067 LOperand* context = UseFixed(instr->context(), rsi);
1068 LInstanceOf* result = new(zone()) LInstanceOf(context, left, right);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001069 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001070}
1071
1072
1073LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1074 HInstanceOfKnownGlobal* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001075 LInstanceOfKnownGlobal* result =
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001076 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->context(), rsi),
1077 UseFixed(instr->left(), rax),
ulan@chromium.org812308e2012-02-29 15:58:45 +00001078 FixedTemp(rdi));
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001079 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001080}
1081
1082
yangguo@chromium.org154ff992012-03-13 08:09:54 +00001083LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
1084 LOperand* receiver = UseRegister(instr->receiver());
1085 LOperand* function = UseRegisterAtStart(instr->function());
1086 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
1087 return AssignEnvironment(DefineSameAsFirst(result));
1088}
1089
1090
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001091LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001092 LOperand* function = UseFixed(instr->function(), rdi);
1093 LOperand* receiver = UseFixed(instr->receiver(), rax);
1094 LOperand* length = UseFixed(instr->length(), rbx);
1095 LOperand* elements = UseFixed(instr->elements(), rcx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001096 LApplyArguments* result = new(zone()) LApplyArguments(function,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001097 receiver,
1098 length,
1099 elements);
1100 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001101}
1102
1103
1104LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001105 LOperand* argument = UseOrConstant(instr->argument());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001106 return new(zone()) LPushArgument(argument);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001107}
1108
1109
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001110LInstruction* LChunkBuilder::DoStoreCodeEntry(
1111 HStoreCodeEntry* store_code_entry) {
1112 LOperand* function = UseRegister(store_code_entry->function());
1113 LOperand* code_object = UseTempRegister(store_code_entry->code_object());
1114 return new(zone()) LStoreCodeEntry(function, code_object);
1115}
1116
1117
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001118LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1119 HInnerAllocatedObject* inner_object) {
1120 LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
1121 LInnerAllocatedObject* result =
1122 new(zone()) LInnerAllocatedObject(base_object);
1123 return DefineAsRegister(result);
1124}
1125
1126
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001127LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001128 return instr->HasNoUses()
1129 ? NULL
1130 : DefineAsRegister(new(zone()) LThisFunction);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001131}
1132
1133
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001134LInstruction* LChunkBuilder::DoContext(HContext* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001135 if (instr->HasNoUses()) return NULL;
1136
1137 if (info()->IsStub()) {
1138 return DefineFixed(new(zone()) LContext, rsi);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001139 }
1140
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001141 return DefineAsRegister(new(zone()) LContext);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001142}
1143
1144
1145LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001146 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001147 return DefineAsRegister(new(zone()) LOuterContext(context));
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001148}
1149
1150
yangguo@chromium.org56454712012-02-16 15:33:53 +00001151LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001152 LOperand* context = UseFixed(instr->context(), rsi);
1153 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
yangguo@chromium.org56454712012-02-16 15:33:53 +00001154}
1155
1156
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001157LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001158 LOperand* context = UseRegisterAtStart(instr->value());
1159 return DefineAsRegister(new(zone()) LGlobalObject(context));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001160}
1161
1162
1163LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001164 LOperand* global_object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001165 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001166}
1167
1168
1169LInstruction* LChunkBuilder::DoCallConstantFunction(
1170 HCallConstantFunction* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001171 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001172}
1173
1174
danno@chromium.org160a7b02011-04-18 15:51:38 +00001175LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001176 LOperand* context = UseFixed(instr->context(), rsi);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001177 LOperand* function = UseFixed(instr->function(), rdi);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001178 LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001179 return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1180}
1181
1182
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001183LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001184 switch (instr->op()) {
1185 case kMathFloor: return DoMathFloor(instr);
1186 case kMathRound: return DoMathRound(instr);
1187 case kMathAbs: return DoMathAbs(instr);
1188 case kMathLog: return DoMathLog(instr);
1189 case kMathSin: return DoMathSin(instr);
1190 case kMathCos: return DoMathCos(instr);
1191 case kMathTan: return DoMathTan(instr);
1192 case kMathExp: return DoMathExp(instr);
1193 case kMathSqrt: return DoMathSqrt(instr);
1194 case kMathPowHalf: return DoMathPowHalf(instr);
1195 default:
1196 UNREACHABLE();
1197 return NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001198 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001199}
1200
1201
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001202LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1203 LOperand* input = UseRegisterAtStart(instr->value());
1204 LMathFloor* result = new(zone()) LMathFloor(input);
1205 return AssignEnvironment(DefineAsRegister(result));
1206}
1207
1208
1209LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1210 LOperand* input = UseRegisterAtStart(instr->value());
1211 LMathRound* result = new(zone()) LMathRound(input);
1212 return AssignEnvironment(DefineAsRegister(result));
1213}
1214
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001215
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001216LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001217 LOperand* context = UseAny(instr->context());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001218 LOperand* input = UseRegisterAtStart(instr->value());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001219 LMathAbs* result = new(zone()) LMathAbs(context, input);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001220 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1221}
1222
1223
1224LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +00001225 ASSERT(instr->representation().IsDouble());
1226 ASSERT(instr->value()->representation().IsDouble());
1227 LOperand* input = UseRegisterAtStart(instr->value());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001228 LMathLog* result = new(zone()) LMathLog(input);
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +00001229 return DefineSameAsFirst(result);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001230}
1231
1232
1233LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1234 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1235 LMathSin* result = new(zone()) LMathSin(input);
1236 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1237}
1238
1239
1240LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1241 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1242 LMathCos* result = new(zone()) LMathCos(input);
1243 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1244}
1245
1246
1247LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
1248 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1249 LMathTan* result = new(zone()) LMathTan(input);
1250 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1251}
1252
1253
1254LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1255 ASSERT(instr->representation().IsDouble());
1256 ASSERT(instr->value()->representation().IsDouble());
1257 LOperand* value = UseTempRegister(instr->value());
1258 LOperand* temp1 = TempRegister();
1259 LOperand* temp2 = TempRegister();
1260 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2);
1261 return DefineAsRegister(result);
1262}
1263
1264
1265LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1266 LOperand* input = UseRegisterAtStart(instr->value());
1267 LMathSqrt* result = new(zone()) LMathSqrt(input);
1268 return DefineSameAsFirst(result);
1269}
1270
1271
1272LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1273 LOperand* input = UseRegisterAtStart(instr->value());
1274 LMathPowHalf* result = new(zone()) LMathPowHalf(input);
1275 return DefineSameAsFirst(result);
1276}
1277
1278
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001279LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001280 ASSERT(instr->key()->representation().IsTagged());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001281 LOperand* context = UseFixed(instr->context(), rsi);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001282 LOperand* key = UseFixed(instr->key(), rcx);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001283 LCallKeyed* result = new(zone()) LCallKeyed(context, key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001284 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001285}
1286
1287
1288LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001289 LOperand* context = UseFixed(instr->context(), rsi);
1290 LCallNamed* result = new(zone()) LCallNamed(context);
1291 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001292}
1293
1294
1295LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001296 LOperand* context = UseFixed(instr->context(), rsi);
1297 LCallGlobal* result = new(zone()) LCallGlobal(context);
1298 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001299}
1300
1301
1302LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001303 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001304}
1305
1306
1307LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001308 LOperand* context = UseFixed(instr->context(), rsi);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001309 LOperand* constructor = UseFixed(instr->constructor(), rdi);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001310 LCallNew* result = new(zone()) LCallNew(context, constructor);
ager@chromium.org378b34e2011-01-28 08:04:38 +00001311 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001312}
1313
1314
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001315LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001316 LOperand* context = UseFixed(instr->context(), rsi);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001317 LOperand* constructor = UseFixed(instr->constructor(), rdi);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001318 LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001319 return MarkAsCall(DefineFixed(result, rax), instr);
1320}
1321
1322
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001323LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001324 LOperand* context = UseFixed(instr->context(), rsi);
danno@chromium.orgc612e022011-11-10 11:38:15 +00001325 LOperand* function = UseFixed(instr->function(), rdi);
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001326 LCallFunction* call = new(zone()) LCallFunction(context, function);
1327 LInstruction* result = DefineFixed(call, rax);
1328 if (instr->IsTailCall()) return result;
1329 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001330}
1331
1332
1333LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001334 LOperand* context = UseFixed(instr->context(), rsi);
1335 LCallRuntime* result = new(zone()) LCallRuntime(context);
1336 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001337}
1338
1339
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001340LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1341 return DoShift(Token::ROR, instr);
1342}
1343
1344
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001345LInstruction* LChunkBuilder::DoShr(HShr* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001346 return DoShift(Token::SHR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001347}
1348
1349
1350LInstruction* LChunkBuilder::DoSar(HSar* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001351 return DoShift(Token::SAR, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001352}
1353
1354
1355LInstruction* LChunkBuilder::DoShl(HShl* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001356 return DoShift(Token::SHL, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001357}
1358
1359
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001360LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001361 if (instr->representation().IsSmiOrInteger32()) {
1362 ASSERT(instr->left()->representation().Equals(instr->representation()));
1363 ASSERT(instr->right()->representation().Equals(instr->representation()));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001364 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001365
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001366 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1367 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001368 return DefineSameAsFirst(new(zone()) LBitI(left, right));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001369 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001370 return DoArithmeticT(instr->op(), instr);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001371 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001372}
1373
1374
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001375LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001376 if (instr->representation().IsSmiOrInteger32()) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001377 ASSERT(instr->left()->representation().Equals(instr->representation()));
1378 ASSERT(instr->right()->representation().Equals(instr->representation()));
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +00001379 if (instr->HasPowerOf2Divisor()) {
1380 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1381 LOperand* value = UseRegisterAtStart(instr->left());
1382 LDivI* div =
1383 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL);
1384 return AssignEnvironment(DefineSameAsFirst(div));
1385 }
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001386 // The temporary operand is necessary to ensure that right is not allocated
1387 // into rdx.
1388 LOperand* temp = FixedTemp(rdx);
1389 LOperand* dividend = UseFixed(instr->left(), rax);
1390 LOperand* divisor = UseRegister(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001391 LDivI* result = new(zone()) LDivI(dividend, divisor, temp);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001392 return AssignEnvironment(DefineFixed(result, rax));
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001393 } else if (instr->representation().IsDouble()) {
1394 return DoArithmeticD(Token::DIV, instr);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001395 } else {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001396 return DoArithmeticT(Token::DIV, instr);
1397 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001398}
1399
1400
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001401HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) {
1402 if (divisor->IsConstant() &&
1403 HConstant::cast(divisor)->HasInteger32Value()) {
1404 HConstant* constant_val = HConstant::cast(divisor);
1405 return constant_val->CopyToRepresentation(Representation::Integer32(),
1406 divisor->block()->zone());
1407 }
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001408 // A value with an integer representation does not need to be transformed.
1409 if (divisor->representation().IsInteger32()) {
1410 return divisor;
1411 // A change from an integer32 can be replaced by the integer32 value.
1412 } else if (divisor->IsChange() &&
1413 HChange::cast(divisor)->from().IsInteger32()) {
1414 return HChange::cast(divisor)->value();
1415 }
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001416 return NULL;
1417}
1418
1419
1420LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1421 HValue* right = instr->right();
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001422 if (!right->IsConstant()) {
1423 ASSERT(right->representation().IsInteger32());
1424 // The temporary operand is necessary to ensure that right is not allocated
1425 // into rdx.
1426 LOperand* temp = FixedTemp(rdx);
1427 LOperand* dividend = UseFixed(instr->left(), rax);
1428 LOperand* divisor = UseRegister(instr->right());
1429 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp);
1430 return AssignEnvironment(DefineFixed(flooring_div, rax));
1431 }
1432
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00001433 ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value());
1434 LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right));
1435 int32_t divisor_si = HConstant::cast(right)->Integer32Value();
1436 if (divisor_si == 0) {
1437 LOperand* dividend = UseRegister(instr->left());
1438 return AssignEnvironment(DefineAsRegister(
1439 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)));
1440 } else if (IsPowerOf2(abs(divisor_si))) {
1441 LOperand* dividend = UseRegisterAtStart(instr->left());
1442 LInstruction* result = DefineAsRegister(
1443 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL));
1444 return divisor_si < 0 ? AssignEnvironment(result) : result;
1445 } else {
1446 // use two r64
1447 LOperand* dividend = UseRegisterAtStart(instr->left());
1448 LOperand* temp = TempRegister();
1449 LInstruction* result = DefineAsRegister(
1450 new(zone()) LMathFloorOfDiv(dividend, divisor, temp));
1451 return divisor_si < 0 ? AssignEnvironment(result) : result;
1452 }
1453}
1454
1455
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001456LInstruction* LChunkBuilder::DoMod(HMod* instr) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001457 HValue* left = instr->left();
1458 HValue* right = instr->right();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001459 if (instr->representation().IsSmiOrInteger32()) {
1460 ASSERT(left->representation().Equals(instr->representation()));
1461 ASSERT(right->representation().Equals(instr->representation()));
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001462 if (instr->HasPowerOf2Divisor()) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001463 ASSERT(!right->CanBeZero());
1464 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1465 UseOrConstant(right),
1466 NULL);
1467 LInstruction* result = DefineSameAsFirst(mod);
1468 return (left->CanBeNegative() &&
1469 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1470 ? AssignEnvironment(result)
1471 : result;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001472 } else if (instr->fixed_right_arg().has_value) {
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001473 LModI* mod = new(zone()) LModI(UseRegister(left),
1474 UseRegisterAtStart(right),
1475 NULL);
1476 return AssignEnvironment(DefineSameAsFirst(mod));
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001477 } else {
1478 // The temporary operand is necessary to ensure that right is not
1479 // allocated into edx.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001480 LModI* mod = new(zone()) LModI(UseFixed(left, rax),
1481 UseRegister(right),
1482 FixedTemp(rdx));
1483 LInstruction* result = DefineFixed(mod, rdx);
1484 return (right->CanBeZero() ||
1485 (left->RangeCanInclude(kMinInt) &&
1486 right->RangeCanInclude(-1) &&
1487 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1488 (left->CanBeNegative() &&
1489 instr->CanBeZero() &&
1490 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1491 ? AssignEnvironment(result)
1492 : result;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001493 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001494 } else if (instr->representation().IsDouble()) {
1495 return DoArithmeticD(Token::MOD, instr);
hpayer@chromium.org2f877ac2013-09-18 15:29:06 +00001496 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001497 return DoArithmeticT(Token::MOD, instr);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001498 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001499}
1500
1501
1502LInstruction* LChunkBuilder::DoMul(HMul* 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()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001506 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1507 LOperand* right = UseOrConstant(instr->BetterRightOperand());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001508 LMulI* mul = new(zone()) LMulI(left, right);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001509 if (instr->CheckFlag(HValue::kCanOverflow) ||
1510 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1511 AssignEnvironment(mul);
1512 }
1513 return DefineSameAsFirst(mul);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001514 } else if (instr->representation().IsDouble()) {
1515 return DoArithmeticD(Token::MUL, instr);
1516 } else {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001517 return DoArithmeticT(Token::MUL, instr);
1518 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001519}
1520
1521
1522LInstruction* LChunkBuilder::DoSub(HSub* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001523 if (instr->representation().IsSmiOrInteger32()) {
1524 ASSERT(instr->left()->representation().Equals(instr->representation()));
1525 ASSERT(instr->right()->representation().Equals(instr->representation()));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001526 LOperand* left = UseRegisterAtStart(instr->left());
1527 LOperand* right = UseOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001528 LSubI* sub = new(zone()) LSubI(left, right);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001529 LInstruction* result = DefineSameAsFirst(sub);
1530 if (instr->CheckFlag(HValue::kCanOverflow)) {
1531 result = AssignEnvironment(result);
1532 }
1533 return result;
1534 } else if (instr->representation().IsDouble()) {
1535 return DoArithmeticD(Token::SUB, instr);
1536 } else {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001537 return DoArithmeticT(Token::SUB, instr);
1538 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001539}
1540
1541
1542LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001543 if (instr->representation().IsSmiOrInteger32()) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001544 // Check to see if it would be advantageous to use an lea instruction rather
1545 // than an add. This is the case when no overflow check is needed and there
1546 // are multiple uses of the add's inputs, so using a 3-register add will
1547 // preserve all input values for later uses.
1548 bool use_lea = LAddI::UseLea(instr);
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001549 ASSERT(instr->left()->representation().Equals(instr->representation()));
1550 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001551 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1552 HValue* right_candidate = instr->BetterRightOperand();
1553 LOperand* right = use_lea
1554 ? UseRegisterOrConstantAtStart(right_candidate)
1555 : UseOrConstantAtStart(right_candidate);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001556 LAddI* add = new(zone()) LAddI(left, right);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001557 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1558 LInstruction* result = use_lea
1559 ? DefineAsRegister(add)
1560 : DefineSameAsFirst(add);
1561 if (can_overflow) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001562 result = AssignEnvironment(result);
1563 }
1564 return result;
1565 } else if (instr->representation().IsDouble()) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001566 return DoArithmeticD(Token::ADD, instr);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001567 } else {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001568 return DoArithmeticT(Token::ADD, instr);
1569 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001570 return NULL;
1571}
1572
1573
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001574LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1575 LOperand* left = NULL;
1576 LOperand* right = NULL;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001577 if (instr->representation().IsSmiOrInteger32()) {
1578 ASSERT(instr->left()->representation().Equals(instr->representation()));
1579 ASSERT(instr->right()->representation().Equals(instr->representation()));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001580 left = UseRegisterAtStart(instr->BetterLeftOperand());
1581 right = UseOrConstantAtStart(instr->BetterRightOperand());
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001582 } else {
1583 ASSERT(instr->representation().IsDouble());
1584 ASSERT(instr->left()->representation().IsDouble());
1585 ASSERT(instr->right()->representation().IsDouble());
1586 left = UseRegisterAtStart(instr->left());
1587 right = UseRegisterAtStart(instr->right());
1588 }
1589 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right);
1590 return DefineSameAsFirst(minmax);
1591}
1592
1593
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001594LInstruction* LChunkBuilder::DoPower(HPower* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001595 ASSERT(instr->representation().IsDouble());
1596 // We call a C function for double power. It can't trigger a GC.
1597 // We need to use fixed result register for the call.
1598 Representation exponent_type = instr->right()->representation();
1599 ASSERT(instr->left()->representation().IsDouble());
1600 LOperand* left = UseFixedDouble(instr->left(), xmm2);
1601 LOperand* right = exponent_type.IsDouble() ?
danno@chromium.orgca29dd82013-04-26 11:59:48 +00001602 UseFixedDouble(instr->right(), xmm1) : UseFixed(instr->right(), rdx);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001603 LPower* result = new(zone()) LPower(left, right);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001604 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001605 CAN_DEOPTIMIZE_EAGERLY);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001606}
1607
1608
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001609LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1610 ASSERT(instr->representation().IsDouble());
1611 ASSERT(instr->global_object()->representation().IsTagged());
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +00001612 LOperand* global_object = UseTempRegister(instr->global_object());
1613 LOperand* scratch = TempRegister();
1614 LOperand* scratch2 = TempRegister();
1615 LOperand* scratch3 = TempRegister();
1616 LRandom* result = new(zone()) LRandom(
1617 global_object, scratch, scratch2, scratch3);
1618 return DefineFixedDouble(result, xmm1);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001619}
1620
1621
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001622LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001623 ASSERT(instr->left()->representation().IsTagged());
1624 ASSERT(instr->right()->representation().IsTagged());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001625 LOperand* context = UseFixed(instr->context(), rsi);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001626 LOperand* left = UseFixed(instr->left(), rdx);
1627 LOperand* right = UseFixed(instr->right(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001628 LCmpT* result = new(zone()) LCmpT(context, left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001629 return MarkAsCall(DefineFixed(result, rax), instr);
1630}
1631
1632
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001633LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
1634 HCompareNumericAndBranch* instr) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001635 Representation r = instr->representation();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001636 if (r.IsSmiOrInteger32()) {
danno@chromium.org59400602013-08-13 17:09:37 +00001637 ASSERT(instr->left()->representation().Equals(r));
1638 ASSERT(instr->right()->representation().Equals(r));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001639 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001640 LOperand* right = UseOrConstantAtStart(instr->right());
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001641 return new(zone()) LCompareNumericAndBranch(left, right);
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001642 } else {
1643 ASSERT(r.IsDouble());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001644 ASSERT(instr->left()->representation().IsDouble());
1645 ASSERT(instr->right()->representation().IsDouble());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001646 LOperand* left;
1647 LOperand* right;
1648 if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
1649 left = UseRegisterOrConstantAtStart(instr->left());
1650 right = UseRegisterOrConstantAtStart(instr->right());
1651 } else {
1652 left = UseRegisterAtStart(instr->left());
1653 right = UseRegisterAtStart(instr->right());
1654 }
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001655 return new(zone()) LCompareNumericAndBranch(left, right);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001656 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001657}
1658
1659
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001660LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1661 HCompareObjectEqAndBranch* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00001662 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1663 if (goto_instr != NULL) return goto_instr;
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001664 LOperand* left = UseRegisterAtStart(instr->left());
mstarzinger@chromium.orgb228be02013-04-18 14:56:59 +00001665 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001666 return new(zone()) LCmpObjectEqAndBranch(left, right);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001667}
1668
1669
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001670LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
1671 HCompareHoleAndBranch* instr) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001672 LOperand* value = UseRegisterAtStart(instr->value());
1673 return new(zone()) LCmpHoleAndBranch(value);
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +00001674}
1675
1676
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001677LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch(
1678 HCompareMinusZeroAndBranch* instr) {
1679 LInstruction* goto_instr = CheckElideControlInstruction(instr);
1680 if (goto_instr != NULL) return goto_instr;
1681 LOperand* value = UseRegister(instr->value());
1682 return new(zone()) LCompareMinusZeroAndBranch(value);
1683}
1684
1685
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001686LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001687 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001688 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001689}
1690
1691
erikcorry0ad885c2011-11-21 13:51:57 +00001692LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1693 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001694 LOperand* value = UseRegisterAtStart(instr->value());
erikcorry0ad885c2011-11-21 13:51:57 +00001695 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001696 return new(zone()) LIsStringAndBranch(value, temp);
erikcorry0ad885c2011-11-21 13:51:57 +00001697}
1698
1699
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001700LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001701 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001702 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001703}
1704
1705
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001706LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1707 HIsUndetectableAndBranch* instr) {
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001708 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001709 LOperand* value = UseRegisterAtStart(instr->value());
1710 LOperand* temp = TempRegister();
1711 return new(zone()) LIsUndetectableAndBranch(value, temp);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00001712}
1713
1714
erikcorry0ad885c2011-11-21 13:51:57 +00001715LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1716 HStringCompareAndBranch* instr) {
1717
1718 ASSERT(instr->left()->representation().IsTagged());
1719 ASSERT(instr->right()->representation().IsTagged());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001720 LOperand* context = UseFixed(instr->context(), rsi);
erikcorry0ad885c2011-11-21 13:51:57 +00001721 LOperand* left = UseFixed(instr->left(), rdx);
1722 LOperand* right = UseFixed(instr->right(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001723 LStringCompareAndBranch* result =
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001724 new(zone()) LStringCompareAndBranch(context, left, right);
erikcorry0ad885c2011-11-21 13:51:57 +00001725
1726 return MarkAsCall(result, instr);
1727}
1728
1729
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001730LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1731 HHasInstanceTypeAndBranch* instr) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001732 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001733 LOperand* value = UseRegisterAtStart(instr->value());
1734 return new(zone()) LHasInstanceTypeAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001735}
1736
1737
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001738LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1739 HGetCachedArrayIndex* instr) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001740 ASSERT(instr->value()->representation().IsTagged());
1741 LOperand* value = UseRegisterAtStart(instr->value());
1742
ulan@chromium.org812308e2012-02-29 15:58:45 +00001743 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00001744}
1745
1746
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001747LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1748 HHasCachedArrayIndexAndBranch* instr) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001749 ASSERT(instr->value()->representation().IsTagged());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001750 LOperand* value = UseRegisterAtStart(instr->value());
1751 return new(zone()) LHasCachedArrayIndexAndBranch(value);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001752}
1753
1754
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001755LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1756 HClassOfTestAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001757 LOperand* value = UseRegister(instr->value());
1758 return new(zone()) LClassOfTestAndBranch(value,
1759 TempRegister(),
1760 TempRegister());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001761}
1762
1763
yangguo@chromium.org355cfd12012-08-29 15:32:24 +00001764LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1765 LOperand* map = UseRegisterAtStart(instr->value());
1766 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1767}
1768
1769
whesse@chromium.org7b260152011-06-20 15:33:18 +00001770LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1771 LOperand* object = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001772 return DefineAsRegister(new(zone()) LElementsKind(object));
whesse@chromium.org7b260152011-06-20 15:33:18 +00001773}
1774
1775
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001776LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001777 LOperand* object = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001778 LValueOf* result = new(zone()) LValueOf(object);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001779 return DefineSameAsFirst(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001780}
1781
1782
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001783LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1784 LOperand* object = UseFixed(instr->value(), rax);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001785 LDateField* result = new(zone()) LDateField(object, instr->index());
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001786 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
svenpanne@chromium.org4efbdb12012-03-12 08:18:42 +00001787}
1788
1789
machenbach@chromium.orge8412be2013-11-08 10:23:52 +00001790LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
1791 LOperand* string = UseRegisterAtStart(instr->string());
1792 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1793 return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
1794}
1795
1796
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001797LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +00001798 LOperand* string = UseRegisterAtStart(instr->string());
1799 LOperand* index = UseRegisterOrConstantAtStart(instr->index());
1800 LOperand* value = UseRegisterOrConstantAtStart(instr->value());
1801 return new(zone()) LSeqStringSetChar(string, index, value);
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00001802}
1803
1804
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001805LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001806 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1807 LOperand* length = Use(instr->length());
1808 return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001809}
1810
1811
svenpanne@chromium.org876cca82013-03-18 14:43:20 +00001812LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
1813 HBoundsCheckBaseIndexInformation* instr) {
1814 UNREACHABLE();
1815 return NULL;
1816}
1817
1818
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00001819LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1820 // The control instruction marking the end of a block that completed
1821 // abruptly (e.g., threw an exception). There is nothing specific to do.
1822 return NULL;
1823}
1824
1825
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001826LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001827 LOperand* context = UseFixed(instr->context(), rsi);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00001828 LOperand* value = UseFixed(instr->value(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00001829 return MarkAsCall(new(zone()) LThrow(context, value), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001830}
1831
1832
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001833LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
1834 return NULL;
1835}
1836
1837
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001838LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
1839 // All HForceRepresentation instructions should be eliminated in the
1840 // representation change phase of Hydrogen.
1841 UNREACHABLE();
1842 return NULL;
1843}
1844
1845
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001846LInstruction* LChunkBuilder::DoChange(HChange* instr) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001847 Representation from = instr->from();
1848 Representation to = instr->to();
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001849 if (from.IsSmi()) {
1850 if (to.IsTagged()) {
1851 LOperand* value = UseRegister(instr->value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001852 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1853 }
1854 from = Representation::Tagged();
1855 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001856 // Only mark conversions that might need to allocate as calling rather than
1857 // all changes. This makes simple, non-allocating conversion not have to force
1858 // building a stack frame.
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001859 if (from.IsTagged()) {
1860 if (to.IsDouble()) {
1861 LOperand* value = UseRegister(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001862 LNumberUntagD* res = new(zone()) LNumberUntagD(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001863 return AssignEnvironment(DefineAsRegister(res));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001864 } else if (to.IsSmi()) {
1865 HValue* val = instr->value();
1866 LOperand* value = UseRegister(val);
1867 if (val->type().IsSmi()) {
1868 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1869 }
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001870 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001871 } else {
1872 ASSERT(to.IsInteger32());
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001873 HValue* val = instr->value();
1874 LOperand* value = UseRegister(val);
1875 if (val->type().IsSmi() || val->representation().IsSmi()) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001876 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001877 } else {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +00001878 bool truncating = instr->CanTruncateToInt32();
1879 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
ulan@chromium.org812308e2012-02-29 15:58:45 +00001880 LTaggedToI* res = new(zone()) LTaggedToI(value, xmm_temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001881 return AssignEnvironment(DefineSameAsFirst(res));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001882 }
1883 }
1884 } else if (from.IsDouble()) {
1885 if (to.IsTagged()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001886 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001887 LOperand* value = UseRegister(instr->value());
1888 LOperand* temp = TempRegister();
1889
1890 // Make sure that temp and result_temp are different registers.
1891 LUnallocated* result_temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001892 LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001893 return AssignPointerMap(Define(result, result_temp));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001894 } else if (to.IsSmi()) {
1895 LOperand* value = UseRegister(instr->value());
1896 return AssignEnvironment(
1897 DefineAsRegister(new(zone()) LDoubleToSmi(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001898 } else {
1899 ASSERT(to.IsInteger32());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001900 LOperand* value = UseRegister(instr->value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001901 return AssignEnvironment(
1902 DefineAsRegister(new(zone()) LDoubleToI(value)));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001903 }
1904 } else if (from.IsInteger32()) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001905 info()->MarkAsDeferredCalling();
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001906 if (to.IsTagged()) {
1907 HValue* val = instr->value();
1908 LOperand* value = UseRegister(val);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001909 if (val->CheckFlag(HInstruction::kUint32)) {
1910 LOperand* temp = FixedTemp(xmm1);
1911 LNumberTagU* result = new(zone()) LNumberTagU(value, temp);
1912 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1913 } else if (val->HasRange() && val->range()->IsInSmiRange()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001914 return DefineSameAsFirst(new(zone()) LSmiTag(value));
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001915 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001916 LNumberTagI* result = new(zone()) LNumberTagI(value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001917 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1918 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001919 } else if (to.IsSmi()) {
1920 HValue* val = instr->value();
1921 LOperand* value = UseRegister(val);
machenbach@chromium.orged29eb22013-10-31 13:30:00 +00001922 LInstruction* result = NULL;
1923 if (val->CheckFlag(HInstruction::kUint32)) {
1924 result = DefineAsRegister(new(zone()) LUint32ToSmi(value));
1925 if (val->HasRange() && val->range()->IsInSmiRange() &&
1926 val->range()->upper() != kMaxInt) {
1927 return result;
1928 }
1929 } else {
1930 result = DefineAsRegister(new(zone()) LInteger32ToSmi(value));
1931 if (val->HasRange() && val->range()->IsInSmiRange()) {
1932 return result;
1933 }
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001934 }
1935 return AssignEnvironment(result);
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001936 } else {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001937 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1938 LOperand* temp = FixedTemp(xmm1);
1939 return DefineAsRegister(
1940 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp));
1941 } else {
1942 ASSERT(to.IsDouble());
1943 LOperand* value = Use(instr->value());
1944 return DefineAsRegister(new(zone()) LInteger32ToDouble(value));
1945 }
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001946 }
1947 }
1948 UNREACHABLE();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001949 return NULL;
1950}
1951
1952
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001953LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001954 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001955 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001956}
1957
1958
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001959LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1960 LOperand* value = UseRegisterAtStart(instr->value());
1961 return AssignEnvironment(new(zone()) LCheckSmi(value));
1962}
1963
1964
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001965LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001966 LOperand* value = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00001967 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001968 return AssignEnvironment(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001969}
1970
1971
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00001972LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00001973 LOperand* value = UseRegisterAtStart(instr->value());
mstarzinger@chromium.org1f410f92013-08-29 08:13:16 +00001974 return AssignEnvironment(new(zone()) LCheckValue(value));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001975}
1976
1977
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001978LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +00001979 LOperand* value = NULL;
danno@chromium.org59400602013-08-13 17:09:37 +00001980 if (!instr->CanOmitMapChecks()) {
1981 value = UseRegisterAtStart(instr->value());
1982 if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
1983 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001984 LCheckMaps* result = new(zone()) LCheckMaps(value);
danno@chromium.org59400602013-08-13 17:09:37 +00001985 if (!instr->CanOmitMapChecks()) {
1986 AssignEnvironment(result);
1987 if (instr->has_migration_target()) return AssignPointerMap(result);
1988 }
1989 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001990}
1991
1992
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001993LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1994 HValue* value = instr->value();
1995 Representation input_rep = value->representation();
1996 LOperand* reg = UseRegister(value);
1997 if (input_rep.IsDouble()) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001998 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00001999 } else if (input_rep.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002000 return DefineSameAsFirst(new(zone()) LClampIToUint8(reg));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002001 } else {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002002 ASSERT(input_rep.IsSmiOrTagged());
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002003 // Register allocator doesn't (yet) support allocation of double
2004 // temps. Reserve xmm1 explicitly.
ulan@chromium.org812308e2012-02-29 15:58:45 +00002005 LClampTToUint8* result = new(zone()) LClampTToUint8(reg,
ulan@chromium.org812308e2012-02-29 15:58:45 +00002006 FixedTemp(xmm1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002007 return AssignEnvironment(DefineSameAsFirst(result));
2008 }
2009}
2010
2011
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002012LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002013 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00002014 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002015 return new(zone()) LReturn(
2016 UseFixed(instr->value(), rax), context, parameter_count);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002017}
2018
2019
2020LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
2021 Representation r = instr->representation();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002022 if (r.IsSmi()) {
2023 return DefineAsRegister(new(zone()) LConstantS);
2024 } else if (r.IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002025 return DefineAsRegister(new(zone()) LConstantI);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002026 } else if (r.IsDouble()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00002027 LOperand* temp = TempRegister();
ulan@chromium.org812308e2012-02-29 15:58:45 +00002028 return DefineAsRegister(new(zone()) LConstantD(temp));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002029 } else if (r.IsExternal()) {
2030 return DefineAsRegister(new(zone()) LConstantE);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00002031 } else if (r.IsTagged()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002032 return DefineAsRegister(new(zone()) LConstantT);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002033 } else {
2034 UNREACHABLE();
2035 return NULL;
2036 }
2037}
2038
2039
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002040LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002041 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002042 return instr->RequiresHoleCheck()
ager@chromium.org378b34e2011-01-28 08:04:38 +00002043 ? AssignEnvironment(DefineAsRegister(result))
2044 : DefineAsRegister(result);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002045}
2046
2047
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002048LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002049 LOperand* context = UseFixed(instr->context(), rsi);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002050 LOperand* global_object = UseFixed(instr->global_object(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002051 LLoadGlobalGeneric* result =
2052 new(zone()) LLoadGlobalGeneric(context, global_object);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002053 return MarkAsCall(DefineFixed(result, rax), instr);
2054}
2055
2056
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002057LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
danno@chromium.orge78f9fc2011-12-21 08:29:34 +00002058 LOperand* value = UseRegister(instr->value());
2059 // Use a temp to avoid reloading the cell value address in the case where
2060 // we perform a hole check.
2061 return instr->RequiresHoleCheck()
ulan@chromium.org812308e2012-02-29 15:58:45 +00002062 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister()))
2063 : new(zone()) LStoreGlobalCell(value, NULL);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002064}
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002065
2066
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002067LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002068 LOperand* context = UseFixed(instr->context(), rsi);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002069 LOperand* global_object = UseFixed(instr->global_object(), rdx);
2070 LOperand* value = UseFixed(instr->value(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002071 LStoreGlobalGeneric* result =
2072 new(zone()) LStoreGlobalGeneric(context, global_object, value);
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002073 return MarkAsCall(result, instr);
2074}
2075
2076
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002077LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002078 LOperand* context = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002079 LInstruction* result =
2080 DefineAsRegister(new(zone()) LLoadContextSlot(context));
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002081 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002082}
2083
2084
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002085LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002086 LOperand* context;
2087 LOperand* value;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002088 LOperand* temp;
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002089 context = UseRegister(instr->context());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002090 if (instr->NeedsWriteBarrier()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002091 value = UseTempRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002092 temp = TempRegister();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002093 } else {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002094 value = UseRegister(instr->value());
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00002095 temp = NULL;
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002096 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002097 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00002098 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002099}
2100
2101
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002102LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00002103 // Use the special mov rax, moffs64 encoding for external
2104 // memory accesses with 64-bit word-sized values.
2105 if (instr->access().IsExternalMemory() &&
2106 instr->access().offset() == 0 &&
2107 (instr->access().representation().IsSmi() ||
2108 instr->access().representation().IsTagged() ||
2109 instr->access().representation().IsHeapObject() ||
2110 instr->access().representation().IsExternal())) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002111 LOperand* obj = UseRegisterOrConstantAtStart(instr->object());
2112 return DefineFixed(new(zone()) LLoadNamedField(obj), rax);
2113 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002114 LOperand* obj = UseRegisterAtStart(instr->object());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002115 return DefineAsRegister(new(zone()) LLoadNamedField(obj));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002116}
2117
2118
2119LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002120 LOperand* context = UseFixed(instr->context(), rsi);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002121 LOperand* object = UseFixed(instr->object(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002122 LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(context, object);
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002123 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002124}
2125
2126
2127LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2128 HLoadFunctionPrototype* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002129 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002130 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002131}
2132
2133
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002134LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
2135 return DefineAsRegister(new(zone()) LLoadRoot);
2136}
2137
2138
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00002139LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2140 HLoadExternalArrayPointer* instr) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002141 LOperand* input = UseRegisterAtStart(instr->value());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002142 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002143}
2144
2145
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002146LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002147 ASSERT(instr->key()->representation().IsInteger32());
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002148 ElementsKind elements_kind = instr->elements_kind();
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002149 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002150 LLoadKeyed* result = NULL;
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002151
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002152 if (!instr->is_external()) {
2153 LOperand* obj = UseRegisterAtStart(instr->elements());
2154 result = new(zone()) LLoadKeyed(obj, key);
2155 } else {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002156 ASSERT(
2157 (instr->representation().IsInteger32() &&
2158 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2159 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2160 (instr->representation().IsDouble() &&
2161 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2162 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002163 LOperand* external_pointer = UseRegister(instr->elements());
2164 result = new(zone()) LLoadKeyed(external_pointer, key);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002165 }
2166
2167 DefineAsRegister(result);
2168 bool can_deoptimize = instr->RequiresHoleCheck() ||
2169 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002170 // An unsigned int array load might overflow and cause a deopt, make sure it
2171 // has an environment.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002172 return can_deoptimize ? AssignEnvironment(result) : result;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002173}
2174
2175
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002176LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002177 LOperand* context = UseFixed(instr->context(), rsi);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002178 LOperand* object = UseFixed(instr->object(), rdx);
2179 LOperand* key = UseFixed(instr->key(), rax);
2180
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002181 LLoadKeyedGeneric* result =
2182 new(zone()) LLoadKeyedGeneric(context, object, key);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002183 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002184}
2185
2186
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002187LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002188 ElementsKind elements_kind = instr->elements_kind();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002189
2190 if (!instr->is_external()) {
2191 ASSERT(instr->elements()->representation().IsTagged());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002192 bool needs_write_barrier = instr->NeedsWriteBarrier();
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002193 LOperand* object = NULL;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002194 LOperand* key = NULL;
2195 LOperand* val = NULL;
2196
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002197 if (instr->value()->representation().IsDouble()) {
2198 object = UseRegisterAtStart(instr->elements());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002199 val = UseTempRegister(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002200 key = UseRegisterOrConstantAtStart(instr->key());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002201 } else {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002202 ASSERT(instr->value()->representation().IsSmiOrTagged());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002203 object = UseTempRegister(instr->elements());
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002204 if (needs_write_barrier) {
2205 val = UseTempRegister(instr->value());
2206 key = UseTempRegister(instr->key());
2207 } else {
danno@chromium.orgf005df62013-04-30 16:36:45 +00002208 val = UseRegisterOrConstantAtStart(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002209 key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org32d7dba2013-04-24 10:59:06 +00002210 }
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002211 }
2212
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002213 return new(zone()) LStoreKeyed(object, key, val);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002214 }
2215
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002216 ASSERT(
2217 (instr->value()->representation().IsInteger32() &&
2218 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2219 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2220 (instr->value()->representation().IsDouble() &&
2221 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2222 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2223 ASSERT(instr->elements()->representation().IsExternal());
2224 bool val_is_temp_register =
2225 elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2226 elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2227 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2228 : UseRegister(instr->value());
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00002229 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00002230 LOperand* external_pointer = UseRegister(instr->elements());
2231 return new(zone()) LStoreKeyed(external_pointer, key, val);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002232}
2233
2234
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002235LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002236 LOperand* context = UseFixed(instr->context(), rsi);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002237 LOperand* object = UseFixed(instr->object(), rdx);
2238 LOperand* key = UseFixed(instr->key(), rcx);
2239 LOperand* value = UseFixed(instr->value(), rax);
2240
2241 ASSERT(instr->object()->representation().IsTagged());
2242 ASSERT(instr->key()->representation().IsTagged());
2243 ASSERT(instr->value()->representation().IsTagged());
2244
ulan@chromium.org812308e2012-02-29 15:58:45 +00002245 LStoreKeyedGeneric* result =
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002246 new(zone()) LStoreKeyedGeneric(context, object, key, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002247 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002248}
2249
2250
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002251LInstruction* LChunkBuilder::DoTransitionElementsKind(
2252 HTransitionElementsKind* instr) {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002253 LOperand* object = UseRegister(instr->object());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002254 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002255 LOperand* object = UseRegister(instr->object());
2256 LOperand* new_map_reg = TempRegister();
2257 LOperand* temp_reg = TempRegister();
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002258 LTransitionElementsKind* result = new(zone()) LTransitionElementsKind(
2259 object, NULL, new_map_reg, temp_reg);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002260 return result;
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002261 } else {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002262 LOperand* context = UseAny(instr->context());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002263 LTransitionElementsKind* result =
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002264 new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002265 return AssignPointerMap(result);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002266 }
2267}
2268
2269
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002270LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2271 HTrapAllocationMemento* instr) {
2272 LOperand* object = UseRegister(instr->object());
2273 LOperand* temp = TempRegister();
2274 LTrapAllocationMemento* result =
2275 new(zone()) LTrapAllocationMemento(object, temp);
2276 return AssignEnvironment(result);
2277}
2278
2279
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002280LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002281 bool is_in_object = instr->access().IsInobject();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002282 bool is_external_location = instr->access().IsExternalMemory() &&
2283 instr->access().offset() == 0;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002284 bool needs_write_barrier = instr->NeedsWriteBarrier();
danno@chromium.org59400602013-08-13 17:09:37 +00002285 bool needs_write_barrier_for_map = instr->has_transition() &&
verwaest@chromium.org37141392012-05-31 13:27:02 +00002286 instr->NeedsWriteBarrierForMap();
ager@chromium.org378b34e2011-01-28 08:04:38 +00002287
verwaest@chromium.org37141392012-05-31 13:27:02 +00002288 LOperand* obj;
2289 if (needs_write_barrier) {
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002290 obj = is_in_object
verwaest@chromium.org37141392012-05-31 13:27:02 +00002291 ? UseRegister(instr->object())
2292 : UseTempRegister(instr->object());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002293 } else if (is_external_location) {
2294 ASSERT(!is_in_object);
2295 ASSERT(!needs_write_barrier);
2296 ASSERT(!needs_write_barrier_for_map);
2297 obj = UseRegisterOrConstant(instr->object());
verwaest@chromium.org37141392012-05-31 13:27:02 +00002298 } else {
2299 obj = needs_write_barrier_for_map
2300 ? UseRegister(instr->object())
2301 : UseRegisterAtStart(instr->object());
2302 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002303
danno@chromium.orgf005df62013-04-30 16:36:45 +00002304 bool can_be_constant = instr->value()->IsConstant() &&
2305 HConstant::cast(instr->value())->NotInNewSpace() &&
2306 !(FLAG_track_double_fields && instr->field_representation().IsDouble());
2307
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002308 LOperand* val;
2309 if (needs_write_barrier) {
2310 val = UseTempRegister(instr->value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002311 } else if (is_external_location) {
2312 val = UseFixed(instr->value(), rax);
danno@chromium.orgf005df62013-04-30 16:36:45 +00002313 } else if (can_be_constant) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002314 val = UseRegisterOrConstant(instr->value());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002315 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) {
2316 val = UseTempRegister(instr->value());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00002317 } else if (FLAG_track_double_fields &&
2318 instr->field_representation().IsDouble()) {
2319 val = UseRegisterAtStart(instr->value());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002320 } else {
2321 val = UseRegister(instr->value());
2322 }
ager@chromium.org378b34e2011-01-28 08:04:38 +00002323
2324 // We only need a scratch register if we have a write barrier or we
2325 // have a store into the properties array (not in-object-property).
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00002326 LOperand* temp = (!is_in_object || needs_write_barrier ||
verwaest@chromium.org37141392012-05-31 13:27:02 +00002327 needs_write_barrier_for_map) ? TempRegister() : NULL;
ager@chromium.org378b34e2011-01-28 08:04:38 +00002328
danno@chromium.orgf005df62013-04-30 16:36:45 +00002329 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002330 if (FLAG_track_heap_object_fields &&
2331 instr->field_representation().IsHeapObject()) {
2332 if (!instr->value()->type().IsHeapObject()) {
2333 return AssignEnvironment(result);
2334 }
danno@chromium.orgf005df62013-04-30 16:36:45 +00002335 }
2336 return result;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002337}
2338
2339
2340LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002341 LOperand* context = UseFixed(instr->context(), rsi);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002342 LOperand* object = UseFixed(instr->object(), rdx);
2343 LOperand* value = UseFixed(instr->value(), rax);
2344
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002345 LStoreNamedGeneric* result =
2346 new(zone()) LStoreNamedGeneric(context, object, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002347 return MarkAsCall(result, instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002348}
2349
2350
danno@chromium.org160a7b02011-04-18 15:51:38 +00002351LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002352 LOperand* context = UseFixed(instr->context(), rsi);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002353 LOperand* left = FLAG_new_string_add
2354 ? UseFixed(instr->left(), rdx)
2355 : UseOrConstantAtStart(instr->left());
2356 LOperand* right = FLAG_new_string_add
2357 ? UseFixed(instr->right(), rax)
2358 : UseOrConstantAtStart(instr->right());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002359 return MarkAsCall(
2360 DefineFixed(new(zone()) LStringAdd(context, left, right), rax), instr);
danno@chromium.org160a7b02011-04-18 15:51:38 +00002361}
2362
2363
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002364LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
ricow@chromium.org4668a2c2011-08-29 10:41:00 +00002365 LOperand* string = UseTempRegister(instr->string());
2366 LOperand* index = UseTempRegister(instr->index());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002367 LOperand* context = UseAny(instr->context());
2368 LStringCharCodeAt* result =
2369 new(zone()) LStringCharCodeAt(context, string, index);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002370 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002371}
2372
2373
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002374LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2375 LOperand* char_code = UseRegister(instr->value());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002376 LOperand* context = UseAny(instr->context());
2377 LStringCharFromCode* result =
2378 new(zone()) LStringCharFromCode(context, char_code);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002379 return AssignPointerMap(DefineAsRegister(result));
2380}
2381
2382
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002383LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
2384 info()->MarkAsDeferredCalling();
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002385 LOperand* context = UseAny(instr->context());
danno@chromium.orgf005df62013-04-30 16:36:45 +00002386 LOperand* size = instr->size()->IsConstant()
2387 ? UseConstant(instr->size())
2388 : UseTempRegister(instr->size());
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002389 LOperand* temp = TempRegister();
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002390 LAllocate* result = new(zone()) LAllocate(context, size, temp);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00002391 return AssignPointerMap(DefineAsRegister(result));
2392}
2393
2394
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002395LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002396 LOperand* context = UseFixed(instr->context(), rsi);
2397 LRegExpLiteral* result = new(zone()) LRegExpLiteral(context);
2398 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002399}
2400
2401
2402LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002403 LOperand* context = UseFixed(instr->context(), rsi);
2404 LFunctionLiteral* result = new(zone()) LFunctionLiteral(context);
2405 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002406}
2407
2408
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002409LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002410 ASSERT(argument_count_ == 0);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002411 allocator_->MarkAsOsrEntry();
2412 current_block_->last_environment()->set_ast_id(instr->ast_id());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002413 return AssignEnvironment(new(zone()) LOsrEntry);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002414}
2415
2416
2417LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002418 LParameter* result = new(zone()) LParameter;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +00002419 if (instr->kind() == HParameter::STACK_PARAMETER) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002420 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2421 return DefineAsSpilled(result, spill_index);
2422 } else {
2423 ASSERT(info()->IsStub());
2424 CodeStubInterfaceDescriptor* descriptor =
2425 info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002426 int index = static_cast<int>(instr->index());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002427 Register reg = descriptor->GetParameterRegister(index);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002428 return DefineFixed(result, reg);
2429 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002430}
2431
2432
2433LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +00002434 // Use an index that corresponds to the location in the unoptimized frame,
2435 // which the optimized frame will subsume.
2436 int env_index = instr->index();
2437 int spill_index = 0;
2438 if (instr->environment()->is_parameter_index(env_index)) {
2439 spill_index = chunk()->GetParameterStackSlot(env_index);
2440 } else {
2441 spill_index = env_index - instr->environment()->first_local_index();
2442 if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
2443 Abort(kTooManySpillSlotsNeededForOSR);
2444 spill_index = 0;
2445 }
ager@chromium.org04921a82011-06-27 13:21:41 +00002446 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00002447 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002448}
2449
2450
2451LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002452 LOperand* context = UseFixed(instr->context(), rsi);
2453 LCallStub* result = new(zone()) LCallStub(context);
2454 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002455}
2456
2457
2458LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002459 // There are no real uses of the arguments object.
2460 // arguments.length and element access are supported directly on
2461 // stack arguments, and any real arguments object use causes a bailout.
2462 // So this value is never used.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002463 return NULL;
2464}
2465
2466
danno@chromium.org59400602013-08-13 17:09:37 +00002467LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002468 instr->ReplayEnvironment(current_block_->last_environment());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00002469
danno@chromium.org59400602013-08-13 17:09:37 +00002470 // There are no real uses of a captured object.
2471 return NULL;
2472}
2473
2474
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002475LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002476 info()->MarkAsRequiresFrame();
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002477 LOperand* args = UseRegister(instr->arguments());
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00002478 LOperand* length;
2479 LOperand* index;
2480 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2481 length = UseRegisterOrConstant(instr->length());
2482 index = UseOrConstant(instr->index());
2483 } else {
2484 length = UseTempRegister(instr->length());
2485 index = Use(instr->index());
2486 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +00002487 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002488}
2489
2490
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002491LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2492 LOperand* object = UseFixed(instr->value(), rax);
ulan@chromium.org812308e2012-02-29 15:58:45 +00002493 LToFastProperties* result = new(zone()) LToFastProperties(object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002494 return MarkAsCall(DefineFixed(result, rax), instr);
2495}
2496
2497
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002498LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002499 LOperand* context = UseFixed(instr->context(), rsi);
2500 LOperand* value = UseAtStart(instr->value());
2501 LTypeof* result = new(zone()) LTypeof(context, value);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002502 return MarkAsCall(DefineFixed(result, rax), instr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002503}
2504
2505
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002506LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00002507 LInstruction* goto_instr = CheckElideControlInstruction(instr);
2508 if (goto_instr != NULL) return goto_instr;
2509
ulan@chromium.org812308e2012-02-29 15:58:45 +00002510 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002511}
2512
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002513
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002514LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2515 HIsConstructCallAndBranch* instr) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002516 return new(zone()) LIsConstructCallAndBranch(TempRegister());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +00002517}
2518
2519
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002520LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
verwaest@chromium.org662436e2013-08-28 08:41:27 +00002521 instr->ReplayEnvironment(current_block_->last_environment());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002522
2523 // If there is an instruction pending deoptimization environment create a
2524 // lazy bailout instruction to capture the environment.
fschneider@chromium.org1df6b472011-01-26 08:23:03 +00002525 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00002526 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002527 LInstruction* result = AssignEnvironment(lazy_bailout);
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002528 // Store the lazy deopt environment with the instruction if needed. Right
2529 // now it is only used for LInstanceOfKnownGlobal.
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00002530 instruction_pending_deoptimization_environment_->
danno@chromium.org1044a4d2012-04-30 12:34:39 +00002531 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2532 instruction_pending_deoptimization_environment_ = NULL;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002533 pending_deoptimization_ast_id_ = BailoutId::None();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002534 return result;
2535 }
2536
2537 return NULL;
2538}
2539
2540
2541LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00002542 info()->MarkAsDeferredCalling();
ager@chromium.org04921a82011-06-27 13:21:41 +00002543 if (instr->is_function_entry()) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002544 LOperand* context = UseFixed(instr->context(), rsi);
2545 return MarkAsCall(new(zone()) LStackCheck(context), instr);
ager@chromium.org04921a82011-06-27 13:21:41 +00002546 } else {
2547 ASSERT(instr->is_backwards_branch());
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002548 LOperand* context = UseAny(instr->context());
2549 return AssignEnvironment(
2550 AssignPointerMap(new(zone()) LStackCheck(context)));
ager@chromium.org04921a82011-06-27 13:21:41 +00002551 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002552}
2553
2554
2555LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
ager@chromium.org378b34e2011-01-28 08:04:38 +00002556 HEnvironment* outer = current_block_->last_environment();
2557 HConstant* undefined = graph()->GetConstantUndefined();
2558 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002559 instr->arguments_count(),
ager@chromium.org378b34e2011-01-28 08:04:38 +00002560 instr->function(),
danno@chromium.org40cb8782011-05-25 07:58:50 +00002561 undefined,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00002562 instr->inlining_kind(),
2563 instr->undefined_receiver());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002564 // Only replay binding of arguments object if it wasn't removed from graph.
2565 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
2566 inner->Bind(instr->arguments_var(), instr->arguments_object());
danno@chromium.org8c0a43f2012-04-03 08:37:53 +00002567 }
ulan@chromium.org56c14af2012-09-20 12:51:09 +00002568 inner->set_entry(instr);
ager@chromium.org378b34e2011-01-28 08:04:38 +00002569 current_block_->UpdateEnvironment(inner);
2570 chunk_->AddInlinedClosure(instr->closure());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002571 return NULL;
2572}
2573
2574
2575LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002576 LInstruction* pop = NULL;
2577
2578 HEnvironment* env = current_block_->last_environment();
2579
verwaest@chromium.org33e09c82012-10-10 17:07:22 +00002580 if (env->entry()->arguments_pushed()) {
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002581 int argument_count = env->arguments_environment()->parameter_count();
2582 pop = new(zone()) LDrop(argument_count);
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +00002583 ASSERT(instr->argument_delta() == -argument_count);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002584 }
2585
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002586 HEnvironment* outer = current_block_->last_environment()->
2587 DiscardInlined(false);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002588 current_block_->UpdateEnvironment(outer);
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002589
2590 return pop;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002591}
2592
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002593
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002594LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002595 LOperand* context = UseFixed(instr->context(), rsi);
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002596 LOperand* object = UseFixed(instr->enumerable(), rax);
machenbach@chromium.org935a7792013-11-12 09:05:18 +00002597 LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002598 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
2599}
2600
2601
2602LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2603 LOperand* map = UseRegister(instr->map());
2604 return AssignEnvironment(DefineAsRegister(
ulan@chromium.org812308e2012-02-29 15:58:45 +00002605 new(zone()) LForInCacheArray(map)));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002606}
2607
2608
2609LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2610 LOperand* value = UseRegisterAtStart(instr->value());
2611 LOperand* map = UseRegisterAtStart(instr->map());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002612 return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002613}
2614
2615
2616LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2617 LOperand* object = UseRegister(instr->object());
2618 LOperand* index = UseTempRegister(instr->index());
ulan@chromium.org812308e2012-02-29 15:58:45 +00002619 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index));
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00002620}
2621
2622
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +00002623} } // namespace v8::internal
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002624
2625#endif // V8_TARGET_ARCH_X64