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