Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/a64/lithium-a64.cc

Issue 144963003: A64: add missing files. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/lithium-a64.h ('k') | src/a64/lithium-codegen-a64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "lithium-allocator-inl.h" 30 #include "lithium-allocator-inl.h"
31 #include "mips/lithium-mips.h" 31 #include "a64/lithium-a64.h"
32 #include "mips/lithium-codegen-mips.h" 32 #include "a64/lithium-codegen-a64.h"
33 33
34 namespace v8 { 34 namespace v8 {
35 namespace internal { 35 namespace internal {
36 36
37
37 #define DEFINE_COMPILE(type) \ 38 #define DEFINE_COMPILE(type) \
38 void L##type::CompileToNative(LCodeGen* generator) { \ 39 void L##type::CompileToNative(LCodeGen* generator) { \
39 generator->Do##type(this); \ 40 generator->Do##type(this); \
40 } 41 }
41 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) 42 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
42 #undef DEFINE_COMPILE 43 #undef DEFINE_COMPILE
43 44
44 LOsrEntry::LOsrEntry() { 45
45 for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) { 46 void LLabel::PrintDataTo(StringStream* stream) {
46 register_spills_[i] = NULL; 47 LGap::PrintDataTo(stream);
47 } 48 LLabel* rep = replacement();
48 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) { 49 if (rep != NULL) {
49 double_register_spills_[i] = NULL; 50 stream->Add(" Dead block replaced with B%d", rep->block_id());
50 } 51 }
51 } 52 }
52 53
53 54
54 void LOsrEntry::MarkSpilledRegister(int allocation_index, 55 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
55 LOperand* spill_operand) { 56 arguments()->PrintTo(stream);
56 ASSERT(spill_operand->IsStackSlot()); 57 stream->Add(" length ");
57 ASSERT(register_spills_[allocation_index] == NULL); 58 length()->PrintTo(stream);
58 register_spills_[allocation_index] = spill_operand; 59 stream->Add(" index ");
60 index()->PrintTo(stream);
59 } 61 }
60 62
61 63
62 #ifdef DEBUG 64 void LBranch::PrintDataTo(StringStream* stream) {
63 void LInstruction::VerifyCall() { 65 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
64 // Call instructions can use only fixed registers as temporaries and 66 value()->PrintTo(stream);
65 // outputs because all registers are blocked by the calling convention.
66 // Inputs operands must use a fixed register or use-at-start policy or
67 // a non-register policy.
68 ASSERT(Output() == NULL ||
69 LUnallocated::cast(Output())->HasFixedPolicy() ||
70 !LUnallocated::cast(Output())->HasRegisterPolicy());
71 for (UseIterator it(this); !it.Done(); it.Advance()) {
72 LUnallocated* operand = LUnallocated::cast(it.Current());
73 ASSERT(operand->HasFixedPolicy() ||
74 operand->IsUsedAtStart());
75 }
76 for (TempIterator it(this); !it.Done(); it.Advance()) {
77 LUnallocated* operand = LUnallocated::cast(it.Current());
78 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
79 }
80 }
81 #endif
82
83
84 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
85 LOperand* spill_operand) {
86 ASSERT(spill_operand->IsDoubleStackSlot());
87 ASSERT(double_register_spills_[allocation_index] == NULL);
88 double_register_spills_[allocation_index] = spill_operand;
89 } 67 }
90 68
91 69
70 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
71 stream->Add("#%d / ", arity());
72 }
73
74
75 void LCallNamed::PrintDataTo(StringStream* stream) {
76 SmartArrayPointer<char> name_string = name()->ToCString();
77 stream->Add("%s #%d / ", *name_string, arity());
78 }
79
80
81 void LCallKeyed::PrintDataTo(StringStream* stream) {
82 stream->Add("[x2] #%d / ", arity());
83 }
84
85
86 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
87 stream->Add("#%d / ", arity());
88 }
89
90
91 void LCallGlobal::PrintDataTo(StringStream* stream) {
92 SmartArrayPointer<char> name_string = name()->ToCString();
93 stream->Add("%s #%d / ", *name_string, arity());
94 }
95
96
97 void LCallNew::PrintDataTo(StringStream* stream) {
98 stream->Add("= ");
99 constructor()->PrintTo(stream);
100 stream->Add(" #%d / ", arity());
101 }
102
103
104 void LCallNewArray::PrintDataTo(StringStream* stream) {
105 stream->Add("= ");
106 constructor()->PrintTo(stream);
107 stream->Add(" #%d / ", arity());
108 ASSERT(hydrogen()->property_cell()->value()->IsSmi());
109 ElementsKind kind = static_cast<ElementsKind>(
110 Smi::cast(hydrogen()->property_cell()->value())->value());
111 stream->Add(" (%s) ", ElementsKindToString(kind));
112 }
113
114
115 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
116 stream->Add("if class_of_test(");
117 value()->PrintTo(stream);
118 stream->Add(", \"%o\") then B%d else B%d",
119 *hydrogen()->class_name(),
120 true_block_id(),
121 false_block_id());
122 }
123
124
125 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
126 stream->Add("if ");
127 left()->PrintTo(stream);
128 stream->Add(" %s ", Token::String(op()));
129 right()->PrintTo(stream);
130 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
131 }
132
133
134 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
135 return !gen->IsNextEmittedBlock(block_id());
136 }
137
138
139 void LGoto::PrintDataTo(StringStream* stream) {
140 stream->Add("B%d", block_id());
141 }
142
143
144 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
145 stream->Add(" = ");
146 base_object()->PrintTo(stream);
147 stream->Add(" + %d", offset());
148 }
149
150
151 void LInvokeFunction::PrintDataTo(StringStream* stream) {
152 stream->Add("= ");
153 function()->PrintTo(stream);
154 stream->Add(" #%d / ", arity());
155 }
156
157
92 void LInstruction::PrintTo(StringStream* stream) { 158 void LInstruction::PrintTo(StringStream* stream) {
93 stream->Add("%s ", this->Mnemonic()); 159 stream->Add("%s ", this->Mnemonic());
94 160
95 PrintOutputOperandTo(stream); 161 PrintOutputOperandTo(stream);
96 162
97 PrintDataTo(stream); 163 PrintDataTo(stream);
98 164
99 if (HasEnvironment()) { 165 if (HasEnvironment()) {
100 stream->Add(" "); 166 stream->Add(" ");
101 environment()->PrintTo(stream); 167 environment()->PrintTo(stream);
(...skipping 17 matching lines...) Expand all
119 } 185 }
120 } 186 }
121 } 187 }
122 188
123 189
124 void LInstruction::PrintOutputOperandTo(StringStream* stream) { 190 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
125 if (HasResult()) result()->PrintTo(stream); 191 if (HasResult()) result()->PrintTo(stream);
126 } 192 }
127 193
128 194
129 void LLabel::PrintDataTo(StringStream* stream) { 195 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
130 LGap::PrintDataTo(stream); 196 stream->Add("if has_instance_type(");
131 LLabel* rep = replacement(); 197 value()->PrintTo(stream);
132 if (rep != NULL) { 198 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
133 stream->Add(" Dead block replaced with B%d", rep->block_id()); 199 }
134 } 200
201
202 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
203 stream->Add("if is_object(");
204 value()->PrintTo(stream);
205 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
206 }
207
208
209 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
210 stream->Add("if is_string(");
211 value()->PrintTo(stream);
212 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
213 }
214
215
216 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
217 stream->Add("if is_smi(");
218 value()->PrintTo(stream);
219 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
220 }
221
222
223 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
224 stream->Add("if typeof ");
225 value()->PrintTo(stream);
226 stream->Add(" == \"%s\" then B%d else B%d",
227 *hydrogen()->type_literal()->ToCString(),
228 true_block_id(), false_block_id());
229 }
230
231
232 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
233 stream->Add("if is_undetectable(");
234 value()->PrintTo(stream);
235 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
135 } 236 }
136 237
137 238
138 bool LGap::IsRedundant() const { 239 bool LGap::IsRedundant() const {
139 for (int i = 0; i < 4; i++) { 240 for (int i = 0; i < 4; i++) {
140 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { 241 if ((parallel_moves_[i] != NULL) && !parallel_moves_[i]->IsRedundant()) {
141 return false; 242 return false;
142 } 243 }
143 } 244 }
144 245
145 return true; 246 return true;
146 } 247 }
147 248
148 249
149 void LGap::PrintDataTo(StringStream* stream) { 250 void LGap::PrintDataTo(StringStream* stream) {
150 for (int i = 0; i < 4; i++) { 251 for (int i = 0; i < 4; i++) {
151 stream->Add("("); 252 stream->Add("(");
152 if (parallel_moves_[i] != NULL) { 253 if (parallel_moves_[i] != NULL) {
153 parallel_moves_[i]->PrintDataTo(stream); 254 parallel_moves_[i]->PrintDataTo(stream);
154 } 255 }
155 stream->Add(") "); 256 stream->Add(") ");
156 } 257 }
157 } 258 }
158 259
159 260
261 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
262 context()->PrintTo(stream);
263 stream->Add("[%d]", slot_index());
264 }
265
266
267 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
268 context()->PrintTo(stream);
269 stream->Add("[%d] <- ", slot_index());
270 value()->PrintTo(stream);
271 }
272
273
274 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
275 object()->PrintTo(stream);
276 stream->Add("[");
277 key()->PrintTo(stream);
278 stream->Add("] <- ");
279 value()->PrintTo(stream);
280 }
281
282
283 void LStoreNamedField::PrintDataTo(StringStream* stream) {
284 object()->PrintTo(stream);
285 hydrogen()->access().PrintTo(stream);
286 stream->Add(" <- ");
287 value()->PrintTo(stream);
288 }
289
290
291 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
292 object()->PrintTo(stream);
293 stream->Add(".");
294 stream->Add(*String::cast(*name())->ToCString());
295 stream->Add(" <- ");
296 value()->PrintTo(stream);
297 }
298
299
300 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
301 object()->PrintTo(stream);
302 stream->Add("%p -> %p", *original_map(), *transitioned_map());
303 }
304
305
306 template<int T>
307 void LUnaryMathOperation<T>::PrintDataTo(StringStream* stream) {
308 value()->PrintTo(stream);
309 }
310
311
160 const char* LArithmeticD::Mnemonic() const { 312 const char* LArithmeticD::Mnemonic() const {
161 switch (op()) { 313 switch (op()) {
162 case Token::ADD: return "add-d"; 314 case Token::ADD: return "add-d";
163 case Token::SUB: return "sub-d"; 315 case Token::SUB: return "sub-d";
164 case Token::MUL: return "mul-d"; 316 case Token::MUL: return "mul-d";
165 case Token::DIV: return "div-d"; 317 case Token::DIV: return "div-d";
166 case Token::MOD: return "mod-d"; 318 case Token::MOD: return "mod-d";
167 default: 319 default:
168 UNREACHABLE(); 320 UNREACHABLE();
169 return NULL; 321 return NULL;
170 } 322 }
171 } 323 }
172 324
173 325
174 const char* LArithmeticT::Mnemonic() const { 326 const char* LArithmeticT::Mnemonic() const {
175 switch (op()) { 327 switch (op()) {
176 case Token::ADD: return "add-t"; 328 case Token::ADD: return "add-t";
177 case Token::SUB: return "sub-t"; 329 case Token::SUB: return "sub-t";
178 case Token::MUL: return "mul-t"; 330 case Token::MUL: return "mul-t";
179 case Token::MOD: return "mod-t"; 331 case Token::MOD: return "mod-t";
180 case Token::DIV: return "div-t"; 332 case Token::DIV: return "div-t";
181 case Token::BIT_AND: return "bit-and-t"; 333 case Token::BIT_AND: return "bit-and-t";
182 case Token::BIT_OR: return "bit-or-t"; 334 case Token::BIT_OR: return "bit-or-t";
183 case Token::BIT_XOR: return "bit-xor-t"; 335 case Token::BIT_XOR: return "bit-xor-t";
184 case Token::ROR: return "ror-t"; 336 case Token::ROR: return "ror-t";
185 case Token::SHL: return "sll-t"; 337 case Token::SHL: return "shl-t";
186 case Token::SAR: return "sra-t"; 338 case Token::SAR: return "sar-t";
187 case Token::SHR: return "srl-t"; 339 case Token::SHR: return "shr-t";
188 default: 340 default:
189 UNREACHABLE(); 341 UNREACHABLE();
190 return NULL; 342 return NULL;
191 } 343 }
192 } 344 }
193 345
194 346
195 bool LGoto::HasInterestingComment(LCodeGen* gen) const { 347 void LChunkBuilder::Abort(const char* reason) {
196 return !gen->IsNextEmittedBlock(block_id());
197 }
198
199
200 void LGoto::PrintDataTo(StringStream* stream) {
201 stream->Add("B%d", block_id());
202 }
203
204
205 void LBranch::PrintDataTo(StringStream* stream) {
206 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
207 value()->PrintTo(stream);
208 }
209
210
211 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
212 return new(zone()) LDebugBreak();
213 }
214
215 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
216 stream->Add("if ");
217 left()->PrintTo(stream);
218 stream->Add(" %s ", Token::String(op()));
219 right()->PrintTo(stream);
220 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
221 }
222
223
224 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
225 stream->Add("if is_object(");
226 value()->PrintTo(stream);
227 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
228 }
229
230
231 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
232 stream->Add("if is_string(");
233 value()->PrintTo(stream);
234 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
235 }
236
237
238 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
239 stream->Add("if is_smi(");
240 value()->PrintTo(stream);
241 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
242 }
243
244
245 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
246 stream->Add("if is_undetectable(");
247 value()->PrintTo(stream);
248 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
249 }
250
251
252 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
253 stream->Add("if string_compare(");
254 left()->PrintTo(stream);
255 right()->PrintTo(stream);
256 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
257 }
258
259
260 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
261 stream->Add("if has_instance_type(");
262 value()->PrintTo(stream);
263 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
264 }
265
266
267 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
268 stream->Add("if has_cached_array_index(");
269 value()->PrintTo(stream);
270 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
271 }
272
273
274 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
275 stream->Add("if class_of_test(");
276 value()->PrintTo(stream);
277 stream->Add(", \"%o\") then B%d else B%d",
278 *hydrogen()->class_name(),
279 true_block_id(),
280 false_block_id());
281 }
282
283
284 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
285 stream->Add("if typeof ");
286 value()->PrintTo(stream);
287 stream->Add(" == \"%s\" then B%d else B%d",
288 *hydrogen()->type_literal()->ToCString(),
289 true_block_id(), false_block_id());
290 }
291
292
293 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
294 stream->Add(" = ");
295 base_object()->PrintTo(stream);
296 stream->Add(" + %d", offset());
297 }
298
299
300 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
301 stream->Add("#%d / ", arity());
302 }
303
304
305 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
306 context()->PrintTo(stream);
307 stream->Add("[%d]", slot_index());
308 }
309
310
311 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
312 context()->PrintTo(stream);
313 stream->Add("[%d] <- ", slot_index());
314 value()->PrintTo(stream);
315 }
316
317
318 void LInvokeFunction::PrintDataTo(StringStream* stream) {
319 stream->Add("= ");
320 function()->PrintTo(stream);
321 stream->Add(" #%d / ", arity());
322 }
323
324
325 void LCallKeyed::PrintDataTo(StringStream* stream) {
326 stream->Add("[a2] #%d / ", arity());
327 }
328
329
330 void LCallNamed::PrintDataTo(StringStream* stream) {
331 SmartArrayPointer<char> name_string = name()->ToCString();
332 stream->Add("%s #%d / ", *name_string, arity());
333 }
334
335
336 void LCallGlobal::PrintDataTo(StringStream* stream) {
337 SmartArrayPointer<char> name_string = name()->ToCString();
338 stream->Add("%s #%d / ", *name_string, arity());
339 }
340
341
342 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
343 stream->Add("#%d / ", arity());
344 }
345
346
347 void LCallNew::PrintDataTo(StringStream* stream) {
348 stream->Add("= ");
349 constructor()->PrintTo(stream);
350 stream->Add(" #%d / ", arity());
351 }
352
353
354 void LCallNewArray::PrintDataTo(StringStream* stream) {
355 stream->Add("= ");
356 constructor()->PrintTo(stream);
357 stream->Add(" #%d / ", arity());
358 ASSERT(hydrogen()->property_cell()->value()->IsSmi());
359 ElementsKind kind = static_cast<ElementsKind>(
360 Smi::cast(hydrogen()->property_cell()->value())->value());
361 stream->Add(" (%s) ", ElementsKindToString(kind));
362 }
363
364
365 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
366 arguments()->PrintTo(stream);
367 stream->Add(" length ");
368 length()->PrintTo(stream);
369 stream->Add(" index ");
370 index()->PrintTo(stream);
371 }
372
373
374 void LStoreNamedField::PrintDataTo(StringStream* stream) {
375 object()->PrintTo(stream);
376 hydrogen()->access().PrintTo(stream);
377 stream->Add(" <- ");
378 value()->PrintTo(stream);
379 }
380
381
382 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
383 object()->PrintTo(stream);
384 stream->Add(".");
385 stream->Add(*String::cast(*name())->ToCString());
386 stream->Add(" <- ");
387 value()->PrintTo(stream);
388 }
389
390
391 void LLoadKeyed::PrintDataTo(StringStream* stream) {
392 elements()->PrintTo(stream);
393 stream->Add("[");
394 key()->PrintTo(stream);
395 if (hydrogen()->IsDehoisted()) {
396 stream->Add(" + %d]", additional_index());
397 } else {
398 stream->Add("]");
399 }
400 }
401
402
403 void LStoreKeyed::PrintDataTo(StringStream* stream) {
404 elements()->PrintTo(stream);
405 stream->Add("[");
406 key()->PrintTo(stream);
407 if (hydrogen()->IsDehoisted()) {
408 stream->Add(" + %d] <-", additional_index());
409 } else {
410 stream->Add("] <- ");
411 }
412
413 if (value() == NULL) {
414 ASSERT(hydrogen()->IsConstantHoleStore() &&
415 hydrogen()->value()->representation().IsDouble());
416 stream->Add("<the hole(nan)>");
417 } else {
418 value()->PrintTo(stream);
419 }
420 }
421
422
423 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
424 object()->PrintTo(stream);
425 stream->Add("[");
426 key()->PrintTo(stream);
427 stream->Add("] <- ");
428 value()->PrintTo(stream);
429 }
430
431
432 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
433 object()->PrintTo(stream);
434 stream->Add(" %p -> %p", *original_map(), *transitioned_map());
435 }
436
437
438 int LPlatformChunk::GetNextSpillIndex(bool is_double) {
439 // Skip a slot if for a double-width slot.
440 if (is_double) spill_slot_count_++;
441 return spill_slot_count_++;
442 }
443
444
445 LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
446 int index = GetNextSpillIndex(is_double);
447 if (is_double) {
448 return LDoubleStackSlot::Create(index, zone());
449 } else {
450 return LStackSlot::Create(index, zone());
451 }
452 }
453
454
455 LPlatformChunk* LChunkBuilder::Build() {
456 ASSERT(is_unused());
457 chunk_ = new(zone()) LPlatformChunk(info(), graph());
458 HPhase phase("L_Building chunk", chunk_);
459 status_ = BUILDING;
460 const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
461 for (int i = 0; i < blocks->length(); i++) {
462 HBasicBlock* next = NULL;
463 if (i < blocks->length() - 1) next = blocks->at(i + 1);
464 DoBasicBlock(blocks->at(i), next);
465 if (is_aborted()) return NULL;
466 }
467 status_ = DONE;
468 return chunk_;
469 }
470
471
472 void LCodeGen::Abort(const char* reason) {
473 info()->set_bailout_reason(reason); 348 info()->set_bailout_reason(reason);
474 status_ = ABORTED; 349 status_ = ABORTED;
475 } 350 }
476 351
477 352
478 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { 353 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
479 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER, 354 return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
480 Register::ToAllocationIndex(reg)); 355 Register::ToAllocationIndex(reg));
481 } 356 }
482 357
483 358
484 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { 359 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
485 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, 360 return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
486 DoubleRegister::ToAllocationIndex(reg)); 361 DoubleRegister::ToAllocationIndex(reg));
487 } 362 }
488 363
489 364
365 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
366 if (value->EmitAtUses()) {
367 HInstruction* instr = HInstruction::cast(value);
368 VisitInstruction(instr);
369 }
370 operand->set_virtual_register(value->id());
371 return operand;
372 }
373
374
490 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { 375 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
491 return Use(value, ToUnallocated(fixed_register)); 376 return Use(value, ToUnallocated(fixed_register));
492 } 377 }
493 378
494 379
495 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { 380 LOperand* LChunkBuilder::UseFixedDouble(HValue* value,
496 return Use(value, ToUnallocated(reg)); 381 DoubleRegister fixed_register) {
382 return Use(value, ToUnallocated(fixed_register));
497 } 383 }
498 384
499 385
500 LOperand* LChunkBuilder::UseRegister(HValue* value) { 386 LOperand* LChunkBuilder::UseRegister(HValue* value) {
501 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); 387 return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
502 } 388 }
503 389
504 390
391 LOperand* LChunkBuilder::UseRegisterAndClobber(HValue* value) {
392 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
393 }
394
395
505 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { 396 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
506 return Use(value, 397 return Use(value,
507 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, 398 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
508 LUnallocated::USED_AT_START)); 399 LUnallocated::USED_AT_START));
509 } 400 }
510 401
511 402
512 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
513 return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
514 }
515
516
517 LOperand* LChunkBuilder::Use(HValue* value) {
518 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE));
519 }
520
521
522 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
523 return Use(value, new(zone()) LUnallocated(LUnallocated::NONE,
524 LUnallocated::USED_AT_START));
525 }
526
527
528 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
529 return value->IsConstant()
530 ? chunk_->DefineConstantOperand(HConstant::cast(value))
531 : Use(value);
532 }
533
534
535 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
536 return value->IsConstant()
537 ? chunk_->DefineConstantOperand(HConstant::cast(value))
538 : UseAtStart(value);
539 }
540
541
542 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { 403 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
543 return value->IsConstant() 404 return value->IsConstant() ? UseConstant(value) : UseRegister(value);
544 ? chunk_->DefineConstantOperand(HConstant::cast(value))
545 : UseRegister(value);
546 } 405 }
547 406
548 407
549 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { 408 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
550 return value->IsConstant() 409 return value->IsConstant() ? UseConstant(value) : UseRegisterAtStart(value);
551 ? chunk_->DefineConstantOperand(HConstant::cast(value))
552 : UseRegisterAtStart(value);
553 } 410 }
554 411
555 412
556 LOperand* LChunkBuilder::UseConstant(HValue* value) { 413 LConstantOperand* LChunkBuilder::UseConstant(HValue* value) {
557 return chunk_->DefineConstantOperand(HConstant::cast(value)); 414 return chunk_->DefineConstantOperand(HConstant::cast(value));
558 } 415 }
559 416
560 417
561 LOperand* LChunkBuilder::UseAny(HValue* value) { 418 LOperand* LChunkBuilder::UseAny(HValue* value) {
562 return value->IsConstant() 419 return value->IsConstant()
563 ? chunk_->DefineConstantOperand(HConstant::cast(value)) 420 ? UseConstant(value)
564 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY)); 421 : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
565 } 422 }
566 423
567 424
568 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
569 if (value->EmitAtUses()) {
570 HInstruction* instr = HInstruction::cast(value);
571 VisitInstruction(instr);
572 }
573 operand->set_virtual_register(value->id());
574 return operand;
575 }
576
577
578 template<int I, int T> 425 template<int I, int T>
579 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr, 426 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
580 LUnallocated* result) { 427 LUnallocated* result) {
581 result->set_virtual_register(current_instruction_->id()); 428 result->set_virtual_register(current_instruction_->id());
582 instr->set_result(result); 429 instr->set_result(result);
583 return instr; 430 return instr;
584 } 431 }
585 432
586 433
587 template<int I, int T> 434 template<int I, int T>
(...skipping 27 matching lines...) Expand all
615 } 462 }
616 463
617 464
618 template<int I, int T> 465 template<int I, int T>
619 LInstruction* LChunkBuilder::DefineFixedDouble( 466 LInstruction* LChunkBuilder::DefineFixedDouble(
620 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) { 467 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
621 return Define(instr, ToUnallocated(reg)); 468 return Define(instr, ToUnallocated(reg));
622 } 469 }
623 470
624 471
625 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
626 HEnvironment* hydrogen_env = current_block_->last_environment();
627 int argument_index_accumulator = 0;
628 instr->set_environment(CreateEnvironment(hydrogen_env,
629 &argument_index_accumulator));
630 return instr;
631 }
632
633
634 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, 472 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
635 HInstruction* hinstr, 473 HInstruction* hinstr,
636 CanDeoptimize can_deoptimize) { 474 CanDeoptimize can_deoptimize) {
637 info()->MarkAsNonDeferredCalling(); 475 info()->MarkAsNonDeferredCalling();
638 #ifdef DEBUG 476 // TODO(all): Verify call in debug mode.
639 instr->VerifyCall();
640 #endif
641 instr->MarkAsCall(); 477 instr->MarkAsCall();
642 instr = AssignPointerMap(instr); 478 instr = AssignPointerMap(instr);
643 479
644 if (hinstr->HasObservableSideEffects()) { 480 if (hinstr->HasObservableSideEffects()) {
645 ASSERT(hinstr->next()->IsSimulate()); 481 ASSERT(hinstr->next()->IsSimulate());
646 HSimulate* sim = HSimulate::cast(hinstr->next()); 482 HSimulate* sim = HSimulate::cast(hinstr->next());
647 ASSERT(instruction_pending_deoptimization_environment_ == NULL); 483 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
648 ASSERT(pending_deoptimization_ast_id_.IsNone()); 484 ASSERT(pending_deoptimization_ast_id_.IsNone());
649 instruction_pending_deoptimization_environment_ = instr; 485 instruction_pending_deoptimization_environment_ = instr;
650 pending_deoptimization_ast_id_ = sim->ast_id(); 486 pending_deoptimization_ast_id_ = sim->ast_id();
(...skipping 27 matching lines...) Expand all
678 int vreg = allocator_->GetVirtualRegister(); 514 int vreg = allocator_->GetVirtualRegister();
679 if (!allocator_->AllocationOk()) { 515 if (!allocator_->AllocationOk()) {
680 Abort("Out of virtual registers while trying to allocate temp register."); 516 Abort("Out of virtual registers while trying to allocate temp register.");
681 vreg = 0; 517 vreg = 0;
682 } 518 }
683 operand->set_virtual_register(vreg); 519 operand->set_virtual_register(vreg);
684 return operand; 520 return operand;
685 } 521 }
686 522
687 523
688 LOperand* LChunkBuilder::FixedTemp(Register reg) { 524 int LPlatformChunk::GetNextSpillIndex() {
689 LUnallocated* operand = ToUnallocated(reg); 525 return spill_slot_count_++;
690 ASSERT(operand->HasFixedPolicy()); 526 }
691 return operand; 527
528
529 LOperand* LPlatformChunk::GetNextSpillSlot(bool is_double) {
530 int index = GetNextSpillIndex();
531 if (is_double) {
532 return LDoubleStackSlot::Create(index, zone());
533 } else {
534 return LStackSlot::Create(index, zone());
535 }
692 } 536 }
693 537
694 538
695 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { 539 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
696 LUnallocated* operand = ToUnallocated(reg); 540 LUnallocated* operand = ToUnallocated(reg);
697 ASSERT(operand->HasFixedPolicy()); 541 ASSERT(operand->HasFixedPolicy());
698 return operand; 542 return operand;
699 } 543 }
700 544
701 545
702 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { 546 LPlatformChunk* LChunkBuilder::Build() {
703 return new(zone()) LLabel(instr->block()); 547 ASSERT(is_unused());
548 chunk_ = new(zone_) LPlatformChunk(info_, graph_);
549 HPhase phase("L_Building chunk", chunk_);
550 status_ = BUILDING;
551 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
552 for (int i = 0; i < blocks->length(); i++) {
553 DoBasicBlock(blocks->at(i));
554 if (is_aborted()) return NULL;
555 }
556 status_ = DONE;
557 return chunk_;
704 } 558 }
705 559
706 560
707 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { 561 void LChunkBuilder::DoBasicBlock(HBasicBlock* block) {
708 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
709 }
710
711
712 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
713 UNREACHABLE();
714 return NULL;
715 }
716
717
718 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
719 return AssignEnvironment(new(zone()) LDeoptimize);
720 }
721
722
723 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
724 return AssignEnvironment(new(zone()) LDeoptimize);
725 }
726
727
728 LInstruction* LChunkBuilder::DoShift(Token::Value op,
729 HBitwiseBinaryOperation* instr) {
730 if (instr->representation().IsSmiOrTagged()) {
731 ASSERT(instr->left()->representation().IsSmiOrTagged());
732 ASSERT(instr->right()->representation().IsSmiOrTagged());
733
734 LOperand* left = UseFixed(instr->left(), a1);
735 LOperand* right = UseFixed(instr->right(), a0);
736 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right);
737 return MarkAsCall(DefineFixed(result, v0), instr);
738 }
739
740 ASSERT(instr->representation().IsInteger32());
741 ASSERT(instr->left()->representation().IsInteger32());
742 ASSERT(instr->right()->representation().IsInteger32());
743 LOperand* left = UseRegisterAtStart(instr->left());
744
745 HValue* right_value = instr->right();
746 LOperand* right = NULL;
747 int constant_value = 0;
748 if (right_value->IsConstant()) {
749 HConstant* constant = HConstant::cast(right_value);
750 right = chunk_->DefineConstantOperand(constant);
751 constant_value = constant->Integer32Value() & 0x1f;
752 } else {
753 right = UseRegisterAtStart(right_value);
754 }
755
756 // Shift operations can only deoptimize if we do a logical shift
757 // by 0 and the result cannot be truncated to int32.
758 bool does_deopt = false;
759 if (op == Token::SHR && constant_value == 0) {
760 if (FLAG_opt_safe_uint32_operations) {
761 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
762 } else {
763 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
764 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
765 does_deopt = true;
766 break;
767 }
768 }
769 }
770 }
771
772 LInstruction* result =
773 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
774 return does_deopt ? AssignEnvironment(result) : result;
775 }
776
777
778 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
779 HArithmeticBinaryOperation* instr) {
780 ASSERT(instr->representation().IsDouble());
781 ASSERT(instr->left()->representation().IsDouble());
782 ASSERT(instr->right()->representation().IsDouble());
783 ASSERT(op != Token::MOD);
784 LOperand* left = UseRegisterAtStart(instr->left());
785 LOperand* right = UseRegisterAtStart(instr->right());
786 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
787 return DefineAsRegister(result);
788 }
789
790
791 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
792 HArithmeticBinaryOperation* instr) {
793 ASSERT(op == Token::ADD ||
794 op == Token::DIV ||
795 op == Token::MOD ||
796 op == Token::MUL ||
797 op == Token::SUB);
798 HValue* left = instr->left();
799 HValue* right = instr->right();
800 ASSERT(left->representation().IsSmiOrTagged());
801 ASSERT(right->representation().IsSmiOrTagged());
802 LOperand* left_operand = UseFixed(left, a1);
803 LOperand* right_operand = UseFixed(right, a0);
804 LArithmeticT* result =
805 new(zone()) LArithmeticT(op, left_operand, right_operand);
806 return MarkAsCall(DefineFixed(result, v0), instr);
807 }
808
809
810 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
811 ASSERT(is_building()); 562 ASSERT(is_building());
812 current_block_ = block; 563 current_block_ = block;
813 next_block_ = next_block; 564
814 if (block->IsStartBlock()) { 565 if (block->IsStartBlock()) {
815 block->UpdateEnvironment(graph_->start_environment()); 566 block->UpdateEnvironment(graph_->start_environment());
816 argument_count_ = 0; 567 argument_count_ = 0;
817 } else if (block->predecessors()->length() == 1) { 568 } else if (block->predecessors()->length() == 1) {
818 // We have a single predecessor => copy environment and outgoing 569 // We have a single predecessor => copy environment and outgoing
819 // argument count from the predecessor. 570 // argument count from the predecessor.
820 ASSERT(block->phis()->length() == 0); 571 ASSERT(block->phis()->length() == 0);
821 HBasicBlock* pred = block->predecessors()->at(0); 572 HBasicBlock* pred = block->predecessors()->at(0);
822 HEnvironment* last_environment = pred->last_environment(); 573 HEnvironment* last_environment = pred->last_environment();
823 ASSERT(last_environment != NULL); 574 ASSERT(last_environment != NULL);
575
824 // Only copy the environment, if it is later used again. 576 // Only copy the environment, if it is later used again.
825 if (pred->end()->SecondSuccessor() == NULL) { 577 if (pred->end()->SecondSuccessor() == NULL) {
826 ASSERT(pred->end()->FirstSuccessor() == block); 578 ASSERT(pred->end()->FirstSuccessor() == block);
827 } else { 579 } else {
828 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() || 580 if ((pred->end()->FirstSuccessor()->block_id() > block->block_id()) ||
829 pred->end()->SecondSuccessor()->block_id() > block->block_id()) { 581 (pred->end()->SecondSuccessor()->block_id() > block->block_id())) {
830 last_environment = last_environment->Copy(); 582 last_environment = last_environment->Copy();
831 } 583 }
832 } 584 }
833 block->UpdateEnvironment(last_environment); 585 block->UpdateEnvironment(last_environment);
834 ASSERT(pred->argument_count() >= 0); 586 ASSERT(pred->argument_count() >= 0);
835 argument_count_ = pred->argument_count(); 587 argument_count_ = pred->argument_count();
836 } else { 588 } else {
837 // We are at a state join => process phis. 589 // We are at a state join => process phis.
838 HBasicBlock* pred = block->predecessors()->at(0); 590 HBasicBlock* pred = block->predecessors()->at(0);
839 // No need to copy the environment, it cannot be used later. 591 // No need to copy the environment, it cannot be used later.
840 HEnvironment* last_environment = pred->last_environment(); 592 HEnvironment* last_environment = pred->last_environment();
841 for (int i = 0; i < block->phis()->length(); ++i) { 593 for (int i = 0; i < block->phis()->length(); ++i) {
842 HPhi* phi = block->phis()->at(i); 594 HPhi* phi = block->phis()->at(i);
843 if (phi->merged_index() < last_environment->length()) { 595 if (phi->merged_index() < last_environment->length()) {
844 last_environment->SetValueAt(phi->merged_index(), phi); 596 last_environment->SetValueAt(phi->merged_index(), phi);
845 } 597 }
846 } 598 }
847 for (int i = 0; i < block->deleted_phis()->length(); ++i) { 599 for (int i = 0; i < block->deleted_phis()->length(); ++i) {
848 if (block->deleted_phis()->at(i) < last_environment->length()) { 600 if (block->deleted_phis()->at(i) < last_environment->length()) {
849 last_environment->SetValueAt(block->deleted_phis()->at(i), 601 last_environment->SetValueAt(block->deleted_phis()->at(i),
850 graph_->GetConstantUndefined()); 602 graph_->GetConstantUndefined());
851 } 603 }
852 } 604 }
853 block->UpdateEnvironment(last_environment); 605 block->UpdateEnvironment(last_environment);
854 // Pick up the outgoing argument count of one of the predecessors. 606 // Pick up the outgoing argument count of one of the predecessors.
855 argument_count_ = pred->argument_count(); 607 argument_count_ = pred->argument_count();
856 } 608 }
609
610 // Translate hydrogen instructions to lithium ones for the current block.
857 HInstruction* current = block->first(); 611 HInstruction* current = block->first();
858 int start = chunk_->instructions()->length(); 612 int start = chunk_->instructions()->length();
859 while (current != NULL && !is_aborted()) { 613 while ((current != NULL) && !is_aborted()) {
860 // Code for constants in registers is generated lazily. 614 // Code for constants in registers is generated lazily.
861 if (!current->EmitAtUses()) { 615 if (!current->EmitAtUses()) {
862 VisitInstruction(current); 616 VisitInstruction(current);
863 } 617 }
864 current = current->next(); 618 current = current->next();
865 } 619 }
866 int end = chunk_->instructions()->length() - 1; 620 int end = chunk_->instructions()->length() - 1;
867 if (end >= start) { 621 if (end >= start) {
868 block->set_first_instruction_index(start); 622 block->set_first_instruction_index(start);
869 block->set_last_instruction_index(end); 623 block->set_last_instruction_index(end);
870 } 624 }
871 block->set_argument_count(argument_count_); 625 block->set_argument_count(argument_count_);
872 next_block_ = NULL;
873 current_block_ = NULL; 626 current_block_ = NULL;
874 } 627 }
875 628
876 629
877 void LChunkBuilder::VisitInstruction(HInstruction* current) { 630 void LChunkBuilder::VisitInstruction(HInstruction* current) {
878 HInstruction* old_current = current_instruction_; 631 HInstruction* old_current = current_instruction_;
879 current_instruction_ = current; 632 current_instruction_ = current;
880 if (current->has_position()) position_ = current->position(); 633 if (current->has_position()) position_ = current->position();
881 LInstruction* instr = current->CompileToLithium(this); 634 LInstruction* instr = current->CompileToLithium(this);
882 635
883 if (instr != NULL) { 636 if (instr != NULL) {
884 #if DEBUG 637 #if DEBUG
885 // Make sure that the lithium instruction has either no fixed register 638 // Make sure that the lithium instruction has either no fixed register
886 // constraints in temps or the result OR no uses that are only used at 639 // constraints in temps or the result OR no uses that are only used at
887 // start. If this invariant doesn't hold, the register allocator can decide 640 // start. If this invariant doesn't hold, the register allocator can decide
888 // to insert a split of a range immediately before the instruction due to an 641 // to insert a split of a range immediately before the instruction due to an
889 // already allocated register needing to be used for the instruction's fixed 642 // already allocated register needing to be used for the instruction's fixed
890 // register constraint. In this case, The register allocator won't see an 643 // register constraint. In this case, the register allocator won't see an
891 // interference between the split child and the use-at-start (it would if 644 // interference between the split child and the use-at-start (it would if
892 // the it was just a plain use), so it is free to move the split child into 645 // the it was just a plain use), so it is free to move the split child into
893 // the same register that is used for the use-at-start. 646 // the same register that is used for the use-at-start.
894 // See https://code.google.com/p/chromium/issues/detail?id=201590 647 // See https://code.google.com/p/chromium/issues/detail?id=201590
895 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) { 648 if (!(instr->ClobbersRegisters() && instr->ClobbersDoubleRegisters())) {
896 int fixed = 0; 649 int fixed = 0;
897 int used_at_start = 0; 650 int used_at_start = 0;
898 for (UseIterator it(instr); !it.Done(); it.Advance()) { 651 for (UseIterator it(instr); !it.Done(); it.Advance()) {
899 LUnallocated* operand = LUnallocated::cast(it.Current()); 652 LUnallocated* operand = LUnallocated::cast(it.Current());
900 if (operand->IsUsedAtStart()) ++used_at_start; 653 if (operand->IsUsedAtStart()) ++used_at_start;
901 } 654 }
902 if (instr->Output() != NULL) { 655 if (instr->Output() != NULL) {
903 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed; 656 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
904 } 657 }
905 for (TempIterator it(instr); !it.Done(); it.Advance()) { 658 for (TempIterator it(instr); !it.Done(); it.Advance()) {
906 LUnallocated* operand = LUnallocated::cast(it.Current()); 659 LUnallocated* operand = LUnallocated::cast(it.Current());
907 if (operand->HasFixedPolicy()) ++fixed; 660 if (operand->HasFixedPolicy()) ++fixed;
908 } 661 }
909 ASSERT(fixed == 0 || used_at_start == 0); 662 ASSERT(fixed == 0 || used_at_start == 0);
910 } 663 }
911 #endif 664 #endif
912 665
913 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { 666 // TODO(all): Add support for FLAG_stress_pointer_maps and
914 instr = AssignPointerMap(instr); 667 // FLAG_stress_environments.
915 }
916 if (FLAG_stress_environments && !instr->HasEnvironment()) {
917 instr = AssignEnvironment(instr);
918 }
919 instr->set_hydrogen_value(current); 668 instr->set_hydrogen_value(current);
920 chunk_->AddInstruction(instr, current_block_); 669 chunk_->AddInstruction(instr, current_block_);
921 } 670 }
922 current_instruction_ = old_current; 671 current_instruction_ = old_current;
923 } 672 }
924 673
925 674
675 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
676 HEnvironment* hydrogen_env = current_block_->last_environment();
677 int argument_index_accumulator = 0;
678 instr->set_environment(CreateEnvironment(hydrogen_env,
679 &argument_index_accumulator));
680 return instr;
681 }
682
683
926 LEnvironment* LChunkBuilder::CreateEnvironment( 684 LEnvironment* LChunkBuilder::CreateEnvironment(
927 HEnvironment* hydrogen_env, 685 HEnvironment* hydrogen_env,
928 int* argument_index_accumulator) { 686 int* argument_index_accumulator) {
929 if (hydrogen_env == NULL) return NULL; 687 if (hydrogen_env == NULL) return NULL;
930 688
931 LEnvironment* outer = 689 LEnvironment* outer =
932 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); 690 CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
933 BailoutId ast_id = hydrogen_env->ast_id(); 691 BailoutId ast_id = hydrogen_env->ast_id();
934 ASSERT(!ast_id.IsNone() || 692 ASSERT(!ast_id.IsNone() || (hydrogen_env->frame_type() != JS_FUNCTION));
935 hydrogen_env->frame_type() != JS_FUNCTION);
936 int value_count = hydrogen_env->length(); 693 int value_count = hydrogen_env->length();
694
937 LEnvironment* result = new(zone()) LEnvironment( 695 LEnvironment* result = new(zone()) LEnvironment(
938 hydrogen_env->closure(), 696 hydrogen_env->closure(),
939 hydrogen_env->frame_type(), 697 hydrogen_env->frame_type(),
940 ast_id, 698 ast_id,
941 hydrogen_env->parameter_count(), 699 hydrogen_env->parameter_count(),
942 argument_count_, 700 argument_count(),
943 value_count, 701 value_count,
944 outer, 702 outer,
945 hydrogen_env->entry(), 703 hydrogen_env->entry(),
946 zone()); 704 zone());
705
947 int argument_index = *argument_index_accumulator; 706 int argument_index = *argument_index_accumulator;
948 for (int i = 0; i < value_count; ++i) { 707 for (int i = 0; i < value_count; ++i) {
949 if (hydrogen_env->is_special_index(i)) continue; 708 if (hydrogen_env->is_special_index(i)) continue;
950 709
951 HValue* value = hydrogen_env->values()->at(i); 710 HValue* value = hydrogen_env->values()->at(i);
952 LOperand* op = NULL; 711 LOperand* op = NULL;
953 if (value->IsArgumentsObject()) { 712 if (value->IsArgumentsObject()) {
954 op = NULL; 713 op = NULL;
955 } else if (value->IsPushArgument()) { 714 } else if (value->IsPushArgument()) {
956 op = new(zone()) LArgument(argument_index++); 715 op = new(zone()) LArgument(argument_index++);
957 } else { 716 } else {
958 op = UseAny(value); 717 op = UseAny(value);
959 } 718 }
960 result->AddValue(op, 719 result->AddValue(op,
961 value->representation(), 720 value->representation(),
962 value->CheckFlag(HInstruction::kUint32)); 721 value->CheckFlag(HInstruction::kUint32));
963 } 722 }
964 723
965 if (hydrogen_env->frame_type() == JS_FUNCTION) { 724 if (hydrogen_env->frame_type() == JS_FUNCTION) {
966 *argument_index_accumulator = argument_index; 725 *argument_index_accumulator = argument_index;
967 } 726 }
968 727
969 return result; 728 return result;
970 } 729 }
971 730
972 731
973 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { 732 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
974 return new(zone()) LGoto(instr->FirstSuccessor()->block_id()); 733 HArithmeticBinaryOperation* instr) {
975 } 734 ASSERT(instr->representation().IsDouble());
976 735 ASSERT(instr->left()->representation().IsDouble());
977 736 ASSERT(instr->right()->representation().IsDouble());
978 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { 737
979 HValue* value = instr->value(); 738 if (op == Token::MOD) {
980 if (value->EmitAtUses()) { 739 LOperand* left = UseFixedDouble(instr->left(), d0);
981 HBasicBlock* successor = HConstant::cast(value)->BooleanValue() 740 LOperand* right = UseFixedDouble(instr->right(), d1);
982 ? instr->FirstSuccessor() 741 LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
983 : instr->SecondSuccessor(); 742 return MarkAsCall(DefineFixedDouble(result, d0), instr);
984 return new(zone()) LGoto(successor->block_id()); 743 } else {
985 } 744 LOperand* left = UseRegisterAtStart(instr->left());
986 745 LOperand* right = UseRegisterAtStart(instr->right());
987 LBranch* result = new(zone()) LBranch(UseRegister(value)); 746 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
988 // Tagged values that are not known smis or booleans require a 747 return DefineAsRegister(result);
989 // deoptimization environment. 748 }
990 Representation rep = value->representation(); 749 }
991 HType type = value->type(); 750
992 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) { 751
993 return AssignEnvironment(result); 752 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
994 } 753 HBinaryOperation* instr) {
995 return result; 754 ASSERT((op == Token::ADD) || (op == Token::SUB) || (op == Token::MUL) ||
996 } 755 (op == Token::DIV) || (op == Token::MOD) || (op == Token::SHR) ||
997 756 (op == Token::SHL) || (op == Token::SAR) || (op == Token::ROR) ||
998 757 (op == Token::BIT_OR) || (op == Token::BIT_AND) ||
999 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { 758 (op == Token::BIT_XOR));
1000 ASSERT(instr->value()->representation().IsTagged()); 759 HValue* left = instr->left();
1001 LOperand* value = UseRegisterAtStart(instr->value()); 760 HValue* right = instr->right();
1002 LOperand* temp = TempRegister(); 761
1003 return new(zone()) LCmpMapAndBranch(value, temp); 762 ASSERT(instr->representation().IsSmiOrTagged());
1004 } 763 ASSERT(left->representation().IsSmiOrTagged());
1005 764 ASSERT(right->representation().IsSmiOrTagged());
1006 765
1007 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { 766 LOperand* left_operand = UseFixed(left, x1);
767 LOperand* right_operand = UseFixed(right, x0);
768 LArithmeticT* result =
769 new(zone()) LArithmeticT(op, left_operand, right_operand);
770 return MarkAsCall(DefineFixed(result, x0), instr);
771 }
772
773
774 #define UNIMPLEMENTED_INSTRUCTION() \
775 do { \
776 static char msg[128]; \
777 snprintf(msg, sizeof(msg), \
778 "unsupported hydrogen instruction (%s)", __func__); \
779 info_->set_bailout_reason(msg); \
780 status_ = ABORTED; \
781 return NULL; \
782 } while (0)
783
784
785 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation(
786 HBoundsCheckBaseIndexInformation* instr) {
787 UNREACHABLE();
788 return NULL;
789 }
790
791
792 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
793 // The control instruction marking the end of a block that completed abruptly
794 // (e.g., threw an exception). There is nothing specific to do.
795 return NULL;
796 }
797
798
799 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
1008 info()->MarkAsRequiresFrame(); 800 info()->MarkAsRequiresFrame();
801 LOperand* args = NULL;
802 LOperand* length = NULL;
803 LOperand* index = NULL;
804 LOperand* temp = NULL;
805
806 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
807 args = UseRegisterAtStart(instr->arguments());
808 length = UseConstant(instr->length());
809 index = UseConstant(instr->index());
810 } else {
811 args = UseRegister(instr->arguments());
812 length = UseRegisterAtStart(instr->length());
813 index = UseRegisterOrConstantAtStart(instr->index());
814 temp = TempRegister();
815 }
816
1009 return DefineAsRegister( 817 return DefineAsRegister(
1010 new(zone()) LArgumentsLength(UseRegister(length->value()))); 818 new(zone()) LAccessArgumentsAt(args, length, index, temp));
1011 } 819 }
1012 820
1013 821
1014 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { 822 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1015 info()->MarkAsRequiresFrame(); 823 if (instr->representation().IsInteger32()) {
1016 return DefineAsRegister(new(zone()) LArgumentsElements); 824 // TODO(all): LAddI instruction should also handle the addition of
1017 } 825 // two SMI values.
1018 826 ASSERT(instr->left()->representation().IsInteger32());
1019 827 ASSERT(instr->right()->representation().IsInteger32());
1020 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { 828 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1021 LInstanceOf* result = 829 LOperand* right =
1022 new(zone()) LInstanceOf(UseFixed(instr->left(), a0), 830 UseRegisterOrConstantAtStart(instr->BetterRightOperand());
1023 UseFixed(instr->right(), a1)); 831 LInstruction* result = DefineAsRegister(new(zone()) LAddI(left, right));
1024 return MarkAsCall(DefineFixed(result, v0), instr); 832 if (instr->CheckFlag(HValue::kCanOverflow)) {
1025 } 833 result = AssignEnvironment(result);
1026 834 }
1027 835 return result;
1028 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( 836 } else if (instr->representation().IsDouble()) {
1029 HInstanceOfKnownGlobal* instr) { 837 return DoArithmeticD(Token::ADD, instr);
1030 LInstanceOfKnownGlobal* result = 838 } else {
1031 new(zone()) LInstanceOfKnownGlobal(UseFixed(instr->left(), a0), 839 ASSERT(instr->representation().IsSmiOrTagged());
1032 FixedTemp(t0)); 840 return DoArithmeticT(Token::ADD, instr);
1033 return MarkAsCall(DefineFixed(result, v0), instr); 841 }
1034 } 842 }
1035 843
1036 844
1037 LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) { 845 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
1038 LOperand* object = UseRegisterAtStart(instr->object()); 846 info()->MarkAsDeferredCalling();
1039 return DefineAsRegister(new(zone()) LInstanceSize(object)); 847 LOperand* size = UseRegisterOrConstant(instr->size());
1040 } 848 LOperand* temp1 = TempRegister();
1041 849 LOperand* temp2 = TempRegister();
1042 850 LAllocate* result = new(zone()) LAllocate(size, temp1, temp2);
1043 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { 851 return AssignPointerMap(DefineAsRegister(result));
1044 LOperand* receiver = UseRegisterAtStart(instr->receiver());
1045 LOperand* function = UseRegisterAtStart(instr->function());
1046 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
1047 return AssignEnvironment(DefineSameAsFirst(result));
1048 } 852 }
1049 853
1050 854
1051 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { 855 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1052 LOperand* function = UseFixed(instr->function(), a1); 856 LOperand* function = UseFixed(instr->function(), x1);
1053 LOperand* receiver = UseFixed(instr->receiver(), a0); 857 LOperand* receiver = UseFixed(instr->receiver(), x0);
1054 LOperand* length = UseFixed(instr->length(), a2); 858 LOperand* length = UseFixed(instr->length(), x2);
1055 LOperand* elements = UseFixed(instr->elements(), a3); 859 LOperand* elements = UseFixed(instr->elements(), x3);
1056 LApplyArguments* result = new(zone()) LApplyArguments(function, 860 LApplyArguments* result = new(zone()) LApplyArguments(function,
1057 receiver, 861 receiver,
1058 length, 862 length,
1059 elements); 863 elements);
1060 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY); 864 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
1061 } 865 }
1062 866
1063 867
1064 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { 868 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* instr) {
1065 ++argument_count_; 869 info()->MarkAsRequiresFrame();
1066 LOperand* argument = Use(instr->argument()); 870 LOperand* temp = instr->from_inlined() ? NULL : TempRegister();
1067 return new(zone()) LPushArgument(argument); 871 return DefineAsRegister(new(zone()) LArgumentsElements(temp));
1068 } 872 }
1069 873
1070 874
1071 LInstruction* LChunkBuilder::DoInnerAllocatedObject( 875 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
1072 HInnerAllocatedObject* inner_object) { 876 info()->MarkAsRequiresFrame();
1073 LOperand* base_object = UseRegisterAtStart(inner_object->base_object()); 877 LOperand* value = UseRegisterAtStart(instr->value());
1074 LInnerAllocatedObject* result = 878 return DefineAsRegister(new(zone()) LArgumentsLength(value));
1075 new(zone()) LInnerAllocatedObject(base_object); 879 }
1076 return DefineAsRegister(result); 880
1077 } 881
1078 882 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
1079 883 // There are no real uses of the arguments object.
1080 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { 884 // arguments.length and element access are supported directly on
1081 return instr->HasNoUses() 885 // stack arguments, and any real arguments object use causes a bailout.
1082 ? NULL 886 // So this value is never used.
1083 : DefineAsRegister(new(zone()) LThisFunction);
1084 }
1085
1086
1087 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1088 // If there is a non-return use, the context must be allocated in a register.
1089 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
1090 if (!it.value()->IsReturn()) {
1091 return DefineAsRegister(new(zone()) LContext);
1092 }
1093 }
1094
1095 return NULL; 887 return NULL;
1096 } 888 }
1097 889
1098 890
1099 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1100 LOperand* context = UseRegisterAtStart(instr->value());
1101 return DefineAsRegister(new(zone()) LOuterContext(context));
1102 }
1103
1104
1105 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1106 return MarkAsCall(new(zone()) LDeclareGlobals, instr);
1107 }
1108
1109
1110 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1111 LOperand* context = UseRegisterAtStart(instr->value());
1112 return DefineAsRegister(new(zone()) LGlobalObject(context));
1113 }
1114
1115
1116 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1117 LOperand* global_object = UseRegisterAtStart(instr->value());
1118 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1119 }
1120
1121
1122 LInstruction* LChunkBuilder::DoCallConstantFunction(
1123 HCallConstantFunction* instr) {
1124 argument_count_ -= instr->argument_count();
1125 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, v0), instr);
1126 }
1127
1128
1129 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1130 LOperand* function = UseFixed(instr->function(), a1);
1131 argument_count_ -= instr->argument_count();
1132 LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1133 return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1134 }
1135
1136
1137 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1138 switch (instr->op()) {
1139 case kMathFloor: return DoMathFloor(instr);
1140 case kMathRound: return DoMathRound(instr);
1141 case kMathAbs: return DoMathAbs(instr);
1142 case kMathLog: return DoMathLog(instr);
1143 case kMathSin: return DoMathSin(instr);
1144 case kMathCos: return DoMathCos(instr);
1145 case kMathTan: return DoMathTan(instr);
1146 case kMathExp: return DoMathExp(instr);
1147 case kMathSqrt: return DoMathSqrt(instr);
1148 case kMathPowHalf: return DoMathPowHalf(instr);
1149 default:
1150 UNREACHABLE();
1151 return NULL;
1152 }
1153 }
1154
1155
1156 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) {
1157 LOperand* input = UseFixedDouble(instr->value(), f4);
1158 LMathLog* result = new(zone()) LMathLog(input);
1159 return MarkAsCall(DefineFixedDouble(result, f4), instr);
1160 }
1161
1162
1163 LInstruction* LChunkBuilder::DoMathSin(HUnaryMathOperation* instr) {
1164 LOperand* input = UseFixedDouble(instr->value(), f4);
1165 LMathSin* result = new(zone()) LMathSin(input);
1166 return MarkAsCall(DefineFixedDouble(result, f4), instr);
1167 }
1168
1169
1170 LInstruction* LChunkBuilder::DoMathCos(HUnaryMathOperation* instr) {
1171 LOperand* input = UseFixedDouble(instr->value(), f4);
1172 LMathCos* result = new(zone()) LMathCos(input);
1173 return MarkAsCall(DefineFixedDouble(result, f4), instr);
1174 }
1175
1176
1177 LInstruction* LChunkBuilder::DoMathTan(HUnaryMathOperation* instr) {
1178 LOperand* input = UseFixedDouble(instr->value(), f4);
1179 LMathTan* result = new(zone()) LMathTan(input);
1180 return MarkAsCall(DefineFixedDouble(result, f4), instr);
1181 }
1182
1183
1184 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
1185 ASSERT(instr->representation().IsDouble());
1186 ASSERT(instr->value()->representation().IsDouble());
1187 LOperand* input = UseTempRegister(instr->value());
1188 LOperand* temp1 = TempRegister();
1189 LOperand* temp2 = TempRegister();
1190 LOperand* double_temp = FixedTemp(f6); // Chosen by fair dice roll.
1191 LMathExp* result = new(zone()) LMathExp(input, double_temp, temp1, temp2);
1192 return DefineAsRegister(result);
1193 }
1194
1195
1196 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) {
1197 // Input cannot be the same as the result, see LCodeGen::DoMathPowHalf.
1198 LOperand* input = UseFixedDouble(instr->value(), f8);
1199 LOperand* temp = FixedTemp(f6);
1200 LMathPowHalf* result = new(zone()) LMathPowHalf(input, temp);
1201 return DefineFixedDouble(result, f4);
1202 }
1203
1204
1205 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) {
1206 LOperand* input = UseRegister(instr->value());
1207 LMathAbs* result = new(zone()) LMathAbs(input);
1208 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1209 }
1210
1211
1212 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) {
1213 LOperand* input = UseRegister(instr->value());
1214 LOperand* temp = TempRegister();
1215 LMathFloor* result = new(zone()) LMathFloor(input, temp);
1216 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1217 }
1218
1219
1220 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) {
1221 LOperand* input = UseRegister(instr->value());
1222 LMathSqrt* result = new(zone()) LMathSqrt(input);
1223 return DefineAsRegister(result);
1224 }
1225
1226
1227 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
1228 LOperand* input = UseRegister(instr->value());
1229 LOperand* temp = FixedTemp(f6);
1230 LMathRound* result = new(zone()) LMathRound(input, temp);
1231 return AssignEnvironment(DefineAsRegister(result));
1232 }
1233
1234
1235 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1236 ASSERT(instr->key()->representation().IsTagged());
1237 argument_count_ -= instr->argument_count();
1238 LOperand* key = UseFixed(instr->key(), a2);
1239 return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), v0), instr);
1240 }
1241
1242
1243 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1244 argument_count_ -= instr->argument_count();
1245 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, v0), instr);
1246 }
1247
1248
1249 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1250 argument_count_ -= instr->argument_count();
1251 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, v0), instr);
1252 }
1253
1254
1255 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1256 argument_count_ -= instr->argument_count();
1257 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr);
1258 }
1259
1260
1261 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1262 LOperand* constructor = UseFixed(instr->constructor(), a1);
1263 argument_count_ -= instr->argument_count();
1264 LCallNew* result = new(zone()) LCallNew(constructor);
1265 return MarkAsCall(DefineFixed(result, v0), instr);
1266 }
1267
1268
1269 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1270 LOperand* constructor = UseFixed(instr->constructor(), a1);
1271 argument_count_ -= instr->argument_count();
1272 LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1273 return MarkAsCall(DefineFixed(result, v0), instr);
1274 }
1275
1276
1277 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1278 LOperand* function = UseFixed(instr->function(), a1);
1279 argument_count_ -= instr->argument_count();
1280 return MarkAsCall(DefineFixed(new(zone()) LCallFunction(function), v0),
1281 instr);
1282 }
1283
1284
1285 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1286 argument_count_ -= instr->argument_count();
1287 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, v0), instr);
1288 }
1289
1290
1291 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1292 return DoShift(Token::ROR, instr);
1293 }
1294
1295
1296 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1297 return DoShift(Token::SHR, instr);
1298 }
1299
1300
1301 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1302 return DoShift(Token::SAR, instr);
1303 }
1304
1305
1306 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1307 return DoShift(Token::SHL, instr);
1308 }
1309
1310
1311 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { 891 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
892 // TODO(all): The latest bleeding_edge handles smi representations too.
1312 if (instr->representation().IsInteger32()) { 893 if (instr->representation().IsInteger32()) {
1313 ASSERT(instr->left()->representation().IsInteger32()); 894 ASSERT(instr->left()->representation().IsInteger32());
1314 ASSERT(instr->right()->representation().IsInteger32()); 895 ASSERT(instr->right()->representation().IsInteger32());
1315 896
1316 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 897 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1317 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 898 LOperand* right =
899 UseRegisterOrConstantAtStart(instr->BetterRightOperand());
1318 return DefineAsRegister(new(zone()) LBitI(left, right)); 900 return DefineAsRegister(new(zone()) LBitI(left, right));
1319 } else { 901 } else {
1320 ASSERT(instr->representation().IsSmiOrTagged()); 902 return DoArithmeticT(instr->op(), instr);
1321 ASSERT(instr->left()->representation().IsSmiOrTagged());
1322 ASSERT(instr->right()->representation().IsSmiOrTagged());
1323
1324 LOperand* left = UseFixed(instr->left(), a1);
1325 LOperand* right = UseFixed(instr->right(), a0);
1326 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1327 return MarkAsCall(DefineFixed(result, v0), instr);
1328 } 903 }
1329 } 904 }
1330 905
1331 906
1332 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { 907 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1333 ASSERT(instr->value()->representation().IsInteger32()); 908 ASSERT(instr->value()->representation().IsInteger32());
1334 ASSERT(instr->representation().IsInteger32()); 909 ASSERT(instr->representation().IsInteger32());
1335 if (instr->HasNoUses()) return NULL; 910 if (instr->HasNoUses()) return NULL;
1336 LOperand* value = UseRegisterAtStart(instr->value()); 911 LOperand* value = UseRegisterAtStart(instr->value());
1337 return DefineAsRegister(new(zone()) LBitNotI(value)); 912 return DefineAsRegister(new(zone()) LBitNotI(value));
1338 } 913 }
1339 914
1340 915
1341 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 916 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
1342 if (instr->representation().IsDouble()) { 917 // V8 expects a label to be generated for each basic block.
1343 return DoArithmeticD(Token::DIV, instr); 918 // This is used in some places like LAllocator::IsBlockBoundary
1344 } else if (instr->representation().IsInteger32()) { 919 // in lithium-allocator.cc
1345 // TODO(1042) The fixed register allocation 920 return new(zone()) LLabel(instr->block());
1346 // is needed because we call TypeRecordingBinaryOpStub from
1347 // the generated code, which requires registers a0
1348 // and a1 to be used. We should remove that
1349 // when we provide a native implementation.
1350 LOperand* dividend = UseFixed(instr->left(), a0);
1351 LOperand* divisor = UseFixed(instr->right(), a1);
1352 return AssignEnvironment(AssignPointerMap(
1353 DefineFixed(new(zone()) LDivI(dividend, divisor), v0)));
1354 } else {
1355 return DoArithmeticT(Token::DIV, instr);
1356 }
1357 }
1358
1359
1360 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1361 UNIMPLEMENTED();
1362 return NULL;
1363 }
1364
1365
1366 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1367 HValue* left = instr->left();
1368 HValue* right = instr->right();
1369 if (instr->representation().IsInteger32()) {
1370 ASSERT(left->representation().IsInteger32());
1371 ASSERT(right->representation().IsInteger32());
1372 if (instr->HasPowerOf2Divisor()) {
1373 ASSERT(!right->CanBeZero());
1374 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1375 UseOrConstant(right));
1376 LInstruction* result = DefineAsRegister(mod);
1377 return (left->CanBeNegative() &&
1378 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1379 ? AssignEnvironment(result)
1380 : result;
1381 } else {
1382 LModI* mod = new(zone()) LModI(UseRegister(left),
1383 UseRegister(right),
1384 TempRegister(),
1385 FixedTemp(f20),
1386 FixedTemp(f22));
1387 LInstruction* result = DefineAsRegister(mod);
1388 return (right->CanBeZero() ||
1389 (left->RangeCanInclude(kMinInt) &&
1390 right->RangeCanInclude(-1)) ||
1391 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1392 ? AssignEnvironment(result)
1393 : result;
1394 }
1395 } else if (instr->representation().IsSmiOrTagged()) {
1396 return DoArithmeticT(Token::MOD, instr);
1397 } else {
1398 ASSERT(instr->representation().IsDouble());
1399 // We call a C function for double modulo. It can't trigger a GC. We need
1400 // to use fixed result register for the call.
1401 // TODO(fschneider): Allow any register as input registers.
1402 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1403 UseFixedDouble(left, f2),
1404 UseFixedDouble(right, f4));
1405 return MarkAsCall(DefineFixedDouble(mod, f2), instr);
1406 }
1407 }
1408
1409
1410 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1411 if (instr->representation().IsInteger32()) {
1412 ASSERT(instr->left()->representation().IsInteger32());
1413 ASSERT(instr->right()->representation().IsInteger32());
1414 LOperand* left;
1415 LOperand* right = UseOrConstant(instr->BetterRightOperand());
1416 LOperand* temp = NULL;
1417 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1418 (instr->CheckFlag(HValue::kCanOverflow) ||
1419 !right->IsConstantOperand())) {
1420 left = UseRegister(instr->BetterLeftOperand());
1421 temp = TempRegister();
1422 } else {
1423 left = UseRegisterAtStart(instr->BetterLeftOperand());
1424 }
1425 LMulI* mul = new(zone()) LMulI(left, right, temp);
1426 if (instr->CheckFlag(HValue::kCanOverflow) ||
1427 instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
1428 AssignEnvironment(mul);
1429 }
1430 return DefineAsRegister(mul);
1431
1432 } else if (instr->representation().IsDouble()) {
1433 if (kArchVariant == kMips32r2) {
1434 if (instr->UseCount() == 1 && instr->uses().value()->IsAdd()) {
1435 HAdd* add = HAdd::cast(instr->uses().value());
1436 if (instr == add->left()) {
1437 // This mul is the lhs of an add. The add and mul will be folded
1438 // into a multiply-add.
1439 return NULL;
1440 }
1441 if (instr == add->right() && !add->left()->IsMul()) {
1442 // This mul is the rhs of an add, where the lhs is not another mul.
1443 // The add and mul will be folded into a multiply-add.
1444 return NULL;
1445 }
1446 }
1447 }
1448 return DoArithmeticD(Token::MUL, instr);
1449 } else {
1450 return DoArithmeticT(Token::MUL, instr);
1451 }
1452 }
1453
1454
1455 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1456 if (instr->representation().IsInteger32()) {
1457 ASSERT(instr->left()->representation().IsInteger32());
1458 ASSERT(instr->right()->representation().IsInteger32());
1459 LOperand* left = UseRegisterAtStart(instr->left());
1460 LOperand* right = UseOrConstantAtStart(instr->right());
1461 LSubI* sub = new(zone()) LSubI(left, right);
1462 LInstruction* result = DefineAsRegister(sub);
1463 if (instr->CheckFlag(HValue::kCanOverflow)) {
1464 result = AssignEnvironment(result);
1465 }
1466 return result;
1467 } else if (instr->representation().IsDouble()) {
1468 return DoArithmeticD(Token::SUB, instr);
1469 } else {
1470 return DoArithmeticT(Token::SUB, instr);
1471 }
1472 }
1473
1474
1475 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
1476 LOperand* multiplier_op = UseRegisterAtStart(mul->left());
1477 LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
1478 LOperand* addend_op = UseRegisterAtStart(addend);
1479 return DefineSameAsFirst(new(zone()) LMultiplyAddD(addend_op, multiplier_op,
1480 multiplicand_op));
1481 }
1482
1483
1484 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
1485 if (instr->representation().IsInteger32()) {
1486 ASSERT(instr->left()->representation().IsInteger32());
1487 ASSERT(instr->right()->representation().IsInteger32());
1488 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1489 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1490 LAddI* add = new(zone()) LAddI(left, right);
1491 LInstruction* result = DefineAsRegister(add);
1492 if (instr->CheckFlag(HValue::kCanOverflow)) {
1493 result = AssignEnvironment(result);
1494 }
1495 return result;
1496 } else if (instr->representation().IsDouble()) {
1497 if (kArchVariant == kMips32r2) {
1498 if (instr->left()->IsMul())
1499 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
1500
1501 if (instr->right()->IsMul()) {
1502 ASSERT(!instr->left()->IsMul());
1503 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
1504 }
1505 }
1506 return DoArithmeticD(Token::ADD, instr);
1507 } else {
1508 ASSERT(instr->representation().IsSmiOrTagged());
1509 return DoArithmeticT(Token::ADD, instr);
1510 }
1511 }
1512
1513
1514 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1515 LOperand* left = NULL;
1516 LOperand* right = NULL;
1517 if (instr->representation().IsInteger32()) {
1518 ASSERT(instr->left()->representation().IsInteger32());
1519 ASSERT(instr->right()->representation().IsInteger32());
1520 left = UseRegisterAtStart(instr->BetterLeftOperand());
1521 right = UseOrConstantAtStart(instr->BetterRightOperand());
1522 } else {
1523 ASSERT(instr->representation().IsDouble());
1524 ASSERT(instr->left()->representation().IsDouble());
1525 ASSERT(instr->right()->representation().IsDouble());
1526 left = UseRegisterAtStart(instr->left());
1527 right = UseRegisterAtStart(instr->right());
1528 }
1529 return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1530 }
1531
1532
1533 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1534 ASSERT(instr->representation().IsDouble());
1535 // We call a C function for double power. It can't trigger a GC.
1536 // We need to use fixed result register for the call.
1537 Representation exponent_type = instr->right()->representation();
1538 ASSERT(instr->left()->representation().IsDouble());
1539 LOperand* left = UseFixedDouble(instr->left(), f2);
1540 LOperand* right = exponent_type.IsDouble() ?
1541 UseFixedDouble(instr->right(), f4) :
1542 UseFixed(instr->right(), a2);
1543 LPower* result = new(zone()) LPower(left, right);
1544 return MarkAsCall(DefineFixedDouble(result, f0),
1545 instr,
1546 CAN_DEOPTIMIZE_EAGERLY);
1547 }
1548
1549
1550 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1551 ASSERT(instr->representation().IsDouble());
1552 ASSERT(instr->global_object()->representation().IsTagged());
1553 LOperand* global_object = UseFixed(instr->global_object(), a0);
1554 LRandom* result = new(zone()) LRandom(global_object);
1555 return MarkAsCall(DefineFixedDouble(result, f0), instr);
1556 }
1557
1558
1559 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1560 ASSERT(instr->left()->representation().IsTagged());
1561 ASSERT(instr->right()->representation().IsTagged());
1562 LOperand* left = UseFixed(instr->left(), a1);
1563 LOperand* right = UseFixed(instr->right(), a0);
1564 LCmpT* result = new(zone()) LCmpT(left, right);
1565 return MarkAsCall(DefineFixed(result, v0), instr);
1566 }
1567
1568
1569 LInstruction* LChunkBuilder::DoCompareIDAndBranch(
1570 HCompareIDAndBranch* instr) {
1571 Representation r = instr->representation();
1572 if (r.IsSmiOrInteger32()) {
1573 ASSERT(instr->left()->representation().IsSmiOrInteger32());
1574 ASSERT(instr->left()->representation().Equals(
1575 instr->right()->representation()));
1576 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1577 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1578 return new(zone()) LCmpIDAndBranch(left, right);
1579 } else {
1580 ASSERT(r.IsDouble());
1581 ASSERT(instr->left()->representation().IsDouble());
1582 ASSERT(instr->right()->representation().IsDouble());
1583 LOperand* left = UseRegisterAtStart(instr->left());
1584 LOperand* right = UseRegisterAtStart(instr->right());
1585 return new(zone()) LCmpIDAndBranch(left, right);
1586 }
1587 }
1588
1589
1590 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1591 HCompareObjectEqAndBranch* instr) {
1592 LOperand* left = UseRegisterAtStart(instr->left());
1593 LOperand* right = UseRegisterAtStart(instr->right());
1594 return new(zone()) LCmpObjectEqAndBranch(left, right);
1595 }
1596
1597
1598 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1599 HCompareConstantEqAndBranch* instr) {
1600 return new(zone()) LCmpConstantEqAndBranch(
1601 UseRegisterAtStart(instr->value()));
1602 }
1603
1604
1605 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1606 ASSERT(instr->value()->representation().IsTagged());
1607 LOperand* temp = TempRegister();
1608 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value()),
1609 temp);
1610 }
1611
1612
1613 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1614 ASSERT(instr->value()->representation().IsTagged());
1615 LOperand* temp = TempRegister();
1616 return new(zone()) LIsStringAndBranch(UseRegisterAtStart(instr->value()),
1617 temp);
1618 }
1619
1620
1621 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1622 ASSERT(instr->value()->representation().IsTagged());
1623 return new(zone()) LIsSmiAndBranch(Use(instr->value()));
1624 }
1625
1626
1627 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1628 HIsUndetectableAndBranch* instr) {
1629 ASSERT(instr->value()->representation().IsTagged());
1630 return new(zone()) LIsUndetectableAndBranch(
1631 UseRegisterAtStart(instr->value()), TempRegister());
1632 }
1633
1634
1635 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
1636 HStringCompareAndBranch* instr) {
1637 ASSERT(instr->left()->representation().IsTagged());
1638 ASSERT(instr->right()->representation().IsTagged());
1639 LOperand* left = UseFixed(instr->left(), a1);
1640 LOperand* right = UseFixed(instr->right(), a0);
1641 LStringCompareAndBranch* result =
1642 new(zone()) LStringCompareAndBranch(left, right);
1643 return MarkAsCall(result, instr);
1644 }
1645
1646
1647 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1648 HHasInstanceTypeAndBranch* instr) {
1649 ASSERT(instr->value()->representation().IsTagged());
1650 LOperand* value = UseRegisterAtStart(instr->value());
1651 return new(zone()) LHasInstanceTypeAndBranch(value);
1652 }
1653
1654
1655 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1656 HGetCachedArrayIndex* instr) {
1657 ASSERT(instr->value()->representation().IsTagged());
1658 LOperand* value = UseRegisterAtStart(instr->value());
1659
1660 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
1661 }
1662
1663
1664 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1665 HHasCachedArrayIndexAndBranch* instr) {
1666 ASSERT(instr->value()->representation().IsTagged());
1667 return new(zone()) LHasCachedArrayIndexAndBranch(
1668 UseRegisterAtStart(instr->value()));
1669 }
1670
1671
1672 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1673 HClassOfTestAndBranch* instr) {
1674 ASSERT(instr->value()->representation().IsTagged());
1675 return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
1676 TempRegister());
1677 }
1678
1679
1680 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1681 HFixedArrayBaseLength* instr) {
1682 LOperand* array = UseRegisterAtStart(instr->value());
1683 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
1684 }
1685
1686
1687 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
1688 LOperand* map = UseRegisterAtStart(instr->value());
1689 return DefineAsRegister(new(zone()) LMapEnumLength(map));
1690 }
1691
1692
1693 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1694 LOperand* object = UseRegisterAtStart(instr->value());
1695 return DefineAsRegister(new(zone()) LElementsKind(object));
1696 }
1697
1698
1699 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1700 LOperand* object = UseRegister(instr->value());
1701 LValueOf* result = new(zone()) LValueOf(object, TempRegister());
1702 return DefineAsRegister(result);
1703 }
1704
1705
1706 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1707 LOperand* object = UseFixed(instr->value(), a0);
1708 LDateField* result =
1709 new(zone()) LDateField(object, FixedTemp(a1), instr->index());
1710 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
1711 }
1712
1713
1714 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1715 LOperand* string = UseRegister(instr->string());
1716 LOperand* index = UseRegister(instr->index());
1717 LOperand* value = UseTempRegister(instr->value());
1718 LSeqStringSetChar* result =
1719 new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
1720 return DefineAsRegister(result);
1721 }
1722
1723
1724 LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
1725 return NULL;
1726 }
1727
1728
1729 LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
1730 HInductionVariableAnnotation* instr) {
1731 return NULL;
1732 } 921 }
1733 922
1734 923
1735 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { 924 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1736 LOperand* value = UseRegisterOrConstantAtStart(instr->index()); 925 LOperand* value = UseRegisterOrConstantAtStart(instr->index());
1737 LOperand* length = UseRegister(instr->length()); 926 LOperand* length = UseRegister(instr->length());
1738 return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); 927 return AssignEnvironment(new(zone()) LBoundsCheck(value, length));
1739 } 928 }
1740 929
1741 930
1742 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation( 931 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
1743 HBoundsCheckBaseIndexInformation* instr) { 932 HValue* value = instr->value();
1744 UNREACHABLE(); 933
1745 return NULL; 934 if (value->EmitAtUses()) {
1746 } 935 // TODO(all): Handle this case with CheckElideControlInstruction once
1747 936 // we've done the rebase.
1748 937 HBasicBlock* successor = HConstant::cast(value)->BooleanValue()
1749 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { 938 ? instr->FirstSuccessor()
1750 // The control instruction marking the end of a block that completed 939 : instr->SecondSuccessor();
1751 // abruptly (e.g., threw an exception). There is nothing specific to do. 940 return new(zone()) LGoto(successor->block_id());
1752 return NULL; 941 }
1753 } 942
1754 943 Representation rep = value->representation();
1755 944 HType type = value->type();
1756 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { 945
1757 LOperand* value = UseFixed(instr->value(), a0); 946 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) {
1758 return MarkAsCall(new(zone()) LThrow(value), instr); 947 ToBooleanStub::Types expected = instr->expected_input_types();
1759 } 948 LOperand* temp1 = NULL;
1760 949 LOperand* temp2 = NULL;
1761 950
1762 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { 951 if (expected.NeedsMap() || expected.IsEmpty()) {
1763 return NULL; 952 temp1 = TempRegister();
1764 } 953 temp2 = TempRegister();
1765 954 }
1766 955
1767 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { 956 // Tagged values that are not known smis or booleans require a
1768 // All HForceRepresentation instructions should be eliminated in the 957 // deoptimization environment.
1769 // representation change phase of Hydrogen. 958 return AssignEnvironment(
1770 UNREACHABLE(); 959 new(zone()) LBranch(UseRegister(value), temp1, temp2));
1771 return NULL; 960 } else {
961 return new(zone()) LBranch(UseRegister(value), NULL, NULL);
962 }
963 }
964
965
966 LInstruction* LChunkBuilder::DoCallConstantFunction(
967 HCallConstantFunction* instr) {
968 argument_count_ -= instr->argument_count();
969 return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, x0), instr);
970 }
971
972
973 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
974 LOperand* function = UseFixed(instr->function(), x1);
975 argument_count_ -= instr->argument_count();
976 LInstruction* result = DefineFixed(new(zone()) LCallFunction(function), x0);
977 // TODO(all): Uncomment the following line during the rebase.
978 // if (instr->IsTailCall()) return result;
979 return MarkAsCall(result, instr);
980 }
981
982
983 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
984 argument_count_ -= instr->argument_count();
985 return MarkAsCall(DefineFixed(new(zone()) LCallGlobal, x0), instr);
986 }
987
988
989 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
990 ASSERT(instr->key()->representation().IsTagged());
991 argument_count_ -= instr->argument_count();
992 LOperand* key = UseFixed(instr->key(), x2);
993 return MarkAsCall(DefineFixed(new(zone()) LCallKeyed(key), x0), instr);
994 }
995
996
997 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
998 argument_count_ -= instr->argument_count();
999 return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, x0), instr);
1000 }
1001
1002
1003 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1004 argument_count_ -= instr->argument_count();
1005 return MarkAsCall(DefineFixed(new(zone()) LCallNamed, x0), instr);
1006 }
1007
1008
1009 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1010 // The call to CallConstructStub will expect the constructor to be in x1.
1011 LOperand* constructor = UseFixed(instr->constructor(), x1);
1012 argument_count_ -= instr->argument_count();
1013 LCallNew* result = new(zone()) LCallNew(constructor);
1014 return MarkAsCall(DefineFixed(result, x0), instr);
1015 }
1016
1017
1018 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
1019 // The call to ArrayConstructCode will expect the constructor to be in x1.
1020 LOperand* constructor = UseFixed(instr->constructor(), x1);
1021 argument_count_ -= instr->argument_count();
1022 LCallNewArray* result = new(zone()) LCallNewArray(constructor);
1023 return MarkAsCall(DefineFixed(result, x0), instr);
1024 }
1025
1026
1027 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1028 argument_count_ -= instr->argument_count();
1029 return MarkAsCall(DefineFixed(new(zone()) LCallRuntime, x0), instr);
1030 }
1031
1032
1033 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1034 argument_count_ -= instr->argument_count();
1035 return MarkAsCall(DefineFixed(new(zone()) LCallStub, x0), instr);
1772 } 1036 }
1773 1037
1774 1038
1775 LInstruction* LChunkBuilder::DoChange(HChange* instr) { 1039 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1776 Representation from = instr->from(); 1040 Representation from = instr->from();
1777 Representation to = instr->to(); 1041 Representation to = instr->to();
1042
1778 if (from.IsSmi()) { 1043 if (from.IsSmi()) {
1779 if (to.IsTagged()) { 1044 if (to.IsTagged()) {
1780 LOperand* value = UseRegister(instr->value()); 1045 LOperand* value = UseRegister(instr->value());
1781 return DefineSameAsFirst(new(zone()) LDummyUse(value)); 1046 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1782 } 1047 }
1783 from = Representation::Tagged(); 1048 from = Representation::Tagged();
1784 } 1049 }
1050
1785 if (from.IsTagged()) { 1051 if (from.IsTagged()) {
1786 if (to.IsDouble()) { 1052 if (to.IsDouble()) {
1787 info()->MarkAsDeferredCalling(); 1053 info()->MarkAsDeferredCalling();
1788 LOperand* value = UseRegister(instr->value()); 1054 LOperand* value = UseRegister(instr->value());
1789 LNumberUntagD* res = new(zone()) LNumberUntagD(value); 1055 LOperand* temp = TempRegister();
1056 LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
1790 return AssignEnvironment(DefineAsRegister(res)); 1057 return AssignEnvironment(DefineAsRegister(res));
1791 } else if (to.IsSmi()) { 1058 } else if (to.IsSmi()) {
1792 HValue* val = instr->value(); 1059 LOperand* value = UseRegister(instr->value());
1793 LOperand* value = UseRegister(val); 1060 if (instr->value()->type().IsSmi()) {
1794 if (val->type().IsSmi()) {
1795 return DefineSameAsFirst(new(zone()) LDummyUse(value)); 1061 return DefineSameAsFirst(new(zone()) LDummyUse(value));
1796 } 1062 }
1797 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); 1063 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
1798 } else { 1064 } else {
1799 ASSERT(to.IsInteger32()); 1065 ASSERT(to.IsInteger32());
1800 LOperand* value = NULL;
1801 LInstruction* res = NULL; 1066 LInstruction* res = NULL;
1067
1802 if (instr->value()->type().IsSmi()) { 1068 if (instr->value()->type().IsSmi()) {
1803 value = UseRegisterAtStart(instr->value()); 1069 LOperand* value = UseRegisterAtStart(instr->value());
1804 res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); 1070 res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
1805 } else { 1071 } else {
1806 value = UseRegister(instr->value()); 1072 LOperand* value = UseRegister(instr->value());
1807 LOperand* temp1 = TempRegister(); 1073 LOperand* temp1 = TempRegister();
1808 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() 1074 LOperand* temp2 =
1809 : NULL; 1075 instr->CanTruncateToInt32() ? TempRegister() : FixedTemp(d24);
1810 LOperand* temp3 = FixedTemp(f22); 1076 res = DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2));
1811 res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
1812 temp1,
1813 temp2,
1814 temp3));
1815 res = AssignEnvironment(res); 1077 res = AssignEnvironment(res);
1816 } 1078 }
1079
1817 return res; 1080 return res;
1818 } 1081 }
1819 } else if (from.IsDouble()) { 1082 } else if (from.IsDouble()) {
1820 if (to.IsTagged()) { 1083 if (to.IsTagged()) {
1821 info()->MarkAsDeferredCalling(); 1084 info()->MarkAsDeferredCalling();
1822 LOperand* value = UseRegister(instr->value()); 1085 LOperand* value = UseRegister(instr->value());
1823 LOperand* temp1 = TempRegister(); 1086 LOperand* temp1 = TempRegister();
1824 LOperand* temp2 = TempRegister(); 1087 LOperand* temp2 = TempRegister();
1825 1088
1826 // Make sure that the temp and result_temp registers are
1827 // different.
1828 LUnallocated* result_temp = TempRegister();
1829 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); 1089 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
1830 Define(result, result_temp); 1090 return AssignPointerMap(DefineAsRegister(result));
1831 return AssignPointerMap(result);
1832 } else if (to.IsSmi()) { 1091 } else if (to.IsSmi()) {
1092 // TODO(all): Split LDoubleToSmi into two instructions.
1833 LOperand* value = UseRegister(instr->value()); 1093 LOperand* value = UseRegister(instr->value());
1834 return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value, 1094 LOperand* temp1 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1835 TempRegister(), TempRegister()))); 1095 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1096 LDoubleToSmi* result = new(zone()) LDoubleToSmi(value, temp1, temp2);
1097 return AssignEnvironment(DefineAsRegister(result));
1836 } else { 1098 } else {
1099 // TODO(all): Split LDoubleToI into two instructions, truncating and not.
1837 ASSERT(to.IsInteger32()); 1100 ASSERT(to.IsInteger32());
1838 LOperand* value = UseRegister(instr->value()); 1101 LOperand* value = UseRegister(instr->value());
1839 LOperand* temp1 = TempRegister(); 1102 LOperand* temp1 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1840 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL; 1103 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
1841 LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2); 1104 LDoubleToI* result = new(zone()) LDoubleToI(value, temp1, temp2);
1842 return AssignEnvironment(DefineAsRegister(res)); 1105 return AssignEnvironment(DefineAsRegister(result));
1843 } 1106 }
1844 } else if (from.IsInteger32()) { 1107 } else if (from.IsInteger32()) {
1845 info()->MarkAsDeferredCalling(); 1108 info()->MarkAsDeferredCalling();
1846 if (to.IsTagged()) { 1109 if (to.IsTagged()) {
1847 HValue* val = instr->value(); 1110 HValue* val = instr->value();
1848 LOperand* value = UseRegisterAtStart(val); 1111 LOperand* value = UseRegisterAtStart(val);
1112
1849 if (val->CheckFlag(HInstruction::kUint32)) { 1113 if (val->CheckFlag(HInstruction::kUint32)) {
1850 LNumberTagU* result = new(zone()) LNumberTagU(value); 1114 LNumberTagU* result = new(zone()) LNumberTagU(value,
1851 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); 1115 TempRegister(),
1852 } else if (val->HasRange() && val->range()->IsInSmiRange()) { 1116 TempRegister());
1117 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1118 } else {
1119 STATIC_ASSERT((kMinInt == Smi::kMinValue) &&
1120 (kMaxInt == Smi::kMaxValue));
1853 return DefineAsRegister(new(zone()) LSmiTag(value)); 1121 return DefineAsRegister(new(zone()) LSmiTag(value));
1854 } else {
1855 LNumberTagI* result = new(zone()) LNumberTagI(value);
1856 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1857 } 1122 }
1858 } else if (to.IsSmi()) { 1123 } else if (to.IsSmi()) {
1859 HValue* val = instr->value(); 1124 LOperand* value = UseRegisterAtStart(instr->value());
1860 LOperand* value = UseRegister(val); 1125 // This cannot deoptimize because an A64 smi can represent any int32.
1861 LInstruction* result = 1126 return DefineAsRegister(new(zone()) LInteger32ToSmi(value));
1862 DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
1863 if (val->HasRange() && val->range()->IsInSmiRange()) {
1864 return result;
1865 }
1866 return AssignEnvironment(result);
1867 } else { 1127 } else {
1868 ASSERT(to.IsDouble()); 1128 ASSERT(to.IsDouble());
1869 if (instr->value()->CheckFlag(HInstruction::kUint32)) { 1129 if (instr->value()->CheckFlag(HInstruction::kUint32)) {
1870 return DefineAsRegister( 1130 return DefineAsRegister(
1871 new(zone()) LUint32ToDouble(UseRegister(instr->value()))); 1131 new(zone()) LUint32ToDouble(UseRegisterAtStart(instr->value())));
1872 } else { 1132 } else {
1873 return DefineAsRegister( 1133 return DefineAsRegister(
1874 new(zone()) LInteger32ToDouble(Use(instr->value()))); 1134 new(zone()) LInteger32ToDouble(UseRegisterAtStart(instr->value())));
1875 } 1135 }
1876 } 1136 }
1877 } 1137 }
1138
1878 UNREACHABLE(); 1139 UNREACHABLE();
1879 return NULL; 1140 return NULL;
1880 } 1141 }
1881 1142
1882 1143
1144 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1145 // We only need a temp register if the target is in new space, but we can't
1146 // dereference the handle to test that here.
1147 LOperand* value = UseRegister(instr->value());
1148 LOperand* temp = TempRegister();
1149 return AssignEnvironment(new(zone()) LCheckFunction(value, temp));
1150 }
1151
1152
1153 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1154 LOperand* value = UseRegisterAtStart(instr->value());
1155 LOperand* temp = TempRegister();
1156 LInstruction* result = new(zone()) LCheckInstanceType(value, temp);
1157 return AssignEnvironment(result);
1158 }
1159
1160
1161 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1162 LOperand* value = UseRegister(instr->value());
1163 LOperand* temp = TempRegister();
1164 LInstruction* result = new(zone()) LCheckMaps(value, temp);
1165 return AssignEnvironment(result);
1166 }
1167
1168
1883 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { 1169 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1170 // TODO(all): On newer v8 versions, this hydrogen instruction has been renamed
1171 // into HCheckHeapObject but still translate into LCheckNonSmi.
1884 LOperand* value = UseRegisterAtStart(instr->value()); 1172 LOperand* value = UseRegisterAtStart(instr->value());
1885 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); 1173 return AssignEnvironment(new(zone()) LCheckNonSmi(value));
1886 } 1174 }
1887 1175
1888 1176
1889 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1890 LOperand* value = UseRegisterAtStart(instr->value());
1891 LInstruction* result = new(zone()) LCheckInstanceType(value);
1892 return AssignEnvironment(result);
1893 }
1894
1895
1896 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { 1177 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1897 LUnallocated* temp1 = TempRegister(); 1178 // TODO(jbramley): The scratch registers are not needed if
1179 // instr->CanOmitPrototypeChecks(). Can we safely test that here?
1180 LOperand* temp1 = TempRegister();
1898 LOperand* temp2 = TempRegister(); 1181 LOperand* temp2 = TempRegister();
1899 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); 1182 return AssignEnvironment(new(zone()) LCheckPrototypeMaps(temp1, temp2));
1900 return AssignEnvironment(result);
1901 }
1902
1903
1904 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1905 LOperand* value = UseRegisterAtStart(instr->value());
1906 return AssignEnvironment(new(zone()) LCheckFunction(value));
1907 }
1908
1909
1910 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
1911 LOperand* value = UseRegisterAtStart(instr->value());
1912 LInstruction* result = new(zone()) LCheckMaps(value);
1913 return AssignEnvironment(result);
1914 } 1183 }
1915 1184
1916 1185
1917 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { 1186 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
1918 HValue* value = instr->value(); 1187 HValue* value = instr->value();
1919 Representation input_rep = value->representation(); 1188 Representation input_rep = value->representation();
1920 LOperand* reg = UseRegister(value); 1189 LOperand* reg = UseRegister(value);
1921 if (input_rep.IsDouble()) { 1190 if (input_rep.IsDouble()) {
1922 // Revisit this decision, here and 8 lines below. 1191 return DefineAsRegister(new(zone()) LClampDToUint8(reg));
1923 return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(f22)));
1924 } else if (input_rep.IsInteger32()) { 1192 } else if (input_rep.IsInteger32()) {
1925 return DefineAsRegister(new(zone()) LClampIToUint8(reg)); 1193 return DefineAsRegister(new(zone()) LClampIToUint8(reg));
1926 } else { 1194 } else {
1927 ASSERT(input_rep.IsSmiOrTagged()); 1195 ASSERT(input_rep.IsSmiOrTagged());
1928 // Register allocator doesn't (yet) support allocation of double 1196 return AssignEnvironment(
1929 // temps. Reserve f22 explicitly. 1197 DefineAsRegister(new(zone()) LClampTToUint8(reg,
1930 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22)); 1198 TempRegister(),
1931 return AssignEnvironment(DefineAsRegister(result)); 1199 FixedTemp(d24))));
1932 } 1200 }
1933 } 1201 }
1934 1202
1935 1203
1936 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { 1204 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
1937 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); 1205 HClassOfTestAndBranch* instr) {
1938 return new(zone()) LReturn(UseFixed(instr->value(), v0), 1206 ASSERT(instr->value()->representation().IsTagged());
1939 parameter_count); 1207 LOperand* value = UseRegisterAtStart(instr->value());
1208 return new(zone()) LClassOfTestAndBranch(value,
1209 TempRegister(),
1210 TempRegister());
1211 }
1212
1213
1214 LInstruction* LChunkBuilder::DoCompareIDAndBranch(HCompareIDAndBranch* instr) {
1215 Representation r = instr->representation();
1216
1217 // TODO(all): This instruction has been replaced by HCompareNumericAndBranch
1218 // on bleeding_edge. We should update when we'll do the rebase.
1219 if (r.IsSmiOrInteger32()) {
1220 ASSERT(instr->left()->representation().Equals(r));
1221 ASSERT(instr->right()->representation().Equals(r));
1222 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1223 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1224 return new(zone()) LCmpIDAndBranch(left, right);
1225 } else {
1226 ASSERT(r.IsDouble());
1227 ASSERT(instr->left()->representation().IsDouble());
1228 ASSERT(instr->right()->representation().IsDouble());
1229 // TODO(all): In fact the only case that we can handle more efficiently is
1230 // when one of the operand is the constant 0. Currently the MacroAssembler
1231 // will be able to cope with any constant by loading it into an internal
1232 // scratch register. This means that if the constant is used more that once,
1233 // it will be loaded multiple times. Unfortunatly crankshaft already
1234 // duplicates constant loads, but we should modify the code below once this
1235 // issue has been addressed in crankshaft.
1236 LOperand* left = UseRegisterOrConstantAtStart(instr->left());
1237 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
1238 return new(zone()) LCmpIDAndBranch(left, right);
1239 }
1240 }
1241
1242
1243 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
1244 ASSERT(instr->left()->representation().IsTagged());
1245 ASSERT(instr->right()->representation().IsTagged());
1246 LOperand* left = UseFixed(instr->left(), x1);
1247 LOperand* right = UseFixed(instr->right(), x0);
1248 LCmpT* result = new(zone()) LCmpT(left, right);
1249 return MarkAsCall(DefineFixed(result, x0), instr);
1250 }
1251
1252
1253 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
1254 HCompareObjectEqAndBranch* instr) {
1255 LOperand* left = UseRegisterAtStart(instr->left());
1256 LOperand* right = UseRegisterAtStart(instr->right());
1257 return new(zone()) LCmpObjectEqAndBranch(left, right);
1258 }
1259
1260
1261 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1262 ASSERT(instr->value()->representation().IsTagged());
1263 LOperand* value = UseRegisterAtStart(instr->value());
1264 LOperand* temp = TempRegister();
1265 return new(zone()) LCmpMapAndBranch(value, temp);
1266 }
1267
1268
1269 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch(
1270 HCompareConstantEqAndBranch* instr) {
1271 UNIMPLEMENTED_INSTRUCTION();
1940 } 1272 }
1941 1273
1942 1274
1943 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { 1275 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1944 Representation r = instr->representation(); 1276 Representation r = instr->representation();
1945 if (r.IsSmi()) { 1277 if (r.IsSmi()) {
1946 return DefineAsRegister(new(zone()) LConstantS); 1278 return DefineAsRegister(new(zone()) LConstantS);
1947 } else if (r.IsInteger32()) { 1279 } else if (r.IsInteger32()) {
1948 return DefineAsRegister(new(zone()) LConstantI); 1280 return DefineAsRegister(new(zone()) LConstantI);
1949 } else if (r.IsDouble()) { 1281 } else if (r.IsDouble()) {
1950 return DefineAsRegister(new(zone()) LConstantD); 1282 return DefineAsRegister(new(zone()) LConstantD);
1951 } else if (r.IsTagged()) { 1283 } else if (r.IsTagged()) {
1952 return DefineAsRegister(new(zone()) LConstantT); 1284 return DefineAsRegister(new(zone()) LConstantT);
1953 } else { 1285 } else {
1954 UNREACHABLE(); 1286 UNREACHABLE();
1955 return NULL; 1287 return NULL;
1956 } 1288 }
1957 } 1289 }
1958 1290
1959 1291
1960 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) { 1292 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1961 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell; 1293 // If there is a non-return use, the context must be allocated in a register.
1962 return instr->RequiresHoleCheck() 1294 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
1963 ? AssignEnvironment(DefineAsRegister(result)) 1295 if (!it.value()->IsReturn()) {
1964 : DefineAsRegister(result); 1296 return DefineAsRegister(new(zone()) LContext);
1965 } 1297 }
1966 1298 }
1967 1299
1968 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { 1300 return NULL;
1969 LOperand* global_object = UseFixed(instr->global_object(), a0); 1301 }
1970 LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object); 1302
1971 return MarkAsCall(DefineFixed(result, v0), instr); 1303
1972 } 1304 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
1973 1305 LOperand* object = UseFixed(instr->value(), x0);
1974 1306 LDateField* result = new(zone()) LDateField(object, instr->index());
1975 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) { 1307 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
1976 LOperand* value = UseRegister(instr->value()); 1308 }
1977 // Use a temp to check the value in the cell in the case where we perform 1309
1978 // a hole check. 1310
1979 return instr->RequiresHoleCheck() 1311 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
1980 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) 1312 return new(zone()) LDebugBreak();
1981 : new(zone()) LStoreGlobalCell(value, NULL); 1313 }
1982 } 1314
1983 1315
1984 1316 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
1985 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) { 1317 UNIMPLEMENTED_INSTRUCTION();
1986 LOperand* global_object = UseFixed(instr->global_object(), a1); 1318 }
1987 LOperand* value = UseFixed(instr->value(), a0); 1319
1988 LStoreGlobalGeneric* result = 1320
1989 new(zone()) LStoreGlobalGeneric(global_object, value); 1321 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
1990 return MarkAsCall(result, instr); 1322 UNIMPLEMENTED_INSTRUCTION();
1323 }
1324
1325
1326 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
1327 return AssignEnvironment(new(zone()) LDeoptimize);
1328 }
1329
1330
1331 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1332 if (instr->representation().IsInteger32()) {
1333 // TODO(all): Update this case to support smi inputs.
1334 ASSERT(instr->left()->representation().Equals(instr->representation()));
1335 ASSERT(instr->right()->representation().Equals(instr->representation()));
1336 if (instr->HasPowerOf2Divisor()) {
1337 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1338 LOperand* value = UseRegisterAtStart(instr->left());
1339 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
1340 return AssignEnvironment(DefineAsRegister(div));
1341 }
1342 LOperand* dividend = UseRegister(instr->left());
1343 LOperand* divisor = UseRegister(instr->right());
1344 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
1345 ? NULL : TempRegister();
1346 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1347 return AssignEnvironment(DefineAsRegister(div));
1348 } else if (instr->representation().IsDouble()) {
1349 return DoArithmeticD(Token::DIV, instr);
1350 } else {
1351 return DoArithmeticT(Token::DIV, instr);
1352 }
1353 }
1354
1355
1356 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
1357 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
1358 }
1359
1360
1361 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
1362 LOperand* object = UseRegisterAtStart(instr->value());
1363 return DefineAsRegister(new(zone()) LElementsKind(object));
1364 }
1365
1366
1367 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
1368 HEnvironment* outer = current_block_->last_environment();
1369 HConstant* undefined = graph()->GetConstantUndefined();
1370 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
1371 instr->arguments_count(),
1372 instr->function(),
1373 undefined,
1374 instr->inlining_kind(),
1375 instr->undefined_receiver());
1376 if (instr->arguments_var() != NULL) {
1377 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
1378 }
1379 inner->set_entry(instr);
1380 current_block_->UpdateEnvironment(inner);
1381 chunk_->AddInlinedClosure(instr->closure());
1382 return NULL;
1383 }
1384
1385
1386 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
1387 UNREACHABLE();
1388 return NULL;
1389 }
1390
1391
1392 LInstruction* LChunkBuilder::DoFixedArrayBaseLength(
1393 HFixedArrayBaseLength* instr) {
1394 LOperand* array = UseRegisterAtStart(instr->value());
1395 return DefineAsRegister(new(zone()) LFixedArrayBaseLength(array));
1396 }
1397
1398
1399 LInstruction* LChunkBuilder::DoForceRepresentation(
1400 HForceRepresentation* instr) {
1401 UNIMPLEMENTED_INSTRUCTION();
1402 }
1403
1404
1405 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1406 return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, x0), instr);
1407 }
1408
1409
1410 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
1411 HGetCachedArrayIndex* instr) {
1412 UNIMPLEMENTED_INSTRUCTION();
1413 }
1414
1415
1416 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1417 LOperand* context = UseRegisterAtStart(instr->value());
1418 return DefineAsRegister(new(zone()) LGlobalObject(context));
1419 }
1420
1421
1422 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1423 LOperand* global_object = UseRegisterAtStart(instr->value());
1424 return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
1425 }
1426
1427
1428 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1429 return new(zone()) LGoto(instr->FirstSuccessor()->block_id());
1430 }
1431
1432
1433 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
1434 HHasCachedArrayIndexAndBranch* instr) {
1435 UNIMPLEMENTED_INSTRUCTION();
1436 }
1437
1438
1439 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
1440 HHasInstanceTypeAndBranch* instr) {
1441 ASSERT(instr->value()->representation().IsTagged());
1442 LOperand* value = UseRegisterAtStart(instr->value());
1443 return new(zone()) LHasInstanceTypeAndBranch(value, TempRegister());
1444 }
1445
1446
1447 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
1448 LOperand* key = UseRegisterAtStart(instr->key());
1449 LOperand* object = UseRegisterAtStart(instr->object());
1450 LIn* result = new(zone()) LIn(key, object);
1451 return MarkAsCall(DefineFixed(result, x0), instr);
1452 }
1453
1454
1455 LInstruction* LChunkBuilder::DoInductionVariableAnnotation(
1456 HInductionVariableAnnotation* instr) {
1457 return NULL;
1458 }
1459
1460
1461 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
1462 HInnerAllocatedObject* inner_object) {
1463 LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
1464 return DefineAsRegister(new(zone()) LInnerAllocatedObject(base_object));
1465 }
1466
1467
1468 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1469 LInstanceOf* result = new(zone()) LInstanceOf(
1470 UseFixed(instr->left(), InstanceofStub::left()),
1471 UseFixed(instr->right(), InstanceofStub::right()));
1472 return MarkAsCall(DefineFixed(result, x0), instr);
1473 }
1474
1475
1476 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1477 HInstanceOfKnownGlobal* instr) {
1478 LInstanceOfKnownGlobal* result = new(zone()) LInstanceOfKnownGlobal(
1479 UseFixed(instr->left(), InstanceofStub::left()));
1480 return MarkAsCall(DefineFixed(result, x0), instr);
1481 }
1482
1483
1484 LInstruction* LChunkBuilder::DoInstanceSize(HInstanceSize* instr) {
1485 LOperand* object = UseRegisterAtStart(instr->object());
1486 return DefineAsRegister(new(zone()) LInstanceSize(object));
1487 }
1488
1489
1490 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
1491 // The function is required (by MacroAssembler::InvokeFunction) to be in x1.
1492 LOperand* function = UseFixed(instr->function(), x1);
1493 argument_count_ -= instr->argument_count();
1494 LInvokeFunction* result = new(zone()) LInvokeFunction(function);
1495 return MarkAsCall(DefineFixed(result, x0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
1496 }
1497
1498
1499 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
1500 HIsConstructCallAndBranch* instr) {
1501 return new(zone()) LIsConstructCallAndBranch(TempRegister(), TempRegister());
1502 }
1503
1504
1505 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
1506 ASSERT(instr->value()->representation().IsTagged());
1507 LOperand* value = UseRegisterAtStart(instr->value());
1508 LOperand* temp1 = TempRegister();
1509 LOperand* temp2 = TempRegister();
1510 return new(zone()) LIsObjectAndBranch(value, temp1, temp2);
1511 }
1512
1513
1514 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
1515 ASSERT(instr->value()->representation().IsTagged());
1516 LOperand* value = UseRegisterAtStart(instr->value());
1517 LOperand* temp = TempRegister();
1518 return new(zone()) LIsStringAndBranch(value, temp);
1519 }
1520
1521
1522 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
1523 ASSERT(instr->value()->representation().IsTagged());
1524 return new(zone()) LIsSmiAndBranch(UseRegisterAtStart(instr->value()));
1525 }
1526
1527
1528 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
1529 HIsUndetectableAndBranch* instr) {
1530 ASSERT(instr->value()->representation().IsTagged());
1531 LOperand* value = UseRegisterAtStart(instr->value());
1532 return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
1533 }
1534
1535
1536 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
1537 LInstruction* pop = NULL;
1538 HEnvironment* env = current_block_->last_environment();
1539
1540 if (env->entry()->arguments_pushed()) {
1541 int argument_count = env->arguments_environment()->parameter_count();
1542 pop = new(zone()) LDrop(argument_count);
1543 argument_count_ -= argument_count;
1544 }
1545
1546 HEnvironment* outer =
1547 current_block_->last_environment()->DiscardInlined(false);
1548 current_block_->UpdateEnvironment(outer);
1549
1550 return pop;
1991 } 1551 }
1992 1552
1993 1553
1994 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { 1554 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1995 LOperand* context = UseRegisterAtStart(instr->value()); 1555 LOperand* context = UseRegisterAtStart(instr->value());
1996 LInstruction* result = 1556 LInstruction* result =
1997 DefineAsRegister(new(zone()) LLoadContextSlot(context)); 1557 DefineAsRegister(new(zone()) LLoadContextSlot(context));
1998 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; 1558 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1999 } 1559 }
2000 1560
2001 1561
2002 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { 1562 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
2003 LOperand* context; 1563 HLoadExternalArrayPointer* instr) {
2004 LOperand* value; 1564 LOperand* input = UseRegisterAtStart(instr->value());
2005 if (instr->NeedsWriteBarrier()) { 1565 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
2006 context = UseTempRegister(instr->context()); 1566 }
2007 value = UseTempRegister(instr->value()); 1567
2008 } else { 1568
2009 context = UseRegister(instr->context()); 1569 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
2010 value = UseRegister(instr->value()); 1570 HLoadFunctionPrototype* instr) {
2011 } 1571 LOperand* function = UseRegister(instr->function());
2012 LInstruction* result = new(zone()) LStoreContextSlot(context, value); 1572 LOperand* temp = TempRegister();
2013 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; 1573 return AssignEnvironment(DefineAsRegister(
1574 new(zone()) LLoadFunctionPrototype(function, temp)));
1575 }
1576
1577
1578 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
1579 LLoadGlobalCell* result = new(zone()) LLoadGlobalCell();
1580 return instr->RequiresHoleCheck()
1581 ? AssignEnvironment(DefineAsRegister(result))
1582 : DefineAsRegister(result);
1583 }
1584
1585
1586 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
1587 LOperand* global_object = UseFixed(instr->global_object(), x0);
1588 LLoadGlobalGeneric* result = new(zone()) LLoadGlobalGeneric(global_object);
1589 return MarkAsCall(DefineFixed(result, x0), instr);
1590 }
1591
1592
1593 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
1594 ASSERT(instr->key()->representation().IsInteger32() ||
1595 instr->key()->representation().IsSmi());
1596 ElementsKind elements_kind = instr->elements_kind();
1597 LOperand* elements = UseRegister(instr->elements());
1598 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
1599
1600 if (!instr->is_external()) {
1601 if (instr->representation().IsDouble()) {
1602 LOperand* temp = (!instr->key()->IsConstant() ||
1603 instr->RequiresHoleCheck())
1604 ? TempRegister()
1605 : NULL;
1606
1607 LLoadKeyedFixedDouble* result =
1608 new(zone()) LLoadKeyedFixedDouble(elements, key, temp);
1609 return instr->RequiresHoleCheck()
1610 ? AssignEnvironment(DefineAsRegister(result))
1611 : DefineAsRegister(result);
1612 } else {
1613 ASSERT(instr->representation().IsSmiOrTagged());
1614 LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
1615 LLoadKeyedFixed* result =
1616 new(zone()) LLoadKeyedFixed(elements, key, temp);
1617 return instr->RequiresHoleCheck()
1618 ? AssignEnvironment(DefineAsRegister(result))
1619 : DefineAsRegister(result);
1620 }
1621 } else {
1622 ASSERT((instr->representation().IsInteger32() &&
1623 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
1624 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
1625 (instr->representation().IsDouble() &&
1626 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
1627 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
1628
1629 LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
1630 LLoadKeyedExternal* result =
1631 new(zone()) LLoadKeyedExternal(elements, key, temp);
1632 // An unsigned int array load might overflow and cause a deopt. Make sure it
1633 // has an environment.
1634 return (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS)
1635 ? AssignEnvironment(DefineAsRegister(result))
1636 : DefineAsRegister(result);
1637 }
1638 }
1639
1640
1641 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1642 LOperand* object = UseFixed(instr->object(), x1);
1643 LOperand* key = UseFixed(instr->key(), x0);
1644
1645 LInstruction* result =
1646 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), x0);
1647 return MarkAsCall(result, instr);
2014 } 1648 }
2015 1649
2016 1650
2017 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { 1651 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
2018 LOperand* obj = UseRegisterAtStart(instr->object()); 1652 LOperand* object = UseRegisterAtStart(instr->object());
2019 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); 1653 return DefineAsRegister(new(zone()) LLoadNamedField(object));
2020 } 1654 }
2021 1655
2022 1656
2023 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic( 1657 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
2024 HLoadNamedFieldPolymorphic* instr) { 1658 HLoadNamedFieldPolymorphic* instr) {
2025 ASSERT(instr->representation().IsTagged()); 1659 ASSERT(instr->representation().IsTagged());
2026 if (instr->need_generic()) { 1660 if (instr->need_generic()) {
2027 LOperand* obj = UseFixed(instr->object(), a0); 1661 LOperand* obj = UseFixed(instr->object(), x0);
2028 LLoadNamedFieldPolymorphic* result = 1662 LLoadNamedFieldPolymorphic* result =
2029 new(zone()) LLoadNamedFieldPolymorphic(obj); 1663 new(zone()) LLoadNamedFieldPolymorphic(obj);
2030 return MarkAsCall(DefineFixed(result, v0), instr); 1664 return MarkAsCall(DefineFixed(result, x0), instr);
2031 } else { 1665 } else {
2032 LOperand* obj = UseRegisterAtStart(instr->object()); 1666 LOperand* obj = UseRegister(instr->object());
2033 LLoadNamedFieldPolymorphic* result = 1667 LLoadNamedFieldPolymorphic* result =
2034 new(zone()) LLoadNamedFieldPolymorphic(obj); 1668 new(zone()) LLoadNamedFieldPolymorphic(obj);
2035 return AssignEnvironment(DefineAsRegister(result)); 1669 return AssignEnvironment(DefineAsRegister(result));
2036 } 1670 }
2037 } 1671 }
2038 1672
2039 1673
2040 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { 1674 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
2041 LOperand* object = UseFixed(instr->object(), a0); 1675 LOperand* object = UseFixed(instr->object(), x0);
2042 LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), v0); 1676 LInstruction* result = DefineFixed(new(zone()) LLoadNamedGeneric(object), x0);
2043 return MarkAsCall(result, instr); 1677 return MarkAsCall(result, instr);
2044 } 1678 }
2045 1679
2046 1680
2047 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( 1681 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
2048 HLoadFunctionPrototype* instr) { 1682 LOperand* map = UseRegisterAtStart(instr->value());
2049 return AssignEnvironment(DefineAsRegister( 1683 return DefineAsRegister(new(zone()) LMapEnumLength(map));
2050 new(zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); 1684 }
2051 } 1685
2052 1686
2053 1687 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
2054 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( 1688 UNIMPLEMENTED_INSTRUCTION();
2055 HLoadExternalArrayPointer* instr) { 1689 }
2056 LOperand* input = UseRegisterAtStart(instr->value()); 1690
2057 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); 1691
2058 } 1692 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
2059 1693 LOperand* left = NULL;
2060 1694 LOperand* right = NULL;
2061 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { 1695 if (instr->representation().IsInteger32()) {
2062 ASSERT(instr->key()->representation().IsInteger32() || 1696 ASSERT(instr->left()->representation().IsInteger32());
2063 instr->key()->representation().IsSmi()); 1697 ASSERT(instr->right()->representation().IsInteger32());
2064 ElementsKind elements_kind = instr->elements_kind(); 1698 left = UseRegisterAtStart(instr->BetterLeftOperand());
2065 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); 1699 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand());
2066 LLoadKeyed* result = NULL; 1700 } else {
2067 1701 ASSERT(instr->representation().IsDouble());
2068 if (!instr->is_external()) { 1702 ASSERT(instr->left()->representation().IsDouble());
2069 LOperand* obj = NULL; 1703 ASSERT(instr->right()->representation().IsDouble());
2070 if (instr->representation().IsDouble()) { 1704 left = UseRegisterAtStart(instr->left());
2071 obj = UseTempRegister(instr->elements()); 1705 right = UseRegisterAtStart(instr->right());
1706 }
1707 return DefineAsRegister(new(zone()) LMathMinMax(left, right));
1708 }
1709
1710
1711 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1712 if (instr->representation().IsInteger32()) {
1713 ASSERT(instr->left()->representation().IsInteger32());
1714 ASSERT(instr->right()->representation().IsInteger32());
1715
1716 UNIMPLEMENTED_INSTRUCTION();
1717 } else if (instr->representation().IsSmiOrTagged()) {
1718 UNIMPLEMENTED_INSTRUCTION();
1719 } else {
1720 return DoArithmeticD(Token::MOD, instr);
1721 }
1722 }
1723
1724
1725 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1726 if (instr->representation().IsInteger32()) {
1727 ASSERT(instr->left()->representation().IsInteger32());
1728 ASSERT(instr->right()->representation().IsInteger32());
1729
1730 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
1731 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
1732 bool needs_environment = can_overflow || bailout_on_minus_zero;
1733
1734 HValue* least_const = instr->BetterLeftOperand();
1735 HValue* most_const = instr->BetterRightOperand();
1736
1737 LOperand* left = UseRegisterAtStart(least_const);
1738
1739 // LMulConstI can handle a subset of constants:
1740 // With support for overflow detection:
1741 // -1, 0, 1, 2
1742 // Without support for overflow detection:
1743 // 2^n, -(2^n)
1744 // 2^n + 1, -(2^n - 1)
1745 if (most_const->IsConstant()) {
1746 int32_t constant = HConstant::cast(most_const)->Integer32Value();
1747 int32_t constant_abs = (constant >= 0) ? constant : -constant;
1748
1749 if (((constant >= -1) && (constant <= 2)) ||
1750 (!can_overflow && (IsPowerOf2(constant_abs) ||
1751 IsPowerOf2(constant_abs + 1) ||
1752 IsPowerOf2(constant_abs - 1)))) {
1753 LConstantOperand* right = UseConstant(most_const);
1754 LMulConstI* mul = new(zone()) LMulConstI(left, right);
1755 if (needs_environment) AssignEnvironment(mul);
1756 return DefineAsRegister(mul);
1757 }
1758 }
1759
1760 // LMulI can handle all cases, but it requires that a register is allocated
1761 // for the second operand.
1762 LOperand* right = UseRegisterAtStart(most_const);
1763 LMulI* mul = new(zone()) LMulI(left, right);
1764 if (needs_environment) AssignEnvironment(mul);
1765 return DefineAsRegister(mul);
1766 } else if (instr->representation().IsDouble()) {
1767 return DoArithmeticD(Token::MUL, instr);
1768 } else {
1769 return DoArithmeticT(Token::MUL, instr);
1770 }
1771 }
1772
1773
1774 LInstruction* LChunkBuilder::DoNumericConstraint(HNumericConstraint* instr) {
1775 return NULL;
1776 }
1777
1778
1779 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1780 UNIMPLEMENTED_INSTRUCTION();
1781 }
1782
1783
1784 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1785 LOperand* context = UseRegisterAtStart(instr->value());
1786 return DefineAsRegister(new(zone()) LOuterContext(context));
1787 }
1788
1789
1790 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
1791 LParameter* result = new(zone()) LParameter;
1792 if (instr->kind() == HParameter::STACK_PARAMETER) {
1793 int spill_index = chunk_->GetParameterStackSlot(instr->index());
1794 return DefineAsSpilled(result, spill_index);
1795 } else {
1796 ASSERT(info()->IsStub());
1797 CodeStubInterfaceDescriptor* descriptor =
1798 info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
1799 int index = static_cast<int>(instr->index());
1800 Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
1801 return DefineFixed(result, reg);
1802 }
1803 }
1804
1805
1806 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
1807 UNIMPLEMENTED_INSTRUCTION();
1808 }
1809
1810
1811 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1812 ++argument_count_;
1813 LOperand* argument = UseRegister(instr->argument());
1814 return new(zone()) LPushArgument(argument);
1815 }
1816
1817
1818 LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
1819 UNIMPLEMENTED_INSTRUCTION();
1820 }
1821
1822
1823 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1824 UNIMPLEMENTED_INSTRUCTION();
1825 }
1826
1827
1828 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1829 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
1830 return new(zone()) LReturn(UseFixed(instr->value(), x0), parameter_count);
1831 }
1832
1833
1834 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
1835 LOperand* string = UseRegister(instr->string());
1836 LOperand* index = UseRegister(instr->index());
1837 LOperand* value = UseRegister(instr->value());
1838 LOperand* temp = TempRegister();
1839 LSeqStringSetChar* result =
1840 new(zone()) LSeqStringSetChar(instr->encoding(),
1841 string, index, value, temp);
1842 return DefineAsRegister(result);
1843 }
1844
1845
1846 LInstruction* LChunkBuilder::DoShift(Token::Value op,
1847 HBitwiseBinaryOperation* instr) {
1848 if (instr->representation().IsSmiOrTagged()) {
1849 return DoArithmeticT(op, instr);
1850 }
1851
1852 ASSERT(instr->representation().IsInteger32());
1853 ASSERT(instr->left()->representation().IsInteger32());
1854 ASSERT(instr->right()->representation().IsInteger32());
1855 LOperand* left = UseRegisterAtStart(instr->left());
1856
1857 HValue* right_value = instr->right();
1858 LOperand* right = NULL;
1859 int constant_value = 0;
1860 if (right_value->IsConstant()) {
1861 right = UseConstant(right_value);
1862 HConstant* constant = HConstant::cast(right_value);
1863 constant_value = constant->Integer32Value() & 0x1f;
1864 } else {
1865 right = UseRegisterAtStart(right_value);
1866 }
1867
1868 // Shift operations can only deoptimize if we do a logical shift by 0 and the
1869 // result cannot be truncated to int32.
1870 bool does_deopt = false;
1871 if ((op == Token::SHR) && (constant_value == 0)) {
1872 if (FLAG_opt_safe_uint32_operations) {
1873 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
2072 } else { 1874 } else {
2073 ASSERT(instr->representation().IsSmiOrTagged()); 1875 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
2074 obj = UseRegisterAtStart(instr->elements()); 1876 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
1877 does_deopt = true;
1878 break;
1879 }
1880 }
2075 } 1881 }
2076 result = new(zone()) LLoadKeyed(obj, key); 1882 }
2077 } else {
2078 ASSERT(
2079 (instr->representation().IsInteger32() &&
2080 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2081 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2082 (instr->representation().IsDouble() &&
2083 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2084 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2085 LOperand* external_pointer = UseRegister(instr->elements());
2086 result = new(zone()) LLoadKeyed(external_pointer, key);
2087 }
2088
2089 DefineAsRegister(result);
2090 // An unsigned int array load might overflow and cause a deopt, make sure it
2091 // has an environment.
2092 bool can_deoptimize = instr->RequiresHoleCheck() ||
2093 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
2094 return can_deoptimize ? AssignEnvironment(result) : result;
2095 }
2096
2097
2098 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
2099 LOperand* object = UseFixed(instr->object(), a1);
2100 LOperand* key = UseFixed(instr->key(), a0);
2101 1883
2102 LInstruction* result = 1884 LInstruction* result =
2103 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0); 1885 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
1886 return does_deopt ? AssignEnvironment(result) : result;
1887 }
1888
1889
1890 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
1891 return DoShift(Token::ROR, instr);
1892 }
1893
1894
1895 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
1896 return DoShift(Token::SAR, instr);
1897 }
1898
1899
1900 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1901 return DoShift(Token::SHL, instr);
1902 }
1903
1904
1905 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
1906 return DoShift(Token::SHR, instr);
1907 }
1908
1909
1910 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
1911 HEnvironment* env = current_block_->last_environment();
1912 ASSERT(env != NULL);
1913
1914 env->set_ast_id(instr->ast_id());
1915
1916 env->Drop(instr->pop_count());
1917 for (int i = instr->values()->length() - 1; i >= 0; --i) {
1918 HValue* value = instr->values()->at(i);
1919 if (instr->HasAssignedIndexAt(i)) {
1920 env->Bind(instr->GetAssignedIndexAt(i), value);
1921 } else {
1922 env->Push(value);
1923 }
1924 }
1925
1926 // If there is an instruction pending deoptimization environment create a
1927 // lazy bailout instruction to capture the environment.
1928 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
1929 LInstruction* result = new(zone()) LLazyBailout;
1930 result = AssignEnvironment(result);
1931 // Store the lazy deopt environment with the instruction if needed. Right
1932 // now it is only used for LInstanceOfKnownGlobal.
1933 instruction_pending_deoptimization_environment_->
1934 SetDeferredLazyDeoptimizationEnvironment(result->environment());
1935 instruction_pending_deoptimization_environment_ = NULL;
1936 pending_deoptimization_ast_id_ = BailoutId::None();
1937 return result;
1938 }
1939
1940 return NULL;
1941 }
1942
1943
1944 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) {
1945 return AssignEnvironment(new(zone()) LDeoptimize);
1946 }
1947
1948
1949 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
1950 if (instr->is_function_entry()) {
1951 return MarkAsCall(new(zone()) LStackCheck, instr);
1952 } else {
1953 ASSERT(instr->is_backwards_branch());
1954 return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
1955 }
1956 }
1957
1958
1959 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1960 LOperand* temp = TempRegister();
1961 LOperand* context;
1962 LOperand* value;
1963 if (instr->NeedsWriteBarrier()) {
1964 // TODO(all): Replace these constraints when RecordWriteStub has been
1965 // rewritten. See GOOGJSE-586.
1966 context = UseRegisterAndClobber(instr->context());
1967 value = UseRegisterAndClobber(instr->value());
1968 } else {
1969 context = UseRegister(instr->context());
1970 value = UseRegister(instr->value());
1971 }
1972 LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
1973 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result;
1974 }
1975
1976
1977 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
1978 LOperand* value = UseRegister(instr->value());
1979 if (instr->RequiresHoleCheck()) {
1980 return AssignEnvironment(new(zone()) LStoreGlobalCell(value,
1981 TempRegister(),
1982 TempRegister()));
1983 } else {
1984 return new(zone()) LStoreGlobalCell(value, TempRegister(), NULL);
1985 }
1986 }
1987
1988
1989 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
1990 LOperand* global_object = UseFixed(instr->global_object(), x1);
1991 LOperand* value = UseFixed(instr->value(), x0);
1992 LStoreGlobalGeneric* result =
1993 new(zone()) LStoreGlobalGeneric(global_object, value);
2104 return MarkAsCall(result, instr); 1994 return MarkAsCall(result, instr);
2105 } 1995 }
2106 1996
2107 1997
2108 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { 1998 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
2109 ElementsKind elements_kind = instr->elements_kind(); 1999 LOperand* temp = NULL;
2110 2000 LOperand* elements = NULL;
2111 if (!instr->is_external()) { 2001 LOperand* val = NULL;
2002 LOperand* key = NULL;
2003
2004 if (!instr->is_external() && instr->value()->representation().IsTagged() &&
2005 instr->NeedsWriteBarrier()) {
2006 // RecordWrite() will clobber all registers.
2007 elements = UseRegisterAndClobber(instr->elements());
2008 val = UseRegisterAndClobber(instr->value());
2009 key = UseRegisterAndClobber(instr->key());
2010 } else {
2011 elements = UseRegister(instr->elements());
2012 val = UseRegister(instr->value());
2013 key = UseRegisterOrConstantAtStart(instr->key());
2014 }
2015
2016 if (instr->is_external()) {
2017 ASSERT(instr->elements()->representation().IsExternal());
2018 ASSERT((instr->value()->representation().IsInteger32() &&
2019 (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) &&
2020 (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) ||
2021 (instr->value()->representation().IsDouble() &&
2022 ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) ||
2023 (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS))));
2024 temp = instr->key()->IsConstant() ? NULL : TempRegister();
2025 return new(zone()) LStoreKeyedExternal(elements, key, val, temp);
2026 } else if (instr->value()->representation().IsDouble()) {
2112 ASSERT(instr->elements()->representation().IsTagged()); 2027 ASSERT(instr->elements()->representation().IsTagged());
2113 bool needs_write_barrier = instr->NeedsWriteBarrier(); 2028
2114 LOperand* object = NULL; 2029 // The constraint used here is UseRegister, even though the StoreKeyed
2115 LOperand* val = NULL; 2030 // instruction may canonicalize the value in the register if it is a NaN.
2116 LOperand* key = NULL; 2031 temp = TempRegister();
2117 2032 return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp);
2118 if (instr->value()->representation().IsDouble()) { 2033 } else {
2119 object = UseRegisterAtStart(instr->elements()); 2034 ASSERT(instr->elements()->representation().IsTagged());
2120 key = UseRegisterOrConstantAtStart(instr->key()); 2035 ASSERT(instr->value()->representation().IsSmiOrTagged());
2121 val = UseTempRegister(instr->value()); 2036
2122 } else { 2037 temp = TempRegister();
2123 ASSERT(instr->value()->representation().IsSmiOrTagged()); 2038 return new(zone()) LStoreKeyedFixed(elements, key, val, temp);
2124 object = UseTempRegister(instr->elements()); 2039 }
2125 val = needs_write_barrier ? UseTempRegister(instr->value())
2126 : UseRegisterAtStart(instr->value());
2127 key = needs_write_barrier ? UseTempRegister(instr->key())
2128 : UseRegisterOrConstantAtStart(instr->key());
2129 }
2130
2131 return new(zone()) LStoreKeyed(object, key, val);
2132 }
2133
2134 ASSERT(
2135 (instr->value()->representation().IsInteger32() &&
2136 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
2137 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
2138 (instr->value()->representation().IsDouble() &&
2139 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
2140 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
2141 ASSERT(instr->elements()->representation().IsExternal());
2142 bool val_is_temp_register =
2143 elements_kind == EXTERNAL_PIXEL_ELEMENTS ||
2144 elements_kind == EXTERNAL_FLOAT_ELEMENTS;
2145 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
2146 : UseRegister(instr->value());
2147 LOperand* key = UseRegisterOrConstantAtStart(instr->key());
2148 LOperand* external_pointer = UseRegister(instr->elements());
2149
2150 return new(zone()) LStoreKeyed(external_pointer, key, val);
2151 } 2040 }
2152 2041
2153 2042
2154 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { 2043 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
2155 LOperand* obj = UseFixed(instr->object(), a2); 2044 LOperand* object = UseFixed(instr->object(), x2);
2156 LOperand* key = UseFixed(instr->key(), a1); 2045 LOperand* key = UseFixed(instr->key(), x1);
2157 LOperand* val = UseFixed(instr->value(), a0); 2046 LOperand* value = UseFixed(instr->value(), x0);
2158 2047
2159 ASSERT(instr->object()->representation().IsTagged()); 2048 ASSERT(instr->object()->representation().IsTagged());
2160 ASSERT(instr->key()->representation().IsTagged()); 2049 ASSERT(instr->key()->representation().IsTagged());
2161 ASSERT(instr->value()->representation().IsTagged()); 2050 ASSERT(instr->value()->representation().IsTagged());
2162 2051
2163 return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); 2052 return MarkAsCall(new(zone()) LStoreKeyedGeneric(object, key, value), instr);
2164 } 2053 }
2165 2054
2166 2055
2167 LInstruction* LChunkBuilder::DoTransitionElementsKind( 2056 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2168 HTransitionElementsKind* instr) { 2057 // TODO(jbramley): Optimize register usage in this instruction. For now, it
2058 // allocates everything that it might need because it keeps changing in the
2059 // merge and keeping it valid is time-consuming.
2060
2061 // TODO(jbramley): It might be beneficial to allow value to be a constant in
2062 // some cases. x64 makes use of this with FLAG_track_fields, for example.
2063
2169 LOperand* object = UseRegister(instr->object()); 2064 LOperand* object = UseRegister(instr->object());
2170 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { 2065 LOperand* value = UseRegisterAndClobber(instr->value());
2171 LOperand* new_map_reg = TempRegister(); 2066 LOperand* temp0 = TempRegister();
2172 LTransitionElementsKind* result = 2067 LOperand* temp1 = TempRegister();
2173 new(zone()) LTransitionElementsKind(object, new_map_reg, NULL); 2068
2174 return result; 2069 LStoreNamedField* result =
2175 } else if (FLAG_compiled_transitions) { 2070 new(zone()) LStoreNamedField(object, value, temp0, temp1);
2176 LTransitionElementsKind* result =
2177 new(zone()) LTransitionElementsKind(object, NULL, NULL);
2178 return AssignPointerMap(result);
2179 } else {
2180 LOperand* object = UseFixed(instr->object(), a0);
2181 LOperand* fixed_object_reg = FixedTemp(a2);
2182 LOperand* new_map_reg = FixedTemp(a3);
2183 LTransitionElementsKind* result =
2184 new(zone()) LTransitionElementsKind(object,
2185 new_map_reg,
2186 fixed_object_reg);
2187 return MarkAsCall(result, instr);
2188 }
2189 }
2190
2191
2192 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2193 HTrapAllocationMemento* instr) {
2194 LOperand* object = UseRegister(instr->object());
2195 LOperand* temp = TempRegister();
2196 LTrapAllocationMemento* result =
2197 new(zone()) LTrapAllocationMemento(object, temp);
2198 return AssignEnvironment(result);
2199 }
2200
2201
2202 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
2203 bool is_in_object = instr->access().IsInobject();
2204 bool needs_write_barrier = instr->NeedsWriteBarrier();
2205 bool needs_write_barrier_for_map = !instr->transition().is_null() &&
2206 instr->NeedsWriteBarrierForMap();
2207
2208 LOperand* obj;
2209 if (needs_write_barrier) {
2210 obj = is_in_object
2211 ? UseRegister(instr->object())
2212 : UseTempRegister(instr->object());
2213 } else {
2214 obj = needs_write_barrier_for_map
2215 ? UseRegister(instr->object())
2216 : UseRegisterAtStart(instr->object());
2217 }
2218
2219 LOperand* val;
2220 if (needs_write_barrier ||
2221 (FLAG_track_fields && instr->field_representation().IsSmi())) {
2222 val = UseTempRegister(instr->value());
2223 } else if (FLAG_track_double_fields &&
2224 instr->field_representation().IsDouble()) {
2225 val = UseRegisterAtStart(instr->value());
2226 } else {
2227 val = UseRegister(instr->value());
2228 }
2229
2230 // We need a temporary register for write barrier of the map field.
2231 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
2232
2233 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp);
2234 if (FLAG_track_heap_object_fields && 2071 if (FLAG_track_heap_object_fields &&
2235 instr->field_representation().IsHeapObject()) { 2072 instr->field_representation().IsHeapObject() &&
2236 if (!instr->value()->type().IsHeapObject()) { 2073 !instr->value()->type().IsHeapObject()) {
2237 return AssignEnvironment(result); 2074 return AssignEnvironment(result);
2238 }
2239 } 2075 }
2240 return result; 2076 return result;
2241 } 2077 }
2242 2078
2243 2079
2244 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { 2080 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
2245 LOperand* obj = UseFixed(instr->object(), a1); 2081 LOperand* object = UseFixed(instr->object(), x1);
2246 LOperand* val = UseFixed(instr->value(), a0); 2082 LOperand* value = UseFixed(instr->value(), x0);
2247 2083 LInstruction* result = new(zone()) LStoreNamedGeneric(object, value);
2248 LInstruction* result = new(zone()) LStoreNamedGeneric(obj, val);
2249 return MarkAsCall(result, instr); 2084 return MarkAsCall(result, instr);
2250 } 2085 }
2251 2086
2252 2087
2253 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { 2088 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
2254 LOperand* left = UseRegisterAtStart(instr->left()); 2089 LOperand* left = UseRegisterAtStart(instr->left());
2255 LOperand* right = UseRegisterAtStart(instr->right()); 2090 LOperand* right = UseRegisterAtStart(instr->right());
2256 return MarkAsCall(DefineFixed(new(zone()) LStringAdd(left, right), v0), 2091
2257 instr); 2092 LStringAdd* result = new(zone()) LStringAdd(left, right);
2093 return MarkAsCall(DefineFixed(result, x0), instr);
2258 } 2094 }
2259 2095
2260 2096
2261 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { 2097 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
2262 LOperand* string = UseTempRegister(instr->string()); 2098 LOperand* string = UseRegisterAndClobber(instr->string());
2263 LOperand* index = UseTempRegister(instr->index()); 2099 LOperand* index = UseRegisterAndClobber(instr->index());
2264 LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index); 2100 LStringCharCodeAt* result = new(zone()) LStringCharCodeAt(string, index);
2265 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); 2101 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2266 } 2102 }
2267 2103
2268 2104
2269 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { 2105 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
2106 // TODO(all) use at start and remove assert in codegen
2270 LOperand* char_code = UseRegister(instr->value()); 2107 LOperand* char_code = UseRegister(instr->value());
2271 LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code); 2108 LStringCharFromCode* result = new(zone()) LStringCharFromCode(char_code);
2272 return AssignPointerMap(DefineAsRegister(result)); 2109 return AssignPointerMap(DefineAsRegister(result));
2273 } 2110 }
2274 2111
2275 2112
2113 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
2114 HStringCompareAndBranch* instr) {
2115 UNIMPLEMENTED_INSTRUCTION();
2116 }
2117
2118
2276 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { 2119 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
2120 // TODO(all): This instruction doesn't exist anymore on bleeding_edge.
2277 LOperand* string = UseRegisterAtStart(instr->value()); 2121 LOperand* string = UseRegisterAtStart(instr->value());
2278 return DefineAsRegister(new(zone()) LStringLength(string)); 2122 return DefineAsRegister(new(zone()) LStringLength(string));
2279 } 2123 }
2280 2124
2281 2125
2282 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { 2126 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
2283 info()->MarkAsDeferredCalling(); 2127 if (instr->representation().IsInteger32()) {
2284 LOperand* size = instr->size()->IsConstant() 2128 ASSERT(instr->left()->representation().IsInteger32());
2285 ? UseConstant(instr->size()) 2129 ASSERT(instr->right()->representation().IsInteger32());
2286 : UseTempRegister(instr->size()); 2130
2131 LOperand *left;
2132 if (instr->left()->IsConstant() &&
2133 (HConstant::cast(instr->left())->Integer32Value() == 0)) {
2134 left = UseConstant(instr->left());
2135 } else {
2136 left = UseRegisterAtStart(instr->left());
2137 }
2138 LOperand* right = UseRegisterOrConstantAtStart(instr->right());
2139 LSubI* sub = new(zone()) LSubI(left, right);
2140 LInstruction* result = DefineAsRegister(sub);
2141 if (instr->CheckFlag(HValue::kCanOverflow)) {
2142 result = AssignEnvironment(result);
2143 }
2144 return result;
2145 } else if (instr->representation().IsDouble()) {
2146 return DoArithmeticD(Token::SUB, instr);
2147 } else {
2148 return DoArithmeticT(Token::SUB, instr);
2149 }
2150 }
2151
2152
2153 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
2154 if (instr->HasNoUses()) {
2155 return NULL;
2156 } else {
2157 return DefineAsRegister(new(zone()) LThisFunction);
2158 }
2159 }
2160
2161
2162 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
2163 // TODO(all): This should not need to be a fixed register, as it's pushed to
2164 // the stack in DoThrow. However, we hit an assertion if it's assigned a non-
2165 // fixed register.
2166 LOperand* value = UseFixed(instr->value(), x0);
2167 return MarkAsCall(new(zone()) LThrow(value), instr);
2168 }
2169
2170
2171 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2172 LOperand* object = UseFixed(instr->value(), x0);
2173 LToFastProperties* result = new(zone()) LToFastProperties(object);
2174 return MarkAsCall(DefineFixed(result, x0), instr);
2175 }
2176
2177
2178 LInstruction* LChunkBuilder::DoTransitionElementsKind(
2179 HTransitionElementsKind* instr) {
2180 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
2181 LOperand* object = UseRegister(instr->object());
2182 LTransitionElementsKind* result =
2183 new(zone()) LTransitionElementsKind(object, TempRegister(),
2184 TempRegister());
2185 return result;
2186 } else if (FLAG_compiled_transitions) {
2187 LOperand* object = UseRegister(instr->object());
2188 LTransitionElementsKind* result =
2189 new(zone()) LTransitionElementsKind(object, NULL, NULL);
2190 return AssignPointerMap(result);
2191 } else {
2192 LOperand* object = UseFixed(instr->object(), x0);
2193 LTransitionElementsKind* result =
2194 new(zone()) LTransitionElementsKind(object, NULL, NULL);
2195 return MarkAsCall(result, instr);
2196 }
2197 }
2198
2199
2200 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
2201 HTrapAllocationMemento* instr) {
2202 LOperand* object = UseRegister(instr->object());
2287 LOperand* temp1 = TempRegister(); 2203 LOperand* temp1 = TempRegister();
2288 LOperand* temp2 = TempRegister(); 2204 LOperand* temp2 = TempRegister();
2289 LAllocate* result = new(zone()) LAllocate(size, temp1, temp2); 2205 LTrapAllocationMemento* result =
2290 return AssignPointerMap(DefineAsRegister(result)); 2206 new(zone()) LTrapAllocationMemento(object, temp1, temp2);
2291 } 2207 return AssignEnvironment(result);
2292 2208 }
2293 2209
2294 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { 2210
2295 return MarkAsCall(DefineFixed(new(zone()) LRegExpLiteral, v0), instr); 2211 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2296 } 2212 // TODO(jbramley): In ARM, this uses UseFixed to force the input to x0.
2297 2213 // However, LCodeGen::DoTypeof just pushes it to the stack (for CallRuntime)
2298 2214 // anyway, so the input doesn't have to be in x0. We might be able to improve
2299 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { 2215 // the ARM back-end a little by relaxing this restriction.
2300 return MarkAsCall(DefineFixed(new(zone()) LFunctionLiteral, v0), instr); 2216 LTypeof* result = new(zone()) LTypeof(UseRegisterAtStart(instr->value()));
2301 } 2217 return MarkAsCall(DefineFixed(result, x0), instr);
2302 2218 }
2303 2219
2304 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { 2220
2305 LOperand* object = UseFixed(instr->object(), a0); 2221 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2306 LOperand* key = UseFixed(instr->key(), a1); 2222 // We only need temp registers in some cases, but we can't dereference the
2307 LDeleteProperty* result = new(zone()) LDeleteProperty(object, key); 2223 // instr->type_literal() handle to test that here.
2308 return MarkAsCall(DefineFixed(result, v0), instr); 2224 LOperand* temp1 = TempRegister();
2309 } 2225 LOperand* temp2 = TempRegister();
2310 2226
2311 2227 return new(zone()) LTypeofIsAndBranch(
2312 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { 2228 UseRegister(instr->value()), temp1, temp2);
2313 ASSERT(argument_count_ == 0); 2229 }
2314 allocator_->MarkAsOsrEntry(); 2230
2315 current_block_->last_environment()->set_ast_id(instr->ast_id()); 2231
2316 return AssignEnvironment(new(zone()) LOsrEntry); 2232 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
2317 } 2233 switch (instr->op()) {
2318 2234 case kMathAbs: {
2319 2235 Representation r = instr->representation();
2320 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { 2236 if (r.IsTagged()) {
2321 LParameter* result = new(zone()) LParameter; 2237 // The tagged case might need to allocate a HeapNumber for the result,
2322 if (instr->kind() == HParameter::STACK_PARAMETER) { 2238 // so it is handled by a separate LInstruction.
2323 int spill_index = chunk()->GetParameterStackSlot(instr->index()); 2239 LOperand* input = UseRegister(instr->value());
2324 return DefineAsSpilled(result, spill_index); 2240 LOperand* temp1 = TempRegister();
2325 } else { 2241 LOperand* temp2 = TempRegister();
2326 ASSERT(info()->IsStub()); 2242 LOperand* temp3 = TempRegister();
2327 CodeStubInterfaceDescriptor* descriptor = 2243 LMathAbsTagged* result =
2328 info()->code_stub()->GetInterfaceDescriptor(info()->isolate()); 2244 new(zone()) LMathAbsTagged(input, temp1, temp2, temp3);
2329 int index = static_cast<int>(instr->index()); 2245 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2330 Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index); 2246 } else {
2331 return DefineFixed(result, reg); 2247 LOperand* input = UseRegisterAtStart(instr->value());
2248 LMathAbs* result = new(zone()) LMathAbs(input);
2249 if (r.IsDouble()) {
2250 // The Double case can never fail so it doesn't need an environment.
2251 return DefineAsRegister(result);
2252 } else {
2253 ASSERT(r.IsInteger32());
2254 // The Integer32 case needs an environment because it can deoptimize
2255 // on INT_MIN.
2256 return AssignEnvironment(DefineAsRegister(result));
2257 }
2258 }
2259 }
2260 case kMathCos: {
2261 ASSERT(instr->representation().IsDouble());
2262 ASSERT(instr->value()->representation().IsDouble());
2263 LOperand* input = UseFixedDouble(instr->value(), d0);
2264 LMathCos* result = new(zone()) LMathCos(input);
2265 return MarkAsCall(DefineFixedDouble(result, d0), instr);
2266 }
2267 case kMathExp: {
2268 ASSERT(instr->representation().IsDouble());
2269 ASSERT(instr->value()->representation().IsDouble());
2270 LOperand* input = UseRegister(instr->value());
2271 // TODO(all): Implement TempFPRegister.
2272 LOperand* double_temp1 = FixedTemp(d24); // This was chosen arbitrarily.
2273 LOperand* temp1 = TempRegister();
2274 LOperand* temp2 = TempRegister();
2275 LOperand* temp3 = TempRegister();
2276 LMathExp* result = new(zone()) LMathExp(input, double_temp1,
2277 temp1, temp2, temp3);
2278 return DefineAsRegister(result);
2279 }
2280 case kMathFloor: {
2281 ASSERT(instr->representation().IsInteger32());
2282 ASSERT(instr->value()->representation().IsDouble());
2283 // TODO(jbramley): A64 can easily handle a double argument with frintm,
2284 // but we're never asked for it here. At the moment, we fall back to the
2285 // runtime if the result doesn't fit, like the other architectures.
2286 LOperand* input = UseRegisterAtStart(instr->value());
2287 LMathFloor* result = new(zone()) LMathFloor(input);
2288 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
2289 }
2290 case kMathLog: {
2291 ASSERT(instr->representation().IsDouble());
2292 ASSERT(instr->value()->representation().IsDouble());
2293 LOperand* input = UseFixedDouble(instr->value(), d0);
2294 LMathLog* result = new(zone()) LMathLog(input);
2295 return MarkAsCall(DefineFixedDouble(result, d0), instr);
2296 }
2297 case kMathPowHalf: {
2298 ASSERT(instr->representation().IsDouble());
2299 ASSERT(instr->value()->representation().IsDouble());
2300 LOperand* input = UseRegister(instr->value());
2301 return DefineAsRegister(new(zone()) LMathPowHalf(input));
2302 }
2303 case kMathRound: {
2304 ASSERT(instr->representation().IsInteger32());
2305 ASSERT(instr->value()->representation().IsDouble());
2306 // TODO(jbramley): As with kMathFloor, we can probably handle double
2307 // results fairly easily, but we are never asked for them.
2308 LOperand* input = UseRegister(instr->value());
2309 LOperand* temp = FixedTemp(d24); // Choosen arbitrarily.
2310 LMathRound* result = new(zone()) LMathRound(input, temp);
2311 return AssignEnvironment(DefineAsRegister(result));
2312 }
2313 case kMathSin: {
2314 ASSERT(instr->representation().IsDouble());
2315 ASSERT(instr->value()->representation().IsDouble());
2316 LOperand* input = UseFixedDouble(instr->value(), d0);
2317 LMathSin* result = new(zone()) LMathSin(input);
2318 return MarkAsCall(DefineFixedDouble(result, d0), instr);
2319 }
2320 case kMathSqrt: {
2321 ASSERT(instr->representation().IsDouble());
2322 ASSERT(instr->value()->representation().IsDouble());
2323 LOperand* input = UseRegisterAtStart(instr->value());
2324 return DefineAsRegister(new(zone()) LMathSqrt(input));
2325 }
2326 case kMathTan: {
2327 ASSERT(instr->representation().IsDouble());
2328 ASSERT(instr->value()->representation().IsDouble());
2329 LOperand* input = UseFixedDouble(instr->value(), d0);
2330 LMathTan* result = new(zone()) LMathTan(input);
2331 return MarkAsCall(DefineFixedDouble(result, d0), instr);
2332 }
2333 default:
2334 UNREACHABLE();
2335 return NULL;
2332 } 2336 }
2333 } 2337 }
2334 2338
2335 2339
2336 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { 2340 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2337 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. 2341 UNIMPLEMENTED_INSTRUCTION();
2338 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { 2342 }
2339 Abort("Too many spill slots needed for OSR"); 2343
2340 spill_index = 0; 2344
2341 } 2345 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
2342 return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
2343 }
2344
2345
2346 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
2347 argument_count_ -= instr->argument_count();
2348 return MarkAsCall(DefineFixed(new(zone()) LCallStub, v0), instr);
2349 }
2350
2351
2352 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2353 // There are no real uses of the arguments object.
2354 // arguments.length and element access are supported directly on
2355 // stack arguments, and any real arguments object use causes a bailout.
2356 // So this value is never used.
2357 return NULL; 2346 return NULL;
2358 } 2347 }
2359 2348
2360 2349
2361 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { 2350 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
2362 info()->MarkAsRequiresFrame(); 2351 LOperand* object = UseRegister(instr->value());
2363 LOperand* args = UseRegister(instr->arguments()); 2352 LValueOf* result = new(zone()) LValueOf(object, TempRegister());
2364 LOperand* length; 2353 return DefineSameAsFirst(result);
2365 LOperand* index;
2366 if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
2367 length = UseRegisterOrConstant(instr->length());
2368 index = UseOrConstant(instr->index());
2369 } else {
2370 length = UseTempRegister(instr->length());
2371 index = UseRegisterAtStart(instr->index());
2372 }
2373 return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
2374 }
2375
2376
2377 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
2378 LOperand* object = UseFixed(instr->value(), a0);
2379 LToFastProperties* result = new(zone()) LToFastProperties(object);
2380 return MarkAsCall(DefineFixed(result, v0), instr);
2381 }
2382
2383
2384 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2385 LTypeof* result = new(zone()) LTypeof(UseFixed(instr->value(), a0));
2386 return MarkAsCall(DefineFixed(result, v0), instr);
2387 }
2388
2389
2390 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
2391 return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
2392 }
2393
2394
2395 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch(
2396 HIsConstructCallAndBranch* instr) {
2397 return new(zone()) LIsConstructCallAndBranch(TempRegister());
2398 }
2399
2400
2401 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2402 HEnvironment* env = current_block_->last_environment();
2403 ASSERT(env != NULL);
2404
2405 env->set_ast_id(instr->ast_id());
2406
2407 env->Drop(instr->pop_count());
2408 for (int i = instr->values()->length() - 1; i >= 0; --i) {
2409 HValue* value = instr->values()->at(i);
2410 if (instr->HasAssignedIndexAt(i)) {
2411 env->Bind(instr->GetAssignedIndexAt(i), value);
2412 } else {
2413 env->Push(value);
2414 }
2415 }
2416
2417 // If there is an instruction pending deoptimization environment create a
2418 // lazy bailout instruction to capture the environment.
2419 if (pending_deoptimization_ast_id_ == instr->ast_id()) {
2420 LInstruction* result = new(zone()) LLazyBailout;
2421 result = AssignEnvironment(result);
2422 // Store the lazy deopt environment with the instruction if needed. Right
2423 // now it is only used for LInstanceOfKnownGlobal.
2424 instruction_pending_deoptimization_environment_->
2425 SetDeferredLazyDeoptimizationEnvironment(result->environment());
2426 instruction_pending_deoptimization_environment_ = NULL;
2427 pending_deoptimization_ast_id_ = BailoutId::None();
2428 return result;
2429 }
2430
2431 return NULL;
2432 }
2433
2434
2435 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
2436 if (instr->is_function_entry()) {
2437 return MarkAsCall(new(zone()) LStackCheck, instr);
2438 } else {
2439 ASSERT(instr->is_backwards_branch());
2440 return AssignEnvironment(AssignPointerMap(new(zone()) LStackCheck));
2441 }
2442 }
2443
2444
2445 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
2446 HEnvironment* outer = current_block_->last_environment();
2447 HConstant* undefined = graph()->GetConstantUndefined();
2448 HEnvironment* inner = outer->CopyForInlining(instr->closure(),
2449 instr->arguments_count(),
2450 instr->function(),
2451 undefined,
2452 instr->inlining_kind(),
2453 instr->undefined_receiver());
2454 if (instr->arguments_var() != NULL) {
2455 inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
2456 }
2457 inner->set_entry(instr);
2458 current_block_->UpdateEnvironment(inner);
2459 chunk_->AddInlinedClosure(instr->closure());
2460 return NULL;
2461 }
2462
2463
2464 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2465 LInstruction* pop = NULL;
2466
2467 HEnvironment* env = current_block_->last_environment();
2468
2469 if (env->entry()->arguments_pushed()) {
2470 int argument_count = env->arguments_environment()->parameter_count();
2471 pop = new(zone()) LDrop(argument_count);
2472 argument_count_ -= argument_count;
2473 }
2474
2475 HEnvironment* outer = current_block_->last_environment()->
2476 DiscardInlined(false);
2477 current_block_->UpdateEnvironment(outer);
2478
2479 return pop;
2480 }
2481
2482
2483 LInstruction* LChunkBuilder::DoIn(HIn* instr) {
2484 LOperand* key = UseRegisterAtStart(instr->key());
2485 LOperand* object = UseRegisterAtStart(instr->object());
2486 LIn* result = new(zone()) LIn(key, object);
2487 return MarkAsCall(DefineFixed(result, v0), instr);
2488 } 2354 }
2489 2355
2490 2356
2491 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { 2357 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
2492 LOperand* object = UseFixed(instr->enumerable(), a0); 2358 // Assign object to a fixed register different from those already used in
2359 // LForInPrepareMap.
2360 LOperand* object = UseFixed(instr->enumerable(), x0);
2493 LForInPrepareMap* result = new(zone()) LForInPrepareMap(object); 2361 LForInPrepareMap* result = new(zone()) LForInPrepareMap(object);
2494 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY); 2362 return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
2495 } 2363 }
2496 2364
2497 2365
2498 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { 2366 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
2499 LOperand* map = UseRegister(instr->map()); 2367 LOperand* map = UseRegister(instr->map());
2500 return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map))); 2368 return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
2501 } 2369 }
2502 2370
2503 2371
2504 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { 2372 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
2505 LOperand* value = UseRegisterAtStart(instr->value()); 2373 LOperand* value = UseRegisterAtStart(instr->value());
2506 LOperand* map = UseRegisterAtStart(instr->map()); 2374 LOperand* map = UseRegister(instr->map());
2507 return AssignEnvironment(new(zone()) LCheckMapValue(value, map)); 2375 LOperand* temp = TempRegister();
2376 return AssignEnvironment(new(zone()) LCheckMapValue(value, map, temp));
2508 } 2377 }
2509 2378
2510 2379
2511 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2380 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2512 LOperand* object = UseRegister(instr->object()); 2381 LOperand* object = UseRegisterAtStart(instr->object());
2513 LOperand* index = UseRegister(instr->index()); 2382 LOperand* index = UseRegister(instr->index());
2514 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); 2383 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2515 } 2384 }
2516 2385
2517 2386
2387 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
2388 LOperand* receiver = UseRegister(instr->receiver());
2389 LOperand* function = UseRegisterAtStart(instr->function());
2390 LOperand* temp = TempRegister();
2391 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function, temp);
2392 return AssignEnvironment(DefineAsRegister(result));
2393 }
2394
2395
2518 } } // namespace v8::internal 2396 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/a64/lithium-a64.h ('k') | src/a64/lithium-codegen-a64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698