OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/ppc/lithium-ppc.h" | 5 #include "src/crankshaft/s390/lithium-s390.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/crankshaft/hydrogen-osr.h" | 9 #include "src/crankshaft/hydrogen-osr.h" |
10 #include "src/crankshaft/lithium-inl.h" | 10 #include "src/crankshaft/lithium-inl.h" |
11 #include "src/crankshaft/ppc/lithium-codegen-ppc.h" | 11 #include "src/crankshaft/s390/lithium-codegen-s390.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 #define DEFINE_COMPILE(type) \ | 16 #define DEFINE_COMPILE(type) \ |
17 void L##type::CompileToNative(LCodeGen* generator) { \ | 17 void L##type::CompileToNative(LCodeGen* generator) { \ |
18 generator->Do##type(this); \ | 18 generator->Do##type(this); \ |
19 } | 19 } |
20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) | 20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) |
21 #undef DEFINE_COMPILE | 21 #undef DEFINE_COMPILE |
(...skipping 10 matching lines...) Expand all Loading... |
32 LUnallocated* operand = LUnallocated::cast(it.Current()); | 32 LUnallocated* operand = LUnallocated::cast(it.Current()); |
33 DCHECK(operand->HasFixedPolicy() || operand->IsUsedAtStart()); | 33 DCHECK(operand->HasFixedPolicy() || operand->IsUsedAtStart()); |
34 } | 34 } |
35 for (TempIterator it(this); !it.Done(); it.Advance()) { | 35 for (TempIterator it(this); !it.Done(); it.Advance()) { |
36 LUnallocated* operand = LUnallocated::cast(it.Current()); | 36 LUnallocated* operand = LUnallocated::cast(it.Current()); |
37 DCHECK(operand->HasFixedPolicy() || !operand->HasRegisterPolicy()); | 37 DCHECK(operand->HasFixedPolicy() || !operand->HasRegisterPolicy()); |
38 } | 38 } |
39 } | 39 } |
40 #endif | 40 #endif |
41 | 41 |
42 | |
43 void LInstruction::PrintTo(StringStream* stream) { | 42 void LInstruction::PrintTo(StringStream* stream) { |
44 stream->Add("%s ", this->Mnemonic()); | 43 stream->Add("%s ", this->Mnemonic()); |
45 | 44 |
46 PrintOutputOperandTo(stream); | 45 PrintOutputOperandTo(stream); |
47 | 46 |
48 PrintDataTo(stream); | 47 PrintDataTo(stream); |
49 | 48 |
50 if (HasEnvironment()) { | 49 if (HasEnvironment()) { |
51 stream->Add(" "); | 50 stream->Add(" "); |
52 environment()->PrintTo(stream); | 51 environment()->PrintTo(stream); |
53 } | 52 } |
54 | 53 |
55 if (HasPointerMap()) { | 54 if (HasPointerMap()) { |
56 stream->Add(" "); | 55 stream->Add(" "); |
57 pointer_map()->PrintTo(stream); | 56 pointer_map()->PrintTo(stream); |
58 } | 57 } |
59 } | 58 } |
60 | 59 |
61 | |
62 void LInstruction::PrintDataTo(StringStream* stream) { | 60 void LInstruction::PrintDataTo(StringStream* stream) { |
63 stream->Add("= "); | 61 stream->Add("= "); |
64 for (int i = 0; i < InputCount(); i++) { | 62 for (int i = 0; i < InputCount(); i++) { |
65 if (i > 0) stream->Add(" "); | 63 if (i > 0) stream->Add(" "); |
66 if (InputAt(i) == NULL) { | 64 if (InputAt(i) == NULL) { |
67 stream->Add("NULL"); | 65 stream->Add("NULL"); |
68 } else { | 66 } else { |
69 InputAt(i)->PrintTo(stream); | 67 InputAt(i)->PrintTo(stream); |
70 } | 68 } |
71 } | 69 } |
72 } | 70 } |
73 | 71 |
74 | |
75 void LInstruction::PrintOutputOperandTo(StringStream* stream) { | 72 void LInstruction::PrintOutputOperandTo(StringStream* stream) { |
76 if (HasResult()) result()->PrintTo(stream); | 73 if (HasResult()) result()->PrintTo(stream); |
77 } | 74 } |
78 | 75 |
79 | |
80 void LLabel::PrintDataTo(StringStream* stream) { | 76 void LLabel::PrintDataTo(StringStream* stream) { |
81 LGap::PrintDataTo(stream); | 77 LGap::PrintDataTo(stream); |
82 LLabel* rep = replacement(); | 78 LLabel* rep = replacement(); |
83 if (rep != NULL) { | 79 if (rep != NULL) { |
84 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 80 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
85 } | 81 } |
86 } | 82 } |
87 | 83 |
88 | |
89 bool LGap::IsRedundant() const { | 84 bool LGap::IsRedundant() const { |
90 for (int i = 0; i < 4; i++) { | 85 for (int i = 0; i < 4; i++) { |
91 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { | 86 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { |
92 return false; | 87 return false; |
93 } | 88 } |
94 } | 89 } |
95 | 90 |
96 return true; | 91 return true; |
97 } | 92 } |
98 | 93 |
99 | |
100 void LGap::PrintDataTo(StringStream* stream) { | 94 void LGap::PrintDataTo(StringStream* stream) { |
101 for (int i = 0; i < 4; i++) { | 95 for (int i = 0; i < 4; i++) { |
102 stream->Add("("); | 96 stream->Add("("); |
103 if (parallel_moves_[i] != NULL) { | 97 if (parallel_moves_[i] != NULL) { |
104 parallel_moves_[i]->PrintDataTo(stream); | 98 parallel_moves_[i]->PrintDataTo(stream); |
105 } | 99 } |
106 stream->Add(") "); | 100 stream->Add(") "); |
107 } | 101 } |
108 } | 102 } |
109 | 103 |
110 | |
111 const char* LArithmeticD::Mnemonic() const { | 104 const char* LArithmeticD::Mnemonic() const { |
112 switch (op()) { | 105 switch (op()) { |
113 case Token::ADD: | 106 case Token::ADD: |
114 return "add-d"; | 107 return "add-d"; |
115 case Token::SUB: | 108 case Token::SUB: |
116 return "sub-d"; | 109 return "sub-d"; |
117 case Token::MUL: | 110 case Token::MUL: |
118 return "mul-d"; | 111 return "mul-d"; |
119 case Token::DIV: | 112 case Token::DIV: |
120 return "div-d"; | 113 return "div-d"; |
121 case Token::MOD: | 114 case Token::MOD: |
122 return "mod-d"; | 115 return "mod-d"; |
123 default: | 116 default: |
124 UNREACHABLE(); | 117 UNREACHABLE(); |
125 return NULL; | 118 return NULL; |
126 } | 119 } |
127 } | 120 } |
128 | 121 |
129 | |
130 const char* LArithmeticT::Mnemonic() const { | 122 const char* LArithmeticT::Mnemonic() const { |
131 switch (op()) { | 123 switch (op()) { |
132 case Token::ADD: | 124 case Token::ADD: |
133 return "add-t"; | 125 return "add-t"; |
134 case Token::SUB: | 126 case Token::SUB: |
135 return "sub-t"; | 127 return "sub-t"; |
136 case Token::MUL: | 128 case Token::MUL: |
137 return "mul-t"; | 129 return "mul-t"; |
138 case Token::MOD: | 130 case Token::MOD: |
139 return "mod-t"; | 131 return "mod-t"; |
(...skipping 12 matching lines...) Expand all Loading... |
152 case Token::SAR: | 144 case Token::SAR: |
153 return "sar-t"; | 145 return "sar-t"; |
154 case Token::SHR: | 146 case Token::SHR: |
155 return "shr-t"; | 147 return "shr-t"; |
156 default: | 148 default: |
157 UNREACHABLE(); | 149 UNREACHABLE(); |
158 return NULL; | 150 return NULL; |
159 } | 151 } |
160 } | 152 } |
161 | 153 |
162 | |
163 bool LGoto::HasInterestingComment(LCodeGen* gen) const { | 154 bool LGoto::HasInterestingComment(LCodeGen* gen) const { |
164 return !gen->IsNextEmittedBlock(block_id()); | 155 return !gen->IsNextEmittedBlock(block_id()); |
165 } | 156 } |
166 | 157 |
167 | |
168 void LGoto::PrintDataTo(StringStream* stream) { | 158 void LGoto::PrintDataTo(StringStream* stream) { |
169 stream->Add("B%d", block_id()); | 159 stream->Add("B%d", block_id()); |
170 } | 160 } |
171 | 161 |
172 | |
173 void LBranch::PrintDataTo(StringStream* stream) { | 162 void LBranch::PrintDataTo(StringStream* stream) { |
174 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); | 163 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); |
175 value()->PrintTo(stream); | 164 value()->PrintTo(stream); |
176 } | 165 } |
177 | 166 |
178 | |
179 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) { | 167 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) { |
180 stream->Add("if "); | 168 stream->Add("if "); |
181 left()->PrintTo(stream); | 169 left()->PrintTo(stream); |
182 stream->Add(" %s ", Token::String(op())); | 170 stream->Add(" %s ", Token::String(op())); |
183 right()->PrintTo(stream); | 171 right()->PrintTo(stream); |
184 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 172 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
185 } | 173 } |
186 | 174 |
187 | |
188 void LIsStringAndBranch::PrintDataTo(StringStream* stream) { | 175 void LIsStringAndBranch::PrintDataTo(StringStream* stream) { |
189 stream->Add("if is_string("); | 176 stream->Add("if is_string("); |
190 value()->PrintTo(stream); | 177 value()->PrintTo(stream); |
191 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 178 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
192 } | 179 } |
193 | 180 |
194 | |
195 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { | 181 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { |
196 stream->Add("if is_smi("); | 182 stream->Add("if is_smi("); |
197 value()->PrintTo(stream); | 183 value()->PrintTo(stream); |
198 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 184 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
199 } | 185 } |
200 | 186 |
201 | |
202 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { | 187 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { |
203 stream->Add("if is_undetectable("); | 188 stream->Add("if is_undetectable("); |
204 value()->PrintTo(stream); | 189 value()->PrintTo(stream); |
205 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 190 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
206 } | 191 } |
207 | 192 |
208 | |
209 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { | 193 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { |
210 stream->Add("if string_compare("); | 194 stream->Add("if string_compare("); |
211 left()->PrintTo(stream); | 195 left()->PrintTo(stream); |
212 right()->PrintTo(stream); | 196 right()->PrintTo(stream); |
213 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 197 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
214 } | 198 } |
215 | 199 |
216 | |
217 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { | 200 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { |
218 stream->Add("if has_instance_type("); | 201 stream->Add("if has_instance_type("); |
219 value()->PrintTo(stream); | 202 value()->PrintTo(stream); |
220 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 203 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
221 } | 204 } |
222 | 205 |
223 | |
224 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { | 206 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { |
225 stream->Add("if has_cached_array_index("); | 207 stream->Add("if has_cached_array_index("); |
226 value()->PrintTo(stream); | 208 value()->PrintTo(stream); |
227 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 209 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
228 } | 210 } |
229 | 211 |
230 | |
231 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { | 212 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
232 stream->Add("if class_of_test("); | 213 stream->Add("if class_of_test("); |
233 value()->PrintTo(stream); | 214 value()->PrintTo(stream); |
234 stream->Add(", \"%o\") then B%d else B%d", *hydrogen()->class_name(), | 215 stream->Add(", \"%o\") then B%d else B%d", *hydrogen()->class_name(), |
235 true_block_id(), false_block_id()); | 216 true_block_id(), false_block_id()); |
236 } | 217 } |
237 | 218 |
238 | |
239 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { | 219 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
240 stream->Add("if typeof "); | 220 stream->Add("if typeof "); |
241 value()->PrintTo(stream); | 221 value()->PrintTo(stream); |
242 stream->Add(" == \"%s\" then B%d else B%d", | 222 stream->Add(" == \"%s\" then B%d else B%d", |
243 hydrogen()->type_literal()->ToCString().get(), true_block_id(), | 223 hydrogen()->type_literal()->ToCString().get(), true_block_id(), |
244 false_block_id()); | 224 false_block_id()); |
245 } | 225 } |
246 | 226 |
247 | |
248 void LStoreCodeEntry::PrintDataTo(StringStream* stream) { | 227 void LStoreCodeEntry::PrintDataTo(StringStream* stream) { |
249 stream->Add(" = "); | 228 stream->Add(" = "); |
250 function()->PrintTo(stream); | 229 function()->PrintTo(stream); |
251 stream->Add(".code_entry = "); | 230 stream->Add(".code_entry = "); |
252 code_object()->PrintTo(stream); | 231 code_object()->PrintTo(stream); |
253 } | 232 } |
254 | 233 |
255 | |
256 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) { | 234 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) { |
257 stream->Add(" = "); | 235 stream->Add(" = "); |
258 base_object()->PrintTo(stream); | 236 base_object()->PrintTo(stream); |
259 stream->Add(" + "); | 237 stream->Add(" + "); |
260 offset()->PrintTo(stream); | 238 offset()->PrintTo(stream); |
261 } | 239 } |
262 | 240 |
263 | |
264 void LCallWithDescriptor::PrintDataTo(StringStream* stream) { | 241 void LCallWithDescriptor::PrintDataTo(StringStream* stream) { |
265 for (int i = 0; i < InputCount(); i++) { | 242 for (int i = 0; i < InputCount(); i++) { |
266 InputAt(i)->PrintTo(stream); | 243 InputAt(i)->PrintTo(stream); |
267 stream->Add(" "); | 244 stream->Add(" "); |
268 } | 245 } |
269 stream->Add("#%d / ", arity()); | 246 stream->Add("#%d / ", arity()); |
270 } | 247 } |
271 | 248 |
272 | |
273 void LLoadContextSlot::PrintDataTo(StringStream* stream) { | 249 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
274 context()->PrintTo(stream); | 250 context()->PrintTo(stream); |
275 stream->Add("[%d]", slot_index()); | 251 stream->Add("[%d]", slot_index()); |
276 } | 252 } |
277 | 253 |
278 | |
279 void LStoreContextSlot::PrintDataTo(StringStream* stream) { | 254 void LStoreContextSlot::PrintDataTo(StringStream* stream) { |
280 context()->PrintTo(stream); | 255 context()->PrintTo(stream); |
281 stream->Add("[%d] <- ", slot_index()); | 256 stream->Add("[%d] <- ", slot_index()); |
282 value()->PrintTo(stream); | 257 value()->PrintTo(stream); |
283 } | 258 } |
284 | 259 |
285 | |
286 void LInvokeFunction::PrintDataTo(StringStream* stream) { | 260 void LInvokeFunction::PrintDataTo(StringStream* stream) { |
287 stream->Add("= "); | 261 stream->Add("= "); |
288 function()->PrintTo(stream); | 262 function()->PrintTo(stream); |
289 stream->Add(" #%d / ", arity()); | 263 stream->Add(" #%d / ", arity()); |
290 } | 264 } |
291 | 265 |
292 | |
293 void LCallNewArray::PrintDataTo(StringStream* stream) { | 266 void LCallNewArray::PrintDataTo(StringStream* stream) { |
294 stream->Add("= "); | 267 stream->Add("= "); |
295 constructor()->PrintTo(stream); | 268 constructor()->PrintTo(stream); |
296 stream->Add(" #%d / ", arity()); | 269 stream->Add(" #%d / ", arity()); |
297 ElementsKind kind = hydrogen()->elements_kind(); | 270 ElementsKind kind = hydrogen()->elements_kind(); |
298 stream->Add(" (%s) ", ElementsKindToString(kind)); | 271 stream->Add(" (%s) ", ElementsKindToString(kind)); |
299 } | 272 } |
300 | 273 |
301 | |
302 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { | 274 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
303 arguments()->PrintTo(stream); | 275 arguments()->PrintTo(stream); |
304 stream->Add(" length "); | 276 stream->Add(" length "); |
305 length()->PrintTo(stream); | 277 length()->PrintTo(stream); |
306 stream->Add(" index "); | 278 stream->Add(" index "); |
307 index()->PrintTo(stream); | 279 index()->PrintTo(stream); |
308 } | 280 } |
309 | 281 |
310 | |
311 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 282 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
312 object()->PrintTo(stream); | 283 object()->PrintTo(stream); |
313 std::ostringstream os; | 284 std::ostringstream os; |
314 os << hydrogen()->access() << " <- "; | 285 os << hydrogen()->access() << " <- "; |
315 stream->Add(os.str().c_str()); | 286 stream->Add(os.str().c_str()); |
316 value()->PrintTo(stream); | 287 value()->PrintTo(stream); |
317 } | 288 } |
318 | 289 |
319 | |
320 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { | 290 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) { |
321 object()->PrintTo(stream); | 291 object()->PrintTo(stream); |
322 stream->Add("."); | 292 stream->Add("."); |
323 stream->Add(String::cast(*name())->ToCString().get()); | 293 stream->Add(String::cast(*name())->ToCString().get()); |
324 stream->Add(" <- "); | 294 stream->Add(" <- "); |
325 value()->PrintTo(stream); | 295 value()->PrintTo(stream); |
326 } | 296 } |
327 | 297 |
328 | |
329 void LLoadKeyed::PrintDataTo(StringStream* stream) { | 298 void LLoadKeyed::PrintDataTo(StringStream* stream) { |
330 elements()->PrintTo(stream); | 299 elements()->PrintTo(stream); |
331 stream->Add("["); | 300 stream->Add("["); |
332 key()->PrintTo(stream); | 301 key()->PrintTo(stream); |
333 if (hydrogen()->IsDehoisted()) { | 302 if (hydrogen()->IsDehoisted()) { |
334 stream->Add(" + %d]", base_offset()); | 303 stream->Add(" + %d]", base_offset()); |
335 } else { | 304 } else { |
336 stream->Add("]"); | 305 stream->Add("]"); |
337 } | 306 } |
338 } | 307 } |
339 | 308 |
340 | |
341 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 309 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
342 elements()->PrintTo(stream); | 310 elements()->PrintTo(stream); |
343 stream->Add("["); | 311 stream->Add("["); |
344 key()->PrintTo(stream); | 312 key()->PrintTo(stream); |
345 if (hydrogen()->IsDehoisted()) { | 313 if (hydrogen()->IsDehoisted()) { |
346 stream->Add(" + %d] <-", base_offset()); | 314 stream->Add(" + %d] <-", base_offset()); |
347 } else { | 315 } else { |
348 stream->Add("] <- "); | 316 stream->Add("] <- "); |
349 } | 317 } |
350 | 318 |
351 if (value() == NULL) { | 319 if (value() == NULL) { |
352 DCHECK(hydrogen()->IsConstantHoleStore() && | 320 DCHECK(hydrogen()->IsConstantHoleStore() && |
353 hydrogen()->value()->representation().IsDouble()); | 321 hydrogen()->value()->representation().IsDouble()); |
354 stream->Add("<the hole(nan)>"); | 322 stream->Add("<the hole(nan)>"); |
355 } else { | 323 } else { |
356 value()->PrintTo(stream); | 324 value()->PrintTo(stream); |
357 } | 325 } |
358 } | 326 } |
359 | 327 |
360 | |
361 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { | 328 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { |
362 object()->PrintTo(stream); | 329 object()->PrintTo(stream); |
363 stream->Add("["); | 330 stream->Add("["); |
364 key()->PrintTo(stream); | 331 key()->PrintTo(stream); |
365 stream->Add("] <- "); | 332 stream->Add("] <- "); |
366 value()->PrintTo(stream); | 333 value()->PrintTo(stream); |
367 } | 334 } |
368 | 335 |
369 | |
370 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { | 336 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { |
371 object()->PrintTo(stream); | 337 object()->PrintTo(stream); |
372 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); | 338 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); |
373 } | 339 } |
374 | 340 |
375 | |
376 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { | 341 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) { |
377 // Skip a slot if for a double-width slot. | 342 // Skip a slot if for a double-width slot. |
378 if (kind == DOUBLE_REGISTERS) current_frame_slots_++; | 343 if (kind == DOUBLE_REGISTERS) current_frame_slots_++; |
379 return current_frame_slots_++; | 344 return current_frame_slots_++; |
380 } | 345 } |
381 | 346 |
382 | |
383 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { | 347 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
384 int index = GetNextSpillIndex(kind); | 348 int index = GetNextSpillIndex(kind); |
385 if (kind == DOUBLE_REGISTERS) { | 349 if (kind == DOUBLE_REGISTERS) { |
386 return LDoubleStackSlot::Create(index, zone()); | 350 return LDoubleStackSlot::Create(index, zone()); |
387 } else { | 351 } else { |
388 DCHECK(kind == GENERAL_REGISTERS); | 352 DCHECK(kind == GENERAL_REGISTERS); |
389 return LStackSlot::Create(index, zone()); | 353 return LStackSlot::Create(index, zone()); |
390 } | 354 } |
391 } | 355 } |
392 | 356 |
393 | |
394 LPlatformChunk* LChunkBuilder::Build() { | 357 LPlatformChunk* LChunkBuilder::Build() { |
395 DCHECK(is_unused()); | 358 DCHECK(is_unused()); |
396 chunk_ = new (zone()) LPlatformChunk(info(), graph()); | 359 chunk_ = new (zone()) LPlatformChunk(info(), graph()); |
397 LPhase phase("L_Building chunk", chunk_); | 360 LPhase phase("L_Building chunk", chunk_); |
398 status_ = BUILDING; | 361 status_ = BUILDING; |
399 | 362 |
400 // If compiling for OSR, reserve space for the unoptimized frame, | 363 // If compiling for OSR, reserve space for the unoptimized frame, |
401 // which will be subsumed into this frame. | 364 // which will be subsumed into this frame. |
402 if (graph()->has_osr()) { | 365 if (graph()->has_osr()) { |
403 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { | 366 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
404 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); | 367 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
405 } | 368 } |
406 } | 369 } |
407 | 370 |
408 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); | 371 const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); |
409 for (int i = 0; i < blocks->length(); i++) { | 372 for (int i = 0; i < blocks->length(); i++) { |
410 HBasicBlock* next = NULL; | 373 HBasicBlock* next = NULL; |
411 if (i < blocks->length() - 1) next = blocks->at(i + 1); | 374 if (i < blocks->length() - 1) next = blocks->at(i + 1); |
412 DoBasicBlock(blocks->at(i), next); | 375 DoBasicBlock(blocks->at(i), next); |
413 if (is_aborted()) return NULL; | 376 if (is_aborted()) return NULL; |
414 } | 377 } |
415 status_ = DONE; | 378 status_ = DONE; |
416 return chunk_; | 379 return chunk_; |
417 } | 380 } |
418 | 381 |
419 | |
420 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { | 382 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) { |
421 return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code()); | 383 return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code()); |
422 } | 384 } |
423 | 385 |
424 | |
425 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { | 386 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) { |
426 return new (zone()) | 387 return new (zone()) |
427 LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code()); | 388 LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code()); |
428 } | 389 } |
429 | 390 |
430 | |
431 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { | 391 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) { |
432 return Use(value, ToUnallocated(fixed_register)); | 392 return Use(value, ToUnallocated(fixed_register)); |
433 } | 393 } |
434 | 394 |
435 | |
436 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { | 395 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, DoubleRegister reg) { |
437 return Use(value, ToUnallocated(reg)); | 396 return Use(value, ToUnallocated(reg)); |
438 } | 397 } |
439 | 398 |
440 | |
441 LOperand* LChunkBuilder::UseRegister(HValue* value) { | 399 LOperand* LChunkBuilder::UseRegister(HValue* value) { |
442 return Use(value, | 400 return Use(value, |
443 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 401 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
444 } | 402 } |
445 | 403 |
446 | |
447 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { | 404 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) { |
448 return Use(value, new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, | 405 return Use(value, new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER, |
449 LUnallocated::USED_AT_START)); | 406 LUnallocated::USED_AT_START)); |
450 } | 407 } |
451 | 408 |
452 | |
453 LOperand* LChunkBuilder::UseTempRegister(HValue* value) { | 409 LOperand* LChunkBuilder::UseTempRegister(HValue* value) { |
454 return Use(value, new (zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER)); | 410 return Use(value, new (zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER)); |
455 } | 411 } |
456 | 412 |
457 | |
458 LOperand* LChunkBuilder::Use(HValue* value) { | 413 LOperand* LChunkBuilder::Use(HValue* value) { |
459 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE)); | 414 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE)); |
460 } | 415 } |
461 | 416 |
462 | |
463 LOperand* LChunkBuilder::UseAtStart(HValue* value) { | 417 LOperand* LChunkBuilder::UseAtStart(HValue* value) { |
464 return Use(value, new (zone()) | 418 return Use(value, new (zone()) LUnallocated(LUnallocated::NONE, |
465 LUnallocated(LUnallocated::NONE, LUnallocated::USED_AT_START)); | 419 LUnallocated::USED_AT_START)); |
466 } | 420 } |
467 | 421 |
468 | |
469 LOperand* LChunkBuilder::UseOrConstant(HValue* value) { | 422 LOperand* LChunkBuilder::UseOrConstant(HValue* value) { |
470 return value->IsConstant() | 423 return value->IsConstant() |
471 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 424 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
472 : Use(value); | 425 : Use(value); |
473 } | 426 } |
474 | 427 |
475 | |
476 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { | 428 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { |
477 return value->IsConstant() | 429 return value->IsConstant() |
478 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 430 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
479 : UseAtStart(value); | 431 : UseAtStart(value); |
480 } | 432 } |
481 | 433 |
482 | |
483 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { | 434 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { |
484 return value->IsConstant() | 435 return value->IsConstant() |
485 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 436 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
486 : UseRegister(value); | 437 : UseRegister(value); |
487 } | 438 } |
488 | 439 |
489 | |
490 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { | 440 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
491 return value->IsConstant() | 441 return value->IsConstant() |
492 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 442 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
493 : UseRegisterAtStart(value); | 443 : UseRegisterAtStart(value); |
494 } | 444 } |
495 | 445 |
496 | |
497 LOperand* LChunkBuilder::UseConstant(HValue* value) { | 446 LOperand* LChunkBuilder::UseConstant(HValue* value) { |
498 return chunk_->DefineConstantOperand(HConstant::cast(value)); | 447 return chunk_->DefineConstantOperand(HConstant::cast(value)); |
499 } | 448 } |
500 | 449 |
501 | |
502 LOperand* LChunkBuilder::UseAny(HValue* value) { | 450 LOperand* LChunkBuilder::UseAny(HValue* value) { |
503 return value->IsConstant() | 451 return value->IsConstant() |
504 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 452 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
505 : Use(value, new (zone()) LUnallocated(LUnallocated::ANY)); | 453 : Use(value, new (zone()) LUnallocated(LUnallocated::ANY)); |
506 } | 454 } |
507 | 455 |
508 | |
509 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 456 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
510 if (value->EmitAtUses()) { | 457 if (value->EmitAtUses()) { |
511 HInstruction* instr = HInstruction::cast(value); | 458 HInstruction* instr = HInstruction::cast(value); |
512 VisitInstruction(instr); | 459 VisitInstruction(instr); |
513 } | 460 } |
514 operand->set_virtual_register(value->id()); | 461 operand->set_virtual_register(value->id()); |
515 return operand; | 462 return operand; |
516 } | 463 } |
517 | 464 |
518 | |
519 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr, | 465 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr, |
520 LUnallocated* result) { | 466 LUnallocated* result) { |
521 result->set_virtual_register(current_instruction_->id()); | 467 result->set_virtual_register(current_instruction_->id()); |
522 instr->set_result(result); | 468 instr->set_result(result); |
523 return instr; | 469 return instr; |
524 } | 470 } |
525 | 471 |
526 | |
527 LInstruction* LChunkBuilder::DefineAsRegister( | 472 LInstruction* LChunkBuilder::DefineAsRegister( |
528 LTemplateResultInstruction<1>* instr) { | 473 LTemplateResultInstruction<1>* instr) { |
529 return Define(instr, | 474 return Define(instr, |
530 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 475 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
531 } | 476 } |
532 | 477 |
533 | |
534 LInstruction* LChunkBuilder::DefineAsSpilled( | 478 LInstruction* LChunkBuilder::DefineAsSpilled( |
535 LTemplateResultInstruction<1>* instr, int index) { | 479 LTemplateResultInstruction<1>* instr, int index) { |
536 return Define(instr, | 480 return Define(instr, |
537 new (zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); | 481 new (zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); |
538 } | 482 } |
539 | 483 |
540 | |
541 LInstruction* LChunkBuilder::DefineSameAsFirst( | 484 LInstruction* LChunkBuilder::DefineSameAsFirst( |
542 LTemplateResultInstruction<1>* instr) { | 485 LTemplateResultInstruction<1>* instr) { |
543 return Define(instr, | 486 return Define(instr, |
544 new (zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); | 487 new (zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); |
545 } | 488 } |
546 | 489 |
547 | |
548 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr, | 490 LInstruction* LChunkBuilder::DefineFixed(LTemplateResultInstruction<1>* instr, |
549 Register reg) { | 491 Register reg) { |
550 return Define(instr, ToUnallocated(reg)); | 492 return Define(instr, ToUnallocated(reg)); |
551 } | 493 } |
552 | 494 |
553 | |
554 LInstruction* LChunkBuilder::DefineFixedDouble( | 495 LInstruction* LChunkBuilder::DefineFixedDouble( |
555 LTemplateResultInstruction<1>* instr, DoubleRegister reg) { | 496 LTemplateResultInstruction<1>* instr, DoubleRegister reg) { |
556 return Define(instr, ToUnallocated(reg)); | 497 return Define(instr, ToUnallocated(reg)); |
557 } | 498 } |
558 | 499 |
559 | |
560 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 500 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
561 HEnvironment* hydrogen_env = current_block_->last_environment(); | 501 HEnvironment* hydrogen_env = current_block_->last_environment(); |
562 int argument_index_accumulator = 0; | 502 int argument_index_accumulator = 0; |
563 ZoneList<HValue*> objects_to_materialize(0, zone()); | 503 ZoneList<HValue*> objects_to_materialize(0, zone()); |
564 instr->set_environment(CreateEnvironment( | 504 instr->set_environment(CreateEnvironment( |
565 hydrogen_env, &argument_index_accumulator, &objects_to_materialize)); | 505 hydrogen_env, &argument_index_accumulator, &objects_to_materialize)); |
566 return instr; | 506 return instr; |
567 } | 507 } |
568 | 508 |
569 | |
570 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 509 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
571 HInstruction* hinstr, | 510 HInstruction* hinstr, |
572 CanDeoptimize can_deoptimize) { | 511 CanDeoptimize can_deoptimize) { |
573 info()->MarkAsNonDeferredCalling(); | 512 info()->MarkAsNonDeferredCalling(); |
574 #ifdef DEBUG | 513 #ifdef DEBUG |
575 instr->VerifyCall(); | 514 instr->VerifyCall(); |
576 #endif | 515 #endif |
577 instr->MarkAsCall(); | 516 instr->MarkAsCall(); |
578 instr = AssignPointerMap(instr); | 517 instr = AssignPointerMap(instr); |
579 | 518 |
580 // If instruction does not have side-effects lazy deoptimization | 519 // If instruction does not have side-effects lazy deoptimization |
581 // after the call will try to deoptimize to the point before the call. | 520 // after the call will try to deoptimize to the point before the call. |
582 // Thus we still need to attach environment to this call even if | 521 // Thus we still need to attach environment to this call even if |
583 // call sequence can not deoptimize eagerly. | 522 // call sequence can not deoptimize eagerly. |
584 bool needs_environment = (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || | 523 bool needs_environment = (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || |
585 !hinstr->HasObservableSideEffects(); | 524 !hinstr->HasObservableSideEffects(); |
586 if (needs_environment && !instr->HasEnvironment()) { | 525 if (needs_environment && !instr->HasEnvironment()) { |
587 instr = AssignEnvironment(instr); | 526 instr = AssignEnvironment(instr); |
588 // We can't really figure out if the environment is needed or not. | 527 // We can't really figure out if the environment is needed or not. |
589 instr->environment()->set_has_been_used(); | 528 instr->environment()->set_has_been_used(); |
590 } | 529 } |
591 | 530 |
592 return instr; | 531 return instr; |
593 } | 532 } |
594 | 533 |
595 | |
596 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 534 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
597 DCHECK(!instr->HasPointerMap()); | 535 DCHECK(!instr->HasPointerMap()); |
598 instr->set_pointer_map(new (zone()) LPointerMap(zone())); | 536 instr->set_pointer_map(new (zone()) LPointerMap(zone())); |
599 return instr; | 537 return instr; |
600 } | 538 } |
601 | 539 |
602 | |
603 LUnallocated* LChunkBuilder::TempRegister() { | 540 LUnallocated* LChunkBuilder::TempRegister() { |
604 LUnallocated* operand = | 541 LUnallocated* operand = |
605 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 542 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
606 int vreg = allocator_->GetVirtualRegister(); | 543 int vreg = allocator_->GetVirtualRegister(); |
607 if (!allocator_->AllocationOk()) { | 544 if (!allocator_->AllocationOk()) { |
608 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); | 545 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); |
609 vreg = 0; | 546 vreg = 0; |
610 } | 547 } |
611 operand->set_virtual_register(vreg); | 548 operand->set_virtual_register(vreg); |
612 return operand; | 549 return operand; |
613 } | 550 } |
614 | 551 |
615 | |
616 LUnallocated* LChunkBuilder::TempDoubleRegister() { | 552 LUnallocated* LChunkBuilder::TempDoubleRegister() { |
617 LUnallocated* operand = | 553 LUnallocated* operand = |
618 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER); | 554 new (zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER); |
619 int vreg = allocator_->GetVirtualRegister(); | 555 int vreg = allocator_->GetVirtualRegister(); |
620 if (!allocator_->AllocationOk()) { | 556 if (!allocator_->AllocationOk()) { |
621 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); | 557 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); |
622 vreg = 0; | 558 vreg = 0; |
623 } | 559 } |
624 operand->set_virtual_register(vreg); | 560 operand->set_virtual_register(vreg); |
625 return operand; | 561 return operand; |
626 } | 562 } |
627 | 563 |
628 | |
629 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 564 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
630 LUnallocated* operand = ToUnallocated(reg); | 565 LUnallocated* operand = ToUnallocated(reg); |
631 DCHECK(operand->HasFixedPolicy()); | 566 DCHECK(operand->HasFixedPolicy()); |
632 return operand; | 567 return operand; |
633 } | 568 } |
634 | 569 |
635 | |
636 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { | 570 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) { |
637 LUnallocated* operand = ToUnallocated(reg); | 571 LUnallocated* operand = ToUnallocated(reg); |
638 DCHECK(operand->HasFixedPolicy()); | 572 DCHECK(operand->HasFixedPolicy()); |
639 return operand; | 573 return operand; |
640 } | 574 } |
641 | 575 |
642 | |
643 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { | 576 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { |
644 return new (zone()) LLabel(instr->block()); | 577 return new (zone()) LLabel(instr->block()); |
645 } | 578 } |
646 | 579 |
647 | |
648 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { | 580 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { |
649 return DefineAsRegister(new (zone()) LDummyUse(UseAny(instr->value()))); | 581 return DefineAsRegister(new (zone()) LDummyUse(UseAny(instr->value()))); |
650 } | 582 } |
651 | 583 |
652 | |
653 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 584 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
654 UNREACHABLE(); | 585 UNREACHABLE(); |
655 return NULL; | 586 return NULL; |
656 } | 587 } |
657 | 588 |
658 | |
659 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 589 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
660 return AssignEnvironment(new (zone()) LDeoptimize); | 590 return AssignEnvironment(new (zone()) LDeoptimize); |
661 } | 591 } |
662 | 592 |
663 | |
664 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 593 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
665 HBitwiseBinaryOperation* instr) { | 594 HBitwiseBinaryOperation* instr) { |
666 if (instr->representation().IsSmiOrInteger32()) { | 595 if (instr->representation().IsSmiOrInteger32()) { |
667 DCHECK(instr->left()->representation().Equals(instr->representation())); | 596 DCHECK(instr->left()->representation().Equals(instr->representation())); |
668 DCHECK(instr->right()->representation().Equals(instr->representation())); | 597 DCHECK(instr->right()->representation().Equals(instr->representation())); |
669 LOperand* left = UseRegisterAtStart(instr->left()); | 598 LOperand* left = UseRegisterAtStart(instr->left()); |
670 | 599 |
671 HValue* right_value = instr->right(); | 600 HValue* right_value = instr->right(); |
672 LOperand* right = NULL; | 601 LOperand* right = NULL; |
673 int constant_value = 0; | 602 int constant_value = 0; |
(...skipping 18 matching lines...) Expand all Loading... |
692 } | 621 } |
693 | 622 |
694 LInstruction* result = | 623 LInstruction* result = |
695 DefineAsRegister(new (zone()) LShiftI(op, left, right, does_deopt)); | 624 DefineAsRegister(new (zone()) LShiftI(op, left, right, does_deopt)); |
696 return does_deopt ? AssignEnvironment(result) : result; | 625 return does_deopt ? AssignEnvironment(result) : result; |
697 } else { | 626 } else { |
698 return DoArithmeticT(op, instr); | 627 return DoArithmeticT(op, instr); |
699 } | 628 } |
700 } | 629 } |
701 | 630 |
702 | |
703 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 631 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
704 HArithmeticBinaryOperation* instr) { | 632 HArithmeticBinaryOperation* instr) { |
705 DCHECK(instr->representation().IsDouble()); | 633 DCHECK(instr->representation().IsDouble()); |
706 DCHECK(instr->left()->representation().IsDouble()); | 634 DCHECK(instr->left()->representation().IsDouble()); |
707 DCHECK(instr->right()->representation().IsDouble()); | 635 DCHECK(instr->right()->representation().IsDouble()); |
708 if (op == Token::MOD) { | 636 if (op == Token::MOD) { |
709 LOperand* left = UseFixedDouble(instr->left(), d1); | 637 LOperand* left = UseFixedDouble(instr->left(), d1); |
710 LOperand* right = UseFixedDouble(instr->right(), d2); | 638 LOperand* right = UseFixedDouble(instr->right(), d2); |
711 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); | 639 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); |
712 // We call a C function for double modulo. It can't trigger a GC. We need | 640 // We call a C function for double modulo. It can't trigger a GC. We need |
713 // to use fixed result register for the call. | 641 // to use fixed result register for the call. |
714 // TODO(fschneider): Allow any register as input registers. | 642 // TODO(fschneider): Allow any register as input registers. |
715 return MarkAsCall(DefineFixedDouble(result, d1), instr); | 643 return MarkAsCall(DefineFixedDouble(result, d1), instr); |
716 } else { | 644 } else { |
717 LOperand* left = UseRegisterAtStart(instr->left()); | 645 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
718 LOperand* right = UseRegisterAtStart(instr->right()); | 646 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
719 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); | 647 LArithmeticD* result = new (zone()) LArithmeticD(op, left, right); |
720 return DefineAsRegister(result); | 648 return DefineSameAsFirst(result); |
721 } | 649 } |
722 } | 650 } |
723 | 651 |
724 | |
725 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 652 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
726 HBinaryOperation* instr) { | 653 HBinaryOperation* instr) { |
727 HValue* left = instr->left(); | 654 HValue* left = instr->left(); |
728 HValue* right = instr->right(); | 655 HValue* right = instr->right(); |
729 DCHECK(left->representation().IsTagged()); | 656 DCHECK(left->representation().IsTagged()); |
730 DCHECK(right->representation().IsTagged()); | 657 DCHECK(right->representation().IsTagged()); |
731 LOperand* context = UseFixed(instr->context(), cp); | 658 LOperand* context = UseFixed(instr->context(), cp); |
732 LOperand* left_operand = UseFixed(left, r4); | 659 LOperand* left_operand = UseFixed(left, r3); |
733 LOperand* right_operand = UseFixed(right, r3); | 660 LOperand* right_operand = UseFixed(right, r2); |
734 LArithmeticT* result = | 661 LArithmeticT* result = |
735 new (zone()) LArithmeticT(op, context, left_operand, right_operand); | 662 new (zone()) LArithmeticT(op, context, left_operand, right_operand); |
736 return MarkAsCall(DefineFixed(result, r3), instr); | 663 return MarkAsCall(DefineFixed(result, r2), instr); |
737 } | 664 } |
738 | 665 |
739 | |
740 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 666 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
741 DCHECK(is_building()); | 667 DCHECK(is_building()); |
742 current_block_ = block; | 668 current_block_ = block; |
743 next_block_ = next_block; | 669 next_block_ = next_block; |
744 if (block->IsStartBlock()) { | 670 if (block->IsStartBlock()) { |
745 block->UpdateEnvironment(graph_->start_environment()); | 671 block->UpdateEnvironment(graph_->start_environment()); |
746 argument_count_ = 0; | 672 argument_count_ = 0; |
747 } else if (block->predecessors()->length() == 1) { | 673 } else if (block->predecessors()->length() == 1) { |
748 // We have a single predecessor => copy environment and outgoing | 674 // We have a single predecessor => copy environment and outgoing |
749 // argument count from the predecessor. | 675 // argument count from the predecessor. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 int end = chunk_->instructions()->length() - 1; | 722 int end = chunk_->instructions()->length() - 1; |
797 if (end >= start) { | 723 if (end >= start) { |
798 block->set_first_instruction_index(start); | 724 block->set_first_instruction_index(start); |
799 block->set_last_instruction_index(end); | 725 block->set_last_instruction_index(end); |
800 } | 726 } |
801 block->set_argument_count(argument_count_); | 727 block->set_argument_count(argument_count_); |
802 next_block_ = NULL; | 728 next_block_ = NULL; |
803 current_block_ = NULL; | 729 current_block_ = NULL; |
804 } | 730 } |
805 | 731 |
806 | |
807 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 732 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
808 HInstruction* old_current = current_instruction_; | 733 HInstruction* old_current = current_instruction_; |
809 current_instruction_ = current; | 734 current_instruction_ = current; |
810 | 735 |
811 LInstruction* instr = NULL; | 736 LInstruction* instr = NULL; |
812 if (current->CanReplaceWithDummyUses()) { | 737 if (current->CanReplaceWithDummyUses()) { |
813 if (current->OperandCount() == 0) { | 738 if (current->OperandCount() == 0) { |
814 instr = DefineAsRegister(new (zone()) LDummy()); | 739 instr = DefineAsRegister(new (zone()) LDummy()); |
815 } else { | 740 } else { |
816 DCHECK(!current->OperandAt(0)->IsControlInstruction()); | 741 DCHECK(!current->OperandAt(0)->IsControlInstruction()); |
817 instr = DefineAsRegister(new (zone()) | 742 instr = DefineAsRegister(new (zone()) |
818 LDummyUse(UseAny(current->OperandAt(0)))); | 743 LDummyUse(UseAny(current->OperandAt(0)))); |
819 } | 744 } |
820 for (int i = 1; i < current->OperandCount(); ++i) { | 745 for (int i = 1; i < current->OperandCount(); ++i) { |
821 if (current->OperandAt(i)->IsControlInstruction()) continue; | 746 if (current->OperandAt(i)->IsControlInstruction()) continue; |
822 LInstruction* dummy = | 747 LInstruction* dummy = |
823 new (zone()) LDummyUse(UseAny(current->OperandAt(i))); | 748 new (zone()) LDummyUse(UseAny(current->OperandAt(i))); |
824 dummy->set_hydrogen_value(current); | 749 dummy->set_hydrogen_value(current); |
825 chunk_->AddInstruction(dummy, current_block_); | 750 chunk_->AddInstruction(dummy, current_block_); |
826 } | 751 } |
827 } else { | 752 } else { |
828 HBasicBlock* successor; | 753 HBasicBlock* successor; |
829 if (current->IsControlInstruction() && | 754 if (current->IsControlInstruction() && |
830 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && | 755 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && |
831 successor != NULL) { | 756 successor != NULL) { |
832 instr = new (zone()) LGoto(successor); | 757 instr = new (zone()) LGoto(successor); |
833 } else { | 758 } else { |
834 instr = current->CompileToLithium(this); | 759 instr = current->CompileToLithium(this); |
835 } | 760 } |
836 } | 761 } |
837 | 762 |
838 argument_count_ += current->argument_delta(); | 763 argument_count_ += current->argument_delta(); |
839 DCHECK(argument_count_ >= 0); | 764 DCHECK(argument_count_ >= 0); |
840 | 765 |
841 if (instr != NULL) { | 766 if (instr != NULL) { |
842 AddInstruction(instr, current); | 767 AddInstruction(instr, current); |
843 } | 768 } |
844 | 769 |
845 current_instruction_ = old_current; | 770 current_instruction_ = old_current; |
846 } | 771 } |
847 | 772 |
848 | |
849 void LChunkBuilder::AddInstruction(LInstruction* instr, | 773 void LChunkBuilder::AddInstruction(LInstruction* instr, |
850 HInstruction* hydrogen_val) { | 774 HInstruction* hydrogen_val) { |
851 // Associate the hydrogen instruction first, since we may need it for | 775 // Associate the hydrogen instruction first, since we may need it for |
852 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. | 776 // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below. |
853 instr->set_hydrogen_value(hydrogen_val); | 777 instr->set_hydrogen_value(hydrogen_val); |
854 | 778 |
855 #if DEBUG | 779 #if DEBUG |
856 // Make sure that the lithium instruction has either no fixed register | 780 // Make sure that the lithium instruction has either no fixed register |
857 // constraints in temps or the result OR no uses that are only used at | 781 // constraints in temps or the result OR no uses that are only used at |
858 // start. If this invariant doesn't hold, the register allocator can decide | 782 // start. If this invariant doesn't hold, the register allocator can decide |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
896 HSimulate* sim = HSimulate::cast(hydrogen_val->next()); | 820 HSimulate* sim = HSimulate::cast(hydrogen_val->next()); |
897 sim->ReplayEnvironment(current_block_->last_environment()); | 821 sim->ReplayEnvironment(current_block_->last_environment()); |
898 hydrogen_value_for_lazy_bailout = sim; | 822 hydrogen_value_for_lazy_bailout = sim; |
899 } | 823 } |
900 LInstruction* bailout = AssignEnvironment(new (zone()) LLazyBailout()); | 824 LInstruction* bailout = AssignEnvironment(new (zone()) LLazyBailout()); |
901 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); | 825 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
902 chunk_->AddInstruction(bailout, current_block_); | 826 chunk_->AddInstruction(bailout, current_block_); |
903 } | 827 } |
904 } | 828 } |
905 | 829 |
906 | |
907 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) { | 830 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) { |
908 return new (zone()) LPrologue(); | 831 return new (zone()) LPrologue(); |
909 } | 832 } |
910 | 833 |
911 | |
912 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 834 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
913 return new (zone()) LGoto(instr->FirstSuccessor()); | 835 return new (zone()) LGoto(instr->FirstSuccessor()); |
914 } | 836 } |
915 | 837 |
916 | |
917 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 838 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
918 HValue* value = instr->value(); | 839 HValue* value = instr->value(); |
919 Representation r = value->representation(); | 840 Representation r = value->representation(); |
920 HType type = value->type(); | 841 HType type = value->type(); |
921 ToBooleanICStub::Types expected = instr->expected_input_types(); | 842 ToBooleanStub::Types expected = instr->expected_input_types(); |
922 if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic(); | 843 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
923 | 844 |
924 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || | 845 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || |
925 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); | 846 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); |
926 LInstruction* branch = new (zone()) LBranch(UseRegister(value)); | 847 LInstruction* branch = new (zone()) LBranch(UseRegister(value)); |
927 if (!easy_case && | 848 if (!easy_case && |
928 ((!expected.Contains(ToBooleanICStub::SMI) && expected.NeedsMap()) || | 849 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
929 !expected.IsGeneric())) { | 850 !expected.IsGeneric())) { |
930 branch = AssignEnvironment(branch); | 851 branch = AssignEnvironment(branch); |
931 } | 852 } |
932 return branch; | 853 return branch; |
933 } | 854 } |
934 | 855 |
935 | |
936 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 856 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
937 return new (zone()) LDebugBreak(); | 857 return new (zone()) LDebugBreak(); |
938 } | 858 } |
939 | 859 |
940 | |
941 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 860 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
942 DCHECK(instr->value()->representation().IsTagged()); | 861 DCHECK(instr->value()->representation().IsTagged()); |
943 LOperand* value = UseRegisterAtStart(instr->value()); | 862 LOperand* value = UseRegister(instr->value()); |
944 LOperand* temp = TempRegister(); | 863 LOperand* temp = TempRegister(); |
945 return new (zone()) LCmpMapAndBranch(value, temp); | 864 return new (zone()) LCmpMapAndBranch(value, temp); |
946 } | 865 } |
947 | 866 |
948 | |
949 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { | 867 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) { |
950 info()->MarkAsRequiresFrame(); | 868 info()->MarkAsRequiresFrame(); |
951 LOperand* value = UseRegister(instr->value()); | 869 LOperand* value = UseRegister(instr->value()); |
952 return DefineAsRegister(new (zone()) LArgumentsLength(value)); | 870 return DefineAsRegister(new (zone()) LArgumentsLength(value)); |
953 } | 871 } |
954 | 872 |
955 | |
956 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 873 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
957 info()->MarkAsRequiresFrame(); | 874 info()->MarkAsRequiresFrame(); |
958 return DefineAsRegister(new (zone()) LArgumentsElements); | 875 return DefineAsRegister(new (zone()) LArgumentsElements); |
959 } | 876 } |
960 | 877 |
961 | |
962 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 878 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
963 LOperand* left = | 879 LOperand* left = |
964 UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister()); | 880 UseFixed(instr->left(), InstanceOfDescriptor::LeftRegister()); |
965 LOperand* right = | 881 LOperand* right = |
966 UseFixed(instr->right(), InstanceOfDescriptor::RightRegister()); | 882 UseFixed(instr->right(), InstanceOfDescriptor::RightRegister()); |
967 LOperand* context = UseFixed(instr->context(), cp); | 883 LOperand* context = UseFixed(instr->context(), cp); |
968 LInstanceOf* result = new (zone()) LInstanceOf(context, left, right); | 884 LInstanceOf* result = new (zone()) LInstanceOf(context, left, right); |
969 return MarkAsCall(DefineFixed(result, r3), instr); | 885 return MarkAsCall(DefineFixed(result, r2), instr); |
970 } | 886 } |
971 | 887 |
972 | |
973 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch( | 888 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch( |
974 HHasInPrototypeChainAndBranch* instr) { | 889 HHasInPrototypeChainAndBranch* instr) { |
975 LOperand* object = UseRegister(instr->object()); | 890 LOperand* object = UseRegister(instr->object()); |
976 LOperand* prototype = UseRegister(instr->prototype()); | 891 LOperand* prototype = UseRegister(instr->prototype()); |
977 LHasInPrototypeChainAndBranch* result = | 892 LHasInPrototypeChainAndBranch* result = |
978 new (zone()) LHasInPrototypeChainAndBranch(object, prototype); | 893 new (zone()) LHasInPrototypeChainAndBranch(object, prototype); |
979 return AssignEnvironment(result); | 894 return AssignEnvironment(result); |
980 } | 895 } |
981 | 896 |
982 | |
983 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 897 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
984 LOperand* receiver = UseRegisterAtStart(instr->receiver()); | 898 LOperand* receiver = UseRegisterAtStart(instr->receiver()); |
985 LOperand* function = UseRegisterAtStart(instr->function()); | 899 LOperand* function = UseRegisterAtStart(instr->function()); |
986 LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function); | 900 LWrapReceiver* result = new (zone()) LWrapReceiver(receiver, function); |
987 return AssignEnvironment(DefineAsRegister(result)); | 901 return AssignEnvironment(DefineAsRegister(result)); |
988 } | 902 } |
989 | 903 |
990 | |
991 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 904 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
992 LOperand* function = UseFixed(instr->function(), r4); | 905 LOperand* function = UseFixed(instr->function(), r3); |
993 LOperand* receiver = UseFixed(instr->receiver(), r3); | 906 LOperand* receiver = UseFixed(instr->receiver(), r2); |
994 LOperand* length = UseFixed(instr->length(), r5); | 907 LOperand* length = UseFixed(instr->length(), r4); |
995 LOperand* elements = UseFixed(instr->elements(), r6); | 908 LOperand* elements = UseFixed(instr->elements(), r5); |
996 LApplyArguments* result = | 909 LApplyArguments* result = |
997 new (zone()) LApplyArguments(function, receiver, length, elements); | 910 new (zone()) LApplyArguments(function, receiver, length, elements); |
998 return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY); | 911 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY); |
999 } | 912 } |
1000 | 913 |
1001 | |
1002 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) { | 914 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) { |
1003 int argc = instr->OperandCount(); | 915 int argc = instr->OperandCount(); |
1004 for (int i = 0; i < argc; ++i) { | 916 for (int i = 0; i < argc; ++i) { |
1005 LOperand* argument = Use(instr->argument(i)); | 917 LOperand* argument = Use(instr->argument(i)); |
1006 AddInstruction(new (zone()) LPushArgument(argument), instr); | 918 AddInstruction(new (zone()) LPushArgument(argument), instr); |
1007 } | 919 } |
1008 return NULL; | 920 return NULL; |
1009 } | 921 } |
1010 | 922 |
1011 | |
1012 LInstruction* LChunkBuilder::DoStoreCodeEntry( | 923 LInstruction* LChunkBuilder::DoStoreCodeEntry( |
1013 HStoreCodeEntry* store_code_entry) { | 924 HStoreCodeEntry* store_code_entry) { |
1014 LOperand* function = UseRegister(store_code_entry->function()); | 925 LOperand* function = UseRegister(store_code_entry->function()); |
1015 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); | 926 LOperand* code_object = UseTempRegister(store_code_entry->code_object()); |
1016 return new (zone()) LStoreCodeEntry(function, code_object); | 927 return new (zone()) LStoreCodeEntry(function, code_object); |
1017 } | 928 } |
1018 | 929 |
1019 | |
1020 LInstruction* LChunkBuilder::DoInnerAllocatedObject( | 930 LInstruction* LChunkBuilder::DoInnerAllocatedObject( |
1021 HInnerAllocatedObject* instr) { | 931 HInnerAllocatedObject* instr) { |
1022 LOperand* base_object = UseRegisterAtStart(instr->base_object()); | 932 LOperand* base_object = UseRegisterAtStart(instr->base_object()); |
1023 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset()); | 933 LOperand* offset = UseRegisterOrConstantAtStart(instr->offset()); |
1024 return DefineAsRegister(new (zone()) | 934 return DefineAsRegister(new (zone()) |
1025 LInnerAllocatedObject(base_object, offset)); | 935 LInnerAllocatedObject(base_object, offset)); |
1026 } | 936 } |
1027 | 937 |
1028 | |
1029 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { | 938 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { |
1030 return instr->HasNoUses() ? NULL | 939 return instr->HasNoUses() ? NULL |
1031 : DefineAsRegister(new (zone()) LThisFunction); | 940 : DefineAsRegister(new (zone()) LThisFunction); |
1032 } | 941 } |
1033 | 942 |
1034 | |
1035 LInstruction* LChunkBuilder::DoContext(HContext* instr) { | 943 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
1036 if (instr->HasNoUses()) return NULL; | 944 if (instr->HasNoUses()) return NULL; |
1037 | 945 |
1038 if (info()->IsStub()) { | 946 if (info()->IsStub()) { |
1039 return DefineFixed(new (zone()) LContext, cp); | 947 return DefineFixed(new (zone()) LContext, cp); |
1040 } | 948 } |
1041 | 949 |
1042 return DefineAsRegister(new (zone()) LContext); | 950 return DefineAsRegister(new (zone()) LContext); |
1043 } | 951 } |
1044 | 952 |
1045 | |
1046 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { | 953 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) { |
1047 LOperand* context = UseFixed(instr->context(), cp); | 954 LOperand* context = UseFixed(instr->context(), cp); |
1048 return MarkAsCall(new (zone()) LDeclareGlobals(context), instr); | 955 return MarkAsCall(new (zone()) LDeclareGlobals(context), instr); |
1049 } | 956 } |
1050 | 957 |
1051 | |
1052 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) { | 958 LInstruction* LChunkBuilder::DoCallWithDescriptor(HCallWithDescriptor* instr) { |
1053 CallInterfaceDescriptor descriptor = instr->descriptor(); | 959 CallInterfaceDescriptor descriptor = instr->descriptor(); |
1054 | 960 |
1055 LOperand* target = UseRegisterOrConstantAtStart(instr->target()); | 961 LOperand* target = UseRegisterOrConstantAtStart(instr->target()); |
1056 ZoneList<LOperand*> ops(instr->OperandCount(), zone()); | 962 ZoneList<LOperand*> ops(instr->OperandCount(), zone()); |
1057 // Target | 963 // Target |
1058 ops.Add(target, zone()); | 964 ops.Add(target, zone()); |
1059 // Context | 965 // Context |
1060 LOperand* op = UseFixed(instr->OperandAt(1), cp); | 966 LOperand* op = UseFixed(instr->OperandAt(1), cp); |
1061 ops.Add(op, zone()); | 967 ops.Add(op, zone()); |
1062 // Other register parameters | 968 // Other register parameters |
1063 for (int i = LCallWithDescriptor::kImplicitRegisterParameterCount; | 969 for (int i = LCallWithDescriptor::kImplicitRegisterParameterCount; |
1064 i < instr->OperandCount(); i++) { | 970 i < instr->OperandCount(); i++) { |
1065 op = | 971 op = |
1066 UseFixed(instr->OperandAt(i), | 972 UseFixed(instr->OperandAt(i), |
1067 descriptor.GetRegisterParameter( | 973 descriptor.GetRegisterParameter( |
1068 i - LCallWithDescriptor::kImplicitRegisterParameterCount)); | 974 i - LCallWithDescriptor::kImplicitRegisterParameterCount)); |
1069 ops.Add(op, zone()); | 975 ops.Add(op, zone()); |
1070 } | 976 } |
1071 | 977 |
1072 LCallWithDescriptor* result = | 978 LCallWithDescriptor* result = |
1073 new (zone()) LCallWithDescriptor(descriptor, ops, zone()); | 979 new (zone()) LCallWithDescriptor(descriptor, ops, zone()); |
1074 return MarkAsCall(DefineFixed(result, r3), instr); | 980 return MarkAsCall(DefineFixed(result, r2), instr); |
1075 } | 981 } |
1076 | 982 |
1077 | |
1078 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { | 983 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) { |
1079 LOperand* context = UseFixed(instr->context(), cp); | 984 LOperand* context = UseFixed(instr->context(), cp); |
1080 LOperand* function = UseFixed(instr->function(), r4); | 985 LOperand* function = UseFixed(instr->function(), r3); |
1081 LInvokeFunction* result = new (zone()) LInvokeFunction(context, function); | 986 LInvokeFunction* result = new (zone()) LInvokeFunction(context, function); |
1082 return MarkAsCall(DefineFixed(result, r3), instr, CANNOT_DEOPTIMIZE_EAGERLY); | 987 return MarkAsCall(DefineFixed(result, r2), instr, CANNOT_DEOPTIMIZE_EAGERLY); |
1083 } | 988 } |
1084 | 989 |
1085 | |
1086 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 990 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
1087 switch (instr->op()) { | 991 switch (instr->op()) { |
1088 case kMathFloor: | 992 case kMathFloor: |
1089 return DoMathFloor(instr); | 993 return DoMathFloor(instr); |
1090 case kMathRound: | 994 case kMathRound: |
1091 return DoMathRound(instr); | 995 return DoMathRound(instr); |
1092 case kMathFround: | 996 case kMathFround: |
1093 return DoMathFround(instr); | 997 return DoMathFround(instr); |
1094 case kMathAbs: | 998 case kMathAbs: |
1095 return DoMathAbs(instr); | 999 return DoMathAbs(instr); |
1096 case kMathLog: | 1000 case kMathLog: |
1097 return DoMathLog(instr); | 1001 return DoMathLog(instr); |
1098 case kMathExp: | 1002 case kMathExp: |
1099 return DoMathExp(instr); | 1003 return DoMathExp(instr); |
1100 case kMathSqrt: | 1004 case kMathSqrt: |
1101 return DoMathSqrt(instr); | 1005 return DoMathSqrt(instr); |
1102 case kMathPowHalf: | 1006 case kMathPowHalf: |
1103 return DoMathPowHalf(instr); | 1007 return DoMathPowHalf(instr); |
1104 case kMathClz32: | 1008 case kMathClz32: |
1105 return DoMathClz32(instr); | 1009 return DoMathClz32(instr); |
1106 default: | 1010 default: |
1107 UNREACHABLE(); | 1011 UNREACHABLE(); |
1108 return NULL; | 1012 return NULL; |
1109 } | 1013 } |
1110 } | 1014 } |
1111 | 1015 |
1112 | |
1113 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1016 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
1114 LOperand* input = UseRegister(instr->value()); | 1017 LOperand* input = UseRegister(instr->value()); |
1115 LMathFloor* result = new (zone()) LMathFloor(input); | 1018 LMathFloor* result = new (zone()) LMathFloor(input); |
1116 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1019 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
1117 } | 1020 } |
1118 | 1021 |
1119 | |
1120 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { | 1022 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { |
1121 LOperand* input = UseRegister(instr->value()); | 1023 LOperand* input = UseRegister(instr->value()); |
1122 LOperand* temp = TempDoubleRegister(); | 1024 LOperand* temp = TempDoubleRegister(); |
1123 LMathRound* result = new (zone()) LMathRound(input, temp); | 1025 LMathRound* result = new (zone()) LMathRound(input, temp); |
1124 return AssignEnvironment(DefineAsRegister(result)); | 1026 return AssignEnvironment(DefineAsRegister(result)); |
1125 } | 1027 } |
1126 | 1028 |
1127 | |
1128 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) { | 1029 LInstruction* LChunkBuilder::DoMathFround(HUnaryMathOperation* instr) { |
1129 LOperand* input = UseRegister(instr->value()); | 1030 LOperand* input = UseRegister(instr->value()); |
1130 LMathFround* result = new (zone()) LMathFround(input); | 1031 LMathFround* result = new (zone()) LMathFround(input); |
1131 return DefineAsRegister(result); | 1032 return DefineAsRegister(result); |
1132 } | 1033 } |
1133 | 1034 |
1134 | |
1135 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { | 1035 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
1136 Representation r = instr->value()->representation(); | 1036 Representation r = instr->value()->representation(); |
1137 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) | 1037 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) |
1138 ? NULL | 1038 ? NULL |
1139 : UseFixed(instr->context(), cp); | 1039 : UseFixed(instr->context(), cp); |
1140 LOperand* input = UseRegister(instr->value()); | 1040 LOperand* input = UseRegister(instr->value()); |
1141 LInstruction* result = | 1041 LInstruction* result = |
1142 DefineAsRegister(new (zone()) LMathAbs(context, input)); | 1042 DefineAsRegister(new (zone()) LMathAbs(context, input)); |
1143 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); | 1043 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
1144 if (!r.IsDouble()) result = AssignEnvironment(result); | 1044 if (!r.IsDouble()) result = AssignEnvironment(result); |
1145 return result; | 1045 return result; |
1146 } | 1046 } |
1147 | 1047 |
1148 | |
1149 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1048 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
1150 DCHECK(instr->representation().IsDouble()); | 1049 DCHECK(instr->representation().IsDouble()); |
1151 DCHECK(instr->value()->representation().IsDouble()); | 1050 DCHECK(instr->value()->representation().IsDouble()); |
1152 LOperand* input = UseFixedDouble(instr->value(), d1); | 1051 LOperand* input = UseFixedDouble(instr->value(), d1); |
1153 return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr); | 1052 return MarkAsCall(DefineFixedDouble(new (zone()) LMathLog(input), d1), instr); |
1154 } | 1053 } |
1155 | 1054 |
1156 | |
1157 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { | 1055 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { |
1158 LOperand* input = UseRegisterAtStart(instr->value()); | 1056 LOperand* input = UseRegisterAtStart(instr->value()); |
1159 LMathClz32* result = new (zone()) LMathClz32(input); | 1057 LMathClz32* result = new (zone()) LMathClz32(input); |
1160 return DefineAsRegister(result); | 1058 return DefineAsRegister(result); |
1161 } | 1059 } |
1162 | 1060 |
1163 | |
1164 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { | 1061 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
1165 DCHECK(instr->representation().IsDouble()); | 1062 DCHECK(instr->representation().IsDouble()); |
1166 DCHECK(instr->value()->representation().IsDouble()); | 1063 DCHECK(instr->value()->representation().IsDouble()); |
1167 LOperand* input = UseRegister(instr->value()); | 1064 LOperand* input = UseRegister(instr->value()); |
1168 LOperand* temp1 = TempRegister(); | 1065 LOperand* temp1 = TempRegister(); |
1169 LOperand* temp2 = TempRegister(); | 1066 LOperand* temp2 = TempRegister(); |
1170 LOperand* double_temp = TempDoubleRegister(); | 1067 LOperand* double_temp = TempDoubleRegister(); |
1171 LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2); | 1068 LMathExp* result = new (zone()) LMathExp(input, double_temp, temp1, temp2); |
1172 return DefineAsRegister(result); | 1069 return DefineAsRegister(result); |
1173 } | 1070 } |
1174 | 1071 |
1175 | |
1176 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { | 1072 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { |
1177 LOperand* input = UseRegisterAtStart(instr->value()); | 1073 LOperand* input = UseRegisterAtStart(instr->value()); |
1178 LMathSqrt* result = new (zone()) LMathSqrt(input); | 1074 LMathSqrt* result = new (zone()) LMathSqrt(input); |
1179 return DefineAsRegister(result); | 1075 return DefineAsRegister(result); |
1180 } | 1076 } |
1181 | 1077 |
1182 | |
1183 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { | 1078 LInstruction* LChunkBuilder::DoMathPowHalf(HUnaryMathOperation* instr) { |
1184 LOperand* input = UseRegisterAtStart(instr->value()); | 1079 LOperand* input = UseRegisterAtStart(instr->value()); |
1185 LMathPowHalf* result = new (zone()) LMathPowHalf(input); | 1080 LMathPowHalf* result = new (zone()) LMathPowHalf(input); |
1186 return DefineAsRegister(result); | 1081 return DefineAsRegister(result); |
1187 } | 1082 } |
1188 | 1083 |
1189 | |
1190 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { | 1084 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) { |
1191 LOperand* context = UseFixed(instr->context(), cp); | 1085 LOperand* context = UseFixed(instr->context(), cp); |
1192 LOperand* constructor = UseFixed(instr->constructor(), r4); | 1086 LOperand* constructor = UseFixed(instr->constructor(), r3); |
1193 LCallNewArray* result = new (zone()) LCallNewArray(context, constructor); | 1087 LCallNewArray* result = new (zone()) LCallNewArray(context, constructor); |
1194 return MarkAsCall(DefineFixed(result, r3), instr); | 1088 return MarkAsCall(DefineFixed(result, r2), instr); |
1195 } | 1089 } |
1196 | 1090 |
1197 | |
1198 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { | 1091 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { |
1199 LOperand* context = UseFixed(instr->context(), cp); | 1092 LOperand* context = UseFixed(instr->context(), cp); |
1200 return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r3), instr); | 1093 return MarkAsCall(DefineFixed(new (zone()) LCallRuntime(context), r2), instr); |
1201 } | 1094 } |
1202 | 1095 |
1203 | |
1204 LInstruction* LChunkBuilder::DoRor(HRor* instr) { | 1096 LInstruction* LChunkBuilder::DoRor(HRor* instr) { |
1205 return DoShift(Token::ROR, instr); | 1097 return DoShift(Token::ROR, instr); |
1206 } | 1098 } |
1207 | 1099 |
1208 | |
1209 LInstruction* LChunkBuilder::DoShr(HShr* instr) { | 1100 LInstruction* LChunkBuilder::DoShr(HShr* instr) { |
1210 return DoShift(Token::SHR, instr); | 1101 return DoShift(Token::SHR, instr); |
1211 } | 1102 } |
1212 | 1103 |
1213 | |
1214 LInstruction* LChunkBuilder::DoSar(HSar* instr) { | 1104 LInstruction* LChunkBuilder::DoSar(HSar* instr) { |
1215 return DoShift(Token::SAR, instr); | 1105 return DoShift(Token::SAR, instr); |
1216 } | 1106 } |
1217 | 1107 |
1218 | |
1219 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1108 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
1220 return DoShift(Token::SHL, instr); | 1109 return DoShift(Token::SHL, instr); |
1221 } | 1110 } |
1222 | 1111 |
1223 | |
1224 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1112 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
1225 if (instr->representation().IsSmiOrInteger32()) { | 1113 if (instr->representation().IsSmiOrInteger32()) { |
1226 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1114 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1227 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1115 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1228 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); | 1116 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); |
1229 | 1117 |
1230 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1118 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1231 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1119 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1232 return DefineAsRegister(new (zone()) LBitI(left, right)); | 1120 return DefineAsRegister(new (zone()) LBitI(left, right)); |
1233 } else { | 1121 } else { |
1234 return DoArithmeticT(instr->op(), instr); | 1122 return DoArithmeticT(instr->op(), instr); |
1235 } | 1123 } |
1236 } | 1124 } |
1237 | 1125 |
1238 | |
1239 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { | 1126 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
1240 DCHECK(instr->representation().IsSmiOrInteger32()); | 1127 DCHECK(instr->representation().IsSmiOrInteger32()); |
1241 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1128 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1242 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1129 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1243 LOperand* dividend = UseRegister(instr->left()); | 1130 LOperand* dividend = UseRegister(instr->left()); |
1244 int32_t divisor = instr->right()->GetInteger32Constant(); | 1131 int32_t divisor = instr->right()->GetInteger32Constant(); |
1245 LInstruction* result = | 1132 LInstruction* result = |
1246 DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor)); | 1133 DefineAsRegister(new (zone()) LDivByPowerOf2I(dividend, divisor)); |
1247 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1134 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
1248 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || | 1135 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || |
1249 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1136 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1250 divisor != 1 && divisor != -1)) { | 1137 divisor != 1 && divisor != -1)) { |
1251 result = AssignEnvironment(result); | 1138 result = AssignEnvironment(result); |
1252 } | 1139 } |
1253 return result; | 1140 return result; |
1254 } | 1141 } |
1255 | 1142 |
1256 | |
1257 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { | 1143 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { |
1258 DCHECK(instr->representation().IsInteger32()); | 1144 DCHECK(instr->representation().IsInteger32()); |
1259 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1145 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1260 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1146 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1261 LOperand* dividend = UseRegister(instr->left()); | 1147 LOperand* dividend = UseRegister(instr->left()); |
1262 int32_t divisor = instr->right()->GetInteger32Constant(); | 1148 int32_t divisor = instr->right()->GetInteger32Constant(); |
1263 LInstruction* result = | 1149 LInstruction* result = |
1264 DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor)); | 1150 DefineAsRegister(new (zone()) LDivByConstI(dividend, divisor)); |
1265 if (divisor == 0 || | 1151 if (divisor == 0 || |
1266 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1152 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
1267 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1153 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1268 result = AssignEnvironment(result); | 1154 result = AssignEnvironment(result); |
1269 } | 1155 } |
1270 return result; | 1156 return result; |
1271 } | 1157 } |
1272 | 1158 |
1273 | |
1274 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { | 1159 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { |
1275 DCHECK(instr->representation().IsSmiOrInteger32()); | 1160 DCHECK(instr->representation().IsSmiOrInteger32()); |
1276 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1161 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1277 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1162 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1278 LOperand* dividend = UseRegister(instr->left()); | 1163 LOperand* dividend = UseRegister(instr->left()); |
1279 LOperand* divisor = UseRegister(instr->right()); | 1164 LOperand* divisor = UseRegister(instr->right()); |
1280 LInstruction* result = | 1165 LInstruction* result = |
1281 DefineAsRegister(new (zone()) LDivI(dividend, divisor)); | 1166 DefineAsRegister(new (zone()) LDivI(dividend, divisor)); |
1282 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1167 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
1283 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1168 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
1284 (instr->CheckFlag(HValue::kCanOverflow) && | 1169 (instr->CheckFlag(HValue::kCanOverflow) && |
1285 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) || | 1170 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) || |
1286 (!instr->IsMathFloorOfDiv() && | 1171 (!instr->IsMathFloorOfDiv() && |
1287 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1172 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
1288 result = AssignEnvironment(result); | 1173 result = AssignEnvironment(result); |
1289 } | 1174 } |
1290 return result; | 1175 return result; |
1291 } | 1176 } |
1292 | 1177 |
1293 | |
1294 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1178 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1295 if (instr->representation().IsSmiOrInteger32()) { | 1179 if (instr->representation().IsSmiOrInteger32()) { |
1296 if (instr->RightIsPowerOf2()) { | 1180 if (instr->RightIsPowerOf2()) { |
1297 return DoDivByPowerOf2I(instr); | 1181 return DoDivByPowerOf2I(instr); |
1298 } else if (instr->right()->IsConstant()) { | 1182 } else if (instr->right()->IsConstant()) { |
1299 return DoDivByConstI(instr); | 1183 return DoDivByConstI(instr); |
1300 } else { | 1184 } else { |
1301 return DoDivI(instr); | 1185 return DoDivI(instr); |
1302 } | 1186 } |
1303 } else if (instr->representation().IsDouble()) { | 1187 } else if (instr->representation().IsDouble()) { |
1304 return DoArithmeticD(Token::DIV, instr); | 1188 return DoArithmeticD(Token::DIV, instr); |
1305 } else { | 1189 } else { |
1306 return DoArithmeticT(Token::DIV, instr); | 1190 return DoArithmeticT(Token::DIV, instr); |
1307 } | 1191 } |
1308 } | 1192 } |
1309 | 1193 |
1310 | |
1311 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { | 1194 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { |
1312 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1195 LOperand* dividend = UseRegisterAtStart(instr->left()); |
1313 int32_t divisor = instr->right()->GetInteger32Constant(); | 1196 int32_t divisor = instr->right()->GetInteger32Constant(); |
1314 LInstruction* result = | 1197 LInstruction* result = |
1315 DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor)); | 1198 DefineAsRegister(new (zone()) LFlooringDivByPowerOf2I(dividend, divisor)); |
1316 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1199 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
1317 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { | 1200 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { |
1318 result = AssignEnvironment(result); | 1201 result = AssignEnvironment(result); |
1319 } | 1202 } |
1320 return result; | 1203 return result; |
1321 } | 1204 } |
1322 | 1205 |
1323 | |
1324 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { | 1206 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
1325 DCHECK(instr->representation().IsInteger32()); | 1207 DCHECK(instr->representation().IsInteger32()); |
1326 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1208 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1327 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1209 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1328 LOperand* dividend = UseRegister(instr->left()); | 1210 LOperand* dividend = UseRegister(instr->left()); |
1329 int32_t divisor = instr->right()->GetInteger32Constant(); | 1211 int32_t divisor = instr->right()->GetInteger32Constant(); |
1330 LOperand* temp = | 1212 LOperand* temp = |
1331 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || | 1213 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || |
1332 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) | 1214 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) |
1333 ? NULL | 1215 ? NULL |
1334 : TempRegister(); | 1216 : TempRegister(); |
1335 LInstruction* result = DefineAsRegister( | 1217 LInstruction* result = DefineAsRegister( |
1336 new (zone()) LFlooringDivByConstI(dividend, divisor, temp)); | 1218 new (zone()) LFlooringDivByConstI(dividend, divisor, temp)); |
1337 if (divisor == 0 || | 1219 if (divisor == 0 || |
1338 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { | 1220 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { |
1339 result = AssignEnvironment(result); | 1221 result = AssignEnvironment(result); |
1340 } | 1222 } |
1341 return result; | 1223 return result; |
1342 } | 1224 } |
1343 | 1225 |
1344 | |
1345 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { | 1226 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { |
1346 DCHECK(instr->representation().IsSmiOrInteger32()); | 1227 DCHECK(instr->representation().IsSmiOrInteger32()); |
1347 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1228 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1348 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1229 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1349 LOperand* dividend = UseRegister(instr->left()); | 1230 LOperand* dividend = UseRegister(instr->left()); |
1350 LOperand* divisor = UseRegister(instr->right()); | 1231 LOperand* divisor = UseRegister(instr->right()); |
1351 LInstruction* result = | 1232 LInstruction* result = |
1352 DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor)); | 1233 DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor)); |
1353 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1234 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
1354 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1235 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
1355 (instr->CheckFlag(HValue::kCanOverflow) && | 1236 (instr->CheckFlag(HValue::kCanOverflow) && |
1356 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1237 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
1357 result = AssignEnvironment(result); | 1238 result = AssignEnvironment(result); |
1358 } | 1239 } |
1359 return result; | 1240 return result; |
1360 } | 1241 } |
1361 | 1242 |
1362 | |
1363 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1243 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
1364 if (instr->RightIsPowerOf2()) { | 1244 if (instr->RightIsPowerOf2()) { |
1365 return DoFlooringDivByPowerOf2I(instr); | 1245 return DoFlooringDivByPowerOf2I(instr); |
1366 } else if (instr->right()->IsConstant()) { | 1246 } else if (instr->right()->IsConstant()) { |
1367 return DoFlooringDivByConstI(instr); | 1247 return DoFlooringDivByConstI(instr); |
1368 } else { | 1248 } else { |
1369 return DoFlooringDivI(instr); | 1249 return DoFlooringDivI(instr); |
1370 } | 1250 } |
1371 } | 1251 } |
1372 | 1252 |
1373 | |
1374 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { | 1253 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
1375 DCHECK(instr->representation().IsSmiOrInteger32()); | 1254 DCHECK(instr->representation().IsSmiOrInteger32()); |
1376 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1255 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1377 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1256 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1378 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1257 LOperand* dividend = UseRegisterAtStart(instr->left()); |
1379 int32_t divisor = instr->right()->GetInteger32Constant(); | 1258 int32_t divisor = instr->right()->GetInteger32Constant(); |
1380 LInstruction* result = | 1259 LInstruction* result = |
1381 DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor)); | 1260 DefineSameAsFirst(new (zone()) LModByPowerOf2I(dividend, divisor)); |
1382 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && | 1261 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && |
1383 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1262 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1384 result = AssignEnvironment(result); | 1263 result = AssignEnvironment(result); |
1385 } | 1264 } |
1386 return result; | 1265 return result; |
1387 } | 1266 } |
1388 | 1267 |
1389 | |
1390 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { | 1268 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { |
1391 DCHECK(instr->representation().IsSmiOrInteger32()); | 1269 DCHECK(instr->representation().IsSmiOrInteger32()); |
1392 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1270 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1393 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1271 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1394 LOperand* dividend = UseRegister(instr->left()); | 1272 LOperand* dividend = UseRegister(instr->left()); |
1395 int32_t divisor = instr->right()->GetInteger32Constant(); | 1273 int32_t divisor = instr->right()->GetInteger32Constant(); |
1396 LInstruction* result = | 1274 LInstruction* result = |
1397 DefineAsRegister(new (zone()) LModByConstI(dividend, divisor)); | 1275 DefineAsRegister(new (zone()) LModByConstI(dividend, divisor)); |
1398 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1276 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1399 result = AssignEnvironment(result); | 1277 result = AssignEnvironment(result); |
1400 } | 1278 } |
1401 return result; | 1279 return result; |
1402 } | 1280 } |
1403 | 1281 |
1404 | |
1405 LInstruction* LChunkBuilder::DoModI(HMod* instr) { | 1282 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
1406 DCHECK(instr->representation().IsSmiOrInteger32()); | 1283 DCHECK(instr->representation().IsSmiOrInteger32()); |
1407 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1284 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1408 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1285 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1409 LOperand* dividend = UseRegister(instr->left()); | 1286 LOperand* dividend = UseRegister(instr->left()); |
1410 LOperand* divisor = UseRegister(instr->right()); | 1287 LOperand* divisor = UseRegister(instr->right()); |
1411 LInstruction* result = | 1288 LInstruction* result = |
1412 DefineAsRegister(new (zone()) LModI(dividend, divisor)); | 1289 DefineAsRegister(new (zone()) LModI(dividend, divisor)); |
1413 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1290 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
1414 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1291 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1415 result = AssignEnvironment(result); | 1292 result = AssignEnvironment(result); |
1416 } | 1293 } |
1417 return result; | 1294 return result; |
1418 } | 1295 } |
1419 | 1296 |
1420 | |
1421 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1297 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
1422 if (instr->representation().IsSmiOrInteger32()) { | 1298 if (instr->representation().IsSmiOrInteger32()) { |
1423 if (instr->RightIsPowerOf2()) { | 1299 if (instr->RightIsPowerOf2()) { |
1424 return DoModByPowerOf2I(instr); | 1300 return DoModByPowerOf2I(instr); |
1425 } else if (instr->right()->IsConstant()) { | 1301 } else if (instr->right()->IsConstant()) { |
1426 return DoModByConstI(instr); | 1302 return DoModByConstI(instr); |
1427 } else { | 1303 } else { |
1428 return DoModI(instr); | 1304 return DoModI(instr); |
1429 } | 1305 } |
1430 } else if (instr->representation().IsDouble()) { | 1306 } else if (instr->representation().IsDouble()) { |
1431 return DoArithmeticD(Token::MOD, instr); | 1307 return DoArithmeticD(Token::MOD, instr); |
1432 } else { | 1308 } else { |
1433 return DoArithmeticT(Token::MOD, instr); | 1309 return DoArithmeticT(Token::MOD, instr); |
1434 } | 1310 } |
1435 } | 1311 } |
1436 | 1312 |
1437 | |
1438 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1313 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1439 if (instr->representation().IsSmiOrInteger32()) { | 1314 if (instr->representation().IsSmiOrInteger32()) { |
1440 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1315 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1441 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1316 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1442 HValue* left = instr->BetterLeftOperand(); | 1317 HValue* left = instr->BetterLeftOperand(); |
1443 HValue* right = instr->BetterRightOperand(); | 1318 HValue* right = instr->BetterRightOperand(); |
1444 LOperand* left_op; | 1319 LOperand* left_op; |
1445 LOperand* right_op; | 1320 LOperand* right_op; |
1446 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); | 1321 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
1447 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); | 1322 bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 } | 1355 } |
1481 return DefineAsRegister(mul); | 1356 return DefineAsRegister(mul); |
1482 | 1357 |
1483 } else if (instr->representation().IsDouble()) { | 1358 } else if (instr->representation().IsDouble()) { |
1484 return DoArithmeticD(Token::MUL, instr); | 1359 return DoArithmeticD(Token::MUL, instr); |
1485 } else { | 1360 } else { |
1486 return DoArithmeticT(Token::MUL, instr); | 1361 return DoArithmeticT(Token::MUL, instr); |
1487 } | 1362 } |
1488 } | 1363 } |
1489 | 1364 |
1490 | |
1491 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1365 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
1492 if (instr->representation().IsSmiOrInteger32()) { | 1366 if (instr->representation().IsSmiOrInteger32()) { |
1493 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1367 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1494 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1368 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1495 | 1369 |
1496 if (instr->left()->IsConstant() && | 1370 if (instr->left()->IsConstant() && |
1497 !instr->CheckFlag(HValue::kCanOverflow)) { | 1371 !instr->CheckFlag(HValue::kCanOverflow)) { |
1498 // If lhs is constant, do reverse subtraction instead. | 1372 // If lhs is constant, do reverse subtraction instead. |
1499 return DoRSub(instr); | 1373 return DoRSub(instr); |
1500 } | 1374 } |
1501 | 1375 |
1502 LOperand* left = UseRegisterAtStart(instr->left()); | 1376 LOperand* left = UseRegisterAtStart(instr->left()); |
1503 LOperand* right = UseOrConstantAtStart(instr->right()); | 1377 LOperand* right = UseOrConstantAtStart(instr->right()); |
1504 LSubI* sub = new (zone()) LSubI(left, right); | 1378 LSubI* sub = new (zone()) LSubI(left, right); |
1505 LInstruction* result = DefineAsRegister(sub); | 1379 LInstruction* result = DefineAsRegister(sub); |
1506 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1380 if (instr->CheckFlag(HValue::kCanOverflow)) { |
1507 result = AssignEnvironment(result); | 1381 result = AssignEnvironment(result); |
1508 } | 1382 } |
1509 return result; | 1383 return result; |
1510 } else if (instr->representation().IsDouble()) { | 1384 } else if (instr->representation().IsDouble()) { |
1511 return DoArithmeticD(Token::SUB, instr); | 1385 return DoArithmeticD(Token::SUB, instr); |
1512 } else { | 1386 } else { |
1513 return DoArithmeticT(Token::SUB, instr); | 1387 return DoArithmeticT(Token::SUB, instr); |
1514 } | 1388 } |
1515 } | 1389 } |
1516 | 1390 |
1517 | |
1518 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { | 1391 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { |
1519 DCHECK(instr->representation().IsSmiOrInteger32()); | 1392 DCHECK(instr->representation().IsSmiOrInteger32()); |
1520 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1393 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1521 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1394 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1522 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); | 1395 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); |
1523 | 1396 |
1524 // Note: The lhs of the subtraction becomes the rhs of the | 1397 // Note: The lhs of the subtraction becomes the rhs of the |
1525 // reverse-subtraction. | 1398 // reverse-subtraction. |
1526 LOperand* left = UseRegisterAtStart(instr->right()); | 1399 LOperand* left = UseRegisterAtStart(instr->right()); |
1527 LOperand* right = UseOrConstantAtStart(instr->left()); | 1400 LOperand* right = UseOrConstantAtStart(instr->left()); |
1528 LRSubI* rsb = new (zone()) LRSubI(left, right); | 1401 LRSubI* rsb = new (zone()) LRSubI(left, right); |
1529 LInstruction* result = DefineAsRegister(rsb); | 1402 LInstruction* result = DefineAsRegister(rsb); |
1530 return result; | 1403 return result; |
1531 } | 1404 } |
1532 | 1405 |
1533 | |
1534 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { | 1406 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) { |
1535 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | 1407 LOperand* multiplier_op = UseRegister(mul->left()); |
1536 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | 1408 LOperand* multiplicand_op = UseRegister(mul->right()); |
1537 LOperand* addend_op = UseRegisterAtStart(addend); | 1409 LOperand* addend_op = UseRegister(addend); |
1538 return DefineSameAsFirst( | 1410 return DefineAsRegister( |
1539 new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op)); | 1411 new (zone()) LMultiplyAddD(addend_op, multiplier_op, multiplicand_op)); |
1540 } | 1412 } |
1541 | 1413 |
| 1414 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) { |
| 1415 LOperand* minuend_op = UseRegister(minuend); |
| 1416 LOperand* multiplier_op = UseRegister(mul->left()); |
| 1417 LOperand* multiplicand_op = UseRegister(mul->right()); |
1542 | 1418 |
1543 LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) { | 1419 return DefineAsRegister( |
1544 LOperand* minuend_op = UseRegisterAtStart(minuend); | |
1545 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | |
1546 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | |
1547 | |
1548 return DefineSameAsFirst( | |
1549 new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op)); | 1420 new (zone()) LMultiplySubD(minuend_op, multiplier_op, multiplicand_op)); |
1550 } | 1421 } |
1551 | 1422 |
1552 | |
1553 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1423 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
1554 if (instr->representation().IsSmiOrInteger32()) { | 1424 if (instr->representation().IsSmiOrInteger32()) { |
1555 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1425 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1556 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1426 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1557 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1427 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1558 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1428 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1559 LAddI* add = new (zone()) LAddI(left, right); | 1429 LAddI* add = new (zone()) LAddI(left, right); |
1560 LInstruction* result = DefineAsRegister(add); | 1430 LInstruction* result = DefineAsRegister(add); |
1561 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1431 if (instr->CheckFlag(HValue::kCanOverflow)) { |
1562 result = AssignEnvironment(result); | 1432 result = AssignEnvironment(result); |
1563 } | 1433 } |
1564 return result; | 1434 return result; |
1565 } else if (instr->representation().IsExternal()) { | 1435 } else if (instr->representation().IsExternal()) { |
1566 DCHECK(instr->IsConsistentExternalRepresentation()); | 1436 DCHECK(instr->IsConsistentExternalRepresentation()); |
1567 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); | 1437 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); |
1568 LOperand* left = UseRegisterAtStart(instr->left()); | 1438 LOperand* left = UseRegisterAtStart(instr->left()); |
1569 LOperand* right = UseOrConstantAtStart(instr->right()); | 1439 LOperand* right = UseOrConstantAtStart(instr->right()); |
1570 LAddI* add = new (zone()) LAddI(left, right); | 1440 LAddI* add = new (zone()) LAddI(left, right); |
1571 LInstruction* result = DefineAsRegister(add); | 1441 LInstruction* result = DefineAsRegister(add); |
1572 return result; | 1442 return result; |
1573 } else if (instr->representation().IsDouble()) { | 1443 } else if (instr->representation().IsDouble()) { |
1574 return DoArithmeticD(Token::ADD, instr); | 1444 return DoArithmeticD(Token::ADD, instr); |
1575 } else { | 1445 } else { |
1576 return DoArithmeticT(Token::ADD, instr); | 1446 return DoArithmeticT(Token::ADD, instr); |
1577 } | 1447 } |
1578 } | 1448 } |
1579 | 1449 |
1580 | |
1581 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1450 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
1582 LOperand* left = NULL; | 1451 LOperand* left = NULL; |
1583 LOperand* right = NULL; | 1452 LOperand* right = NULL; |
1584 if (instr->representation().IsSmiOrInteger32()) { | 1453 if (instr->representation().IsSmiOrInteger32()) { |
1585 DCHECK(instr->left()->representation().Equals(instr->representation())); | 1454 DCHECK(instr->left()->representation().Equals(instr->representation())); |
1586 DCHECK(instr->right()->representation().Equals(instr->representation())); | 1455 DCHECK(instr->right()->representation().Equals(instr->representation())); |
1587 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1456 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1588 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1457 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1589 } else { | 1458 } else { |
1590 DCHECK(instr->representation().IsDouble()); | 1459 DCHECK(instr->representation().IsDouble()); |
1591 DCHECK(instr->left()->representation().IsDouble()); | 1460 DCHECK(instr->left()->representation().IsDouble()); |
1592 DCHECK(instr->right()->representation().IsDouble()); | 1461 DCHECK(instr->right()->representation().IsDouble()); |
1593 left = UseRegisterAtStart(instr->left()); | 1462 left = UseRegister(instr->left()); |
1594 right = UseRegisterAtStart(instr->right()); | 1463 right = UseRegister(instr->right()); |
1595 } | 1464 } |
1596 return DefineAsRegister(new (zone()) LMathMinMax(left, right)); | 1465 return DefineAsRegister(new (zone()) LMathMinMax(left, right)); |
1597 } | 1466 } |
1598 | 1467 |
1599 | |
1600 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1468 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
1601 DCHECK(instr->representation().IsDouble()); | 1469 DCHECK(instr->representation().IsDouble()); |
1602 // We call a C function for double power. It can't trigger a GC. | 1470 // We call a C function for double power. It can't trigger a GC. |
1603 // We need to use fixed result register for the call. | 1471 // We need to use fixed result register for the call. |
1604 Representation exponent_type = instr->right()->representation(); | 1472 Representation exponent_type = instr->right()->representation(); |
1605 DCHECK(instr->left()->representation().IsDouble()); | 1473 DCHECK(instr->left()->representation().IsDouble()); |
1606 LOperand* left = UseFixedDouble(instr->left(), d1); | 1474 LOperand* left = UseFixedDouble(instr->left(), d1); |
1607 LOperand* right = | 1475 LOperand* right = exponent_type.IsDouble() |
1608 exponent_type.IsDouble() | 1476 ? UseFixedDouble(instr->right(), d2) |
1609 ? UseFixedDouble(instr->right(), d2) | 1477 : UseFixed(instr->right(), r4); |
1610 : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent()); | |
1611 LPower* result = new (zone()) LPower(left, right); | 1478 LPower* result = new (zone()) LPower(left, right); |
1612 return MarkAsCall(DefineFixedDouble(result, d3), instr, | 1479 return MarkAsCall(DefineFixedDouble(result, d3), instr, |
1613 CAN_DEOPTIMIZE_EAGERLY); | 1480 CAN_DEOPTIMIZE_EAGERLY); |
1614 } | 1481 } |
1615 | 1482 |
1616 | |
1617 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { | 1483 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
1618 DCHECK(instr->left()->representation().IsTagged()); | 1484 DCHECK(instr->left()->representation().IsTagged()); |
1619 DCHECK(instr->right()->representation().IsTagged()); | 1485 DCHECK(instr->right()->representation().IsTagged()); |
1620 LOperand* context = UseFixed(instr->context(), cp); | 1486 LOperand* context = UseFixed(instr->context(), cp); |
1621 LOperand* left = UseFixed(instr->left(), r4); | 1487 LOperand* left = UseFixed(instr->left(), r3); |
1622 LOperand* right = UseFixed(instr->right(), r3); | 1488 LOperand* right = UseFixed(instr->right(), r2); |
1623 LCmpT* result = new (zone()) LCmpT(context, left, right); | 1489 LCmpT* result = new (zone()) LCmpT(context, left, right); |
1624 return MarkAsCall(DefineFixed(result, r3), instr); | 1490 return MarkAsCall(DefineFixed(result, r2), instr); |
1625 } | 1491 } |
1626 | 1492 |
1627 | |
1628 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( | 1493 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( |
1629 HCompareNumericAndBranch* instr) { | 1494 HCompareNumericAndBranch* instr) { |
1630 Representation r = instr->representation(); | 1495 Representation r = instr->representation(); |
1631 if (r.IsSmiOrInteger32()) { | 1496 if (r.IsSmiOrInteger32()) { |
1632 DCHECK(instr->left()->representation().Equals(r)); | 1497 DCHECK(instr->left()->representation().Equals(r)); |
1633 DCHECK(instr->right()->representation().Equals(r)); | 1498 DCHECK(instr->right()->representation().Equals(r)); |
1634 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); | 1499 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); |
1635 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); | 1500 LOperand* right = UseRegisterOrConstantAtStart(instr->right()); |
1636 return new (zone()) LCompareNumericAndBranch(left, right); | 1501 return new (zone()) LCompareNumericAndBranch(left, right); |
1637 } else { | 1502 } else { |
1638 DCHECK(r.IsDouble()); | 1503 DCHECK(r.IsDouble()); |
1639 DCHECK(instr->left()->representation().IsDouble()); | 1504 DCHECK(instr->left()->representation().IsDouble()); |
1640 DCHECK(instr->right()->representation().IsDouble()); | 1505 DCHECK(instr->right()->representation().IsDouble()); |
1641 LOperand* left = UseRegisterAtStart(instr->left()); | 1506 LOperand* left = UseRegisterAtStart(instr->left()); |
1642 LOperand* right = UseRegisterAtStart(instr->right()); | 1507 LOperand* right = UseRegisterAtStart(instr->right()); |
1643 return new (zone()) LCompareNumericAndBranch(left, right); | 1508 return new (zone()) LCompareNumericAndBranch(left, right); |
1644 } | 1509 } |
1645 } | 1510 } |
1646 | 1511 |
1647 | |
1648 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1512 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
1649 HCompareObjectEqAndBranch* instr) { | 1513 HCompareObjectEqAndBranch* instr) { |
1650 LOperand* left = UseRegisterAtStart(instr->left()); | 1514 LOperand* left = UseRegisterAtStart(instr->left()); |
1651 LOperand* right = UseRegisterAtStart(instr->right()); | 1515 LOperand* right = UseRegisterAtStart(instr->right()); |
1652 return new (zone()) LCmpObjectEqAndBranch(left, right); | 1516 return new (zone()) LCmpObjectEqAndBranch(left, right); |
1653 } | 1517 } |
1654 | 1518 |
1655 | |
1656 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( | 1519 LInstruction* LChunkBuilder::DoCompareHoleAndBranch( |
1657 HCompareHoleAndBranch* instr) { | 1520 HCompareHoleAndBranch* instr) { |
1658 LOperand* value = UseRegisterAtStart(instr->value()); | 1521 LOperand* value = UseRegisterAtStart(instr->value()); |
1659 return new (zone()) LCmpHoleAndBranch(value); | 1522 return new (zone()) LCmpHoleAndBranch(value); |
1660 } | 1523 } |
1661 | 1524 |
1662 | |
1663 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1525 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
1664 DCHECK(instr->value()->representation().IsTagged()); | 1526 DCHECK(instr->value()->representation().IsTagged()); |
1665 LOperand* value = UseRegisterAtStart(instr->value()); | 1527 LOperand* value = UseRegisterAtStart(instr->value()); |
1666 LOperand* temp = TempRegister(); | 1528 LOperand* temp = TempRegister(); |
1667 return new (zone()) LIsStringAndBranch(value, temp); | 1529 return new (zone()) LIsStringAndBranch(value, temp); |
1668 } | 1530 } |
1669 | 1531 |
1670 | |
1671 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { | 1532 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { |
1672 DCHECK(instr->value()->representation().IsTagged()); | 1533 DCHECK(instr->value()->representation().IsTagged()); |
1673 return new (zone()) LIsSmiAndBranch(Use(instr->value())); | 1534 return new (zone()) LIsSmiAndBranch(Use(instr->value())); |
1674 } | 1535 } |
1675 | 1536 |
1676 | |
1677 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( | 1537 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( |
1678 HIsUndetectableAndBranch* instr) { | 1538 HIsUndetectableAndBranch* instr) { |
1679 DCHECK(instr->value()->representation().IsTagged()); | 1539 DCHECK(instr->value()->representation().IsTagged()); |
1680 LOperand* value = UseRegisterAtStart(instr->value()); | 1540 LOperand* value = UseRegisterAtStart(instr->value()); |
1681 return new (zone()) LIsUndetectableAndBranch(value, TempRegister()); | 1541 return new (zone()) LIsUndetectableAndBranch(value, TempRegister()); |
1682 } | 1542 } |
1683 | 1543 |
1684 | |
1685 LInstruction* LChunkBuilder::DoStringCompareAndBranch( | 1544 LInstruction* LChunkBuilder::DoStringCompareAndBranch( |
1686 HStringCompareAndBranch* instr) { | 1545 HStringCompareAndBranch* instr) { |
1687 DCHECK(instr->left()->representation().IsTagged()); | 1546 DCHECK(instr->left()->representation().IsTagged()); |
1688 DCHECK(instr->right()->representation().IsTagged()); | 1547 DCHECK(instr->right()->representation().IsTagged()); |
1689 LOperand* context = UseFixed(instr->context(), cp); | 1548 LOperand* context = UseFixed(instr->context(), cp); |
1690 LOperand* left = UseFixed(instr->left(), r4); | 1549 LOperand* left = UseFixed(instr->left(), r3); |
1691 LOperand* right = UseFixed(instr->right(), r3); | 1550 LOperand* right = UseFixed(instr->right(), r2); |
1692 LStringCompareAndBranch* result = | 1551 LStringCompareAndBranch* result = |
1693 new (zone()) LStringCompareAndBranch(context, left, right); | 1552 new (zone()) LStringCompareAndBranch(context, left, right); |
1694 return MarkAsCall(result, instr); | 1553 return MarkAsCall(result, instr); |
1695 } | 1554 } |
1696 | 1555 |
1697 | |
1698 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( | 1556 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( |
1699 HHasInstanceTypeAndBranch* instr) { | 1557 HHasInstanceTypeAndBranch* instr) { |
1700 DCHECK(instr->value()->representation().IsTagged()); | 1558 DCHECK(instr->value()->representation().IsTagged()); |
1701 LOperand* value = UseRegisterAtStart(instr->value()); | 1559 LOperand* value = UseRegisterAtStart(instr->value()); |
1702 return new (zone()) LHasInstanceTypeAndBranch(value); | 1560 return new (zone()) LHasInstanceTypeAndBranch(value); |
1703 } | 1561 } |
1704 | 1562 |
1705 | |
1706 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( | 1563 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
1707 HGetCachedArrayIndex* instr) { | 1564 HGetCachedArrayIndex* instr) { |
1708 DCHECK(instr->value()->representation().IsTagged()); | 1565 DCHECK(instr->value()->representation().IsTagged()); |
1709 LOperand* value = UseRegisterAtStart(instr->value()); | 1566 LOperand* value = UseRegisterAtStart(instr->value()); |
1710 | 1567 |
1711 return DefineAsRegister(new (zone()) LGetCachedArrayIndex(value)); | 1568 return DefineAsRegister(new (zone()) LGetCachedArrayIndex(value)); |
1712 } | 1569 } |
1713 | 1570 |
1714 | |
1715 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( | 1571 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( |
1716 HHasCachedArrayIndexAndBranch* instr) { | 1572 HHasCachedArrayIndexAndBranch* instr) { |
1717 DCHECK(instr->value()->representation().IsTagged()); | 1573 DCHECK(instr->value()->representation().IsTagged()); |
1718 return new (zone()) | 1574 return new (zone()) |
1719 LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value())); | 1575 LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value())); |
1720 } | 1576 } |
1721 | 1577 |
1722 | |
1723 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( | 1578 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
1724 HClassOfTestAndBranch* instr) { | 1579 HClassOfTestAndBranch* instr) { |
1725 DCHECK(instr->value()->representation().IsTagged()); | 1580 DCHECK(instr->value()->representation().IsTagged()); |
1726 LOperand* value = UseRegister(instr->value()); | 1581 LOperand* value = UseRegister(instr->value()); |
1727 return new (zone()) LClassOfTestAndBranch(value, TempRegister()); | 1582 return new (zone()) LClassOfTestAndBranch(value, TempRegister()); |
1728 } | 1583 } |
1729 | 1584 |
1730 | |
1731 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { | 1585 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { |
1732 LOperand* string = UseRegisterAtStart(instr->string()); | 1586 LOperand* string = UseRegisterAtStart(instr->string()); |
1733 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 1587 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
1734 return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index)); | 1588 return DefineAsRegister(new (zone()) LSeqStringGetChar(string, index)); |
1735 } | 1589 } |
1736 | 1590 |
1737 | |
1738 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { | 1591 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { |
1739 LOperand* string = UseRegisterAtStart(instr->string()); | 1592 LOperand* string = UseRegisterAtStart(instr->string()); |
1740 LOperand* index = FLAG_debug_code | 1593 LOperand* index = FLAG_debug_code |
1741 ? UseRegisterAtStart(instr->index()) | 1594 ? UseRegisterAtStart(instr->index()) |
1742 : UseRegisterOrConstantAtStart(instr->index()); | 1595 : UseRegisterOrConstantAtStart(instr->index()); |
1743 LOperand* value = UseRegisterAtStart(instr->value()); | 1596 LOperand* value = UseRegisterAtStart(instr->value()); |
1744 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; | 1597 LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL; |
1745 return new (zone()) LSeqStringSetChar(context, string, index, value); | 1598 return new (zone()) LSeqStringSetChar(context, string, index, value); |
1746 } | 1599 } |
1747 | 1600 |
1748 | |
1749 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1601 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
1750 if (!FLAG_debug_code && instr->skip_check()) return NULL; | 1602 if (!FLAG_debug_code && instr->skip_check()) return NULL; |
1751 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 1603 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
1752 LOperand* length = !index->IsConstantOperand() | 1604 LOperand* length = !index->IsConstantOperand() |
1753 ? UseRegisterOrConstantAtStart(instr->length()) | 1605 ? UseRegisterOrConstantAtStart(instr->length()) |
1754 : UseRegisterAtStart(instr->length()); | 1606 : UseRegisterAtStart(instr->length()); |
1755 LInstruction* result = new (zone()) LBoundsCheck(index, length); | 1607 LInstruction* result = new (zone()) LBoundsCheck(index, length); |
1756 if (!FLAG_debug_code || !instr->skip_check()) { | 1608 if (!FLAG_debug_code || !instr->skip_check()) { |
1757 result = AssignEnvironment(result); | 1609 result = AssignEnvironment(result); |
1758 } | 1610 } |
1759 return result; | 1611 return result; |
1760 } | 1612 } |
1761 | 1613 |
1762 | |
1763 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation( | 1614 LInstruction* LChunkBuilder::DoBoundsCheckBaseIndexInformation( |
1764 HBoundsCheckBaseIndexInformation* instr) { | 1615 HBoundsCheckBaseIndexInformation* instr) { |
1765 UNREACHABLE(); | 1616 UNREACHABLE(); |
1766 return NULL; | 1617 return NULL; |
1767 } | 1618 } |
1768 | 1619 |
1769 | |
1770 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1620 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
1771 // The control instruction marking the end of a block that completed | 1621 // The control instruction marking the end of a block that completed |
1772 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1622 // abruptly (e.g., threw an exception). There is nothing specific to do. |
1773 return NULL; | 1623 return NULL; |
1774 } | 1624 } |
1775 | 1625 |
1776 | |
1777 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; } | 1626 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { return NULL; } |
1778 | 1627 |
1779 | |
1780 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1628 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
1781 // All HForceRepresentation instructions should be eliminated in the | 1629 // All HForceRepresentation instructions should be eliminated in the |
1782 // representation change phase of Hydrogen. | 1630 // representation change phase of Hydrogen. |
1783 UNREACHABLE(); | 1631 UNREACHABLE(); |
1784 return NULL; | 1632 return NULL; |
1785 } | 1633 } |
1786 | 1634 |
1787 | |
1788 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1635 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
1789 Representation from = instr->from(); | 1636 Representation from = instr->from(); |
1790 Representation to = instr->to(); | 1637 Representation to = instr->to(); |
1791 HValue* val = instr->value(); | 1638 HValue* val = instr->value(); |
1792 if (from.IsSmi()) { | 1639 if (from.IsSmi()) { |
1793 if (to.IsTagged()) { | 1640 if (to.IsTagged()) { |
1794 LOperand* value = UseRegister(val); | 1641 LOperand* value = UseRegister(val); |
1795 return DefineSameAsFirst(new (zone()) LDummyUse(value)); | 1642 return DefineSameAsFirst(new (zone()) LDummyUse(value)); |
1796 } | 1643 } |
1797 from = Representation::Tagged(); | 1644 from = Representation::Tagged(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1877 return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val))); | 1724 return DefineAsRegister(new (zone()) LUint32ToDouble(UseRegister(val))); |
1878 } else { | 1725 } else { |
1879 return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val))); | 1726 return DefineAsRegister(new (zone()) LInteger32ToDouble(Use(val))); |
1880 } | 1727 } |
1881 } | 1728 } |
1882 } | 1729 } |
1883 UNREACHABLE(); | 1730 UNREACHABLE(); |
1884 return NULL; | 1731 return NULL; |
1885 } | 1732 } |
1886 | 1733 |
1887 | |
1888 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 1734 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
1889 LOperand* value = UseRegisterAtStart(instr->value()); | 1735 LOperand* value = UseRegisterAtStart(instr->value()); |
1890 LInstruction* result = new (zone()) LCheckNonSmi(value); | 1736 LInstruction* result = new (zone()) LCheckNonSmi(value); |
1891 if (!instr->value()->type().IsHeapObject()) { | 1737 if (!instr->value()->type().IsHeapObject()) { |
1892 result = AssignEnvironment(result); | 1738 result = AssignEnvironment(result); |
1893 } | 1739 } |
1894 return result; | 1740 return result; |
1895 } | 1741 } |
1896 | 1742 |
1897 | |
1898 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1743 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
1899 LOperand* value = UseRegisterAtStart(instr->value()); | 1744 LOperand* value = UseRegisterAtStart(instr->value()); |
1900 return AssignEnvironment(new (zone()) LCheckSmi(value)); | 1745 return AssignEnvironment(new (zone()) LCheckSmi(value)); |
1901 } | 1746 } |
1902 | 1747 |
1903 | |
1904 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered( | 1748 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered( |
1905 HCheckArrayBufferNotNeutered* instr) { | 1749 HCheckArrayBufferNotNeutered* instr) { |
1906 LOperand* view = UseRegisterAtStart(instr->value()); | 1750 LOperand* view = UseRegisterAtStart(instr->value()); |
1907 LCheckArrayBufferNotNeutered* result = | 1751 LCheckArrayBufferNotNeutered* result = |
1908 new (zone()) LCheckArrayBufferNotNeutered(view); | 1752 new (zone()) LCheckArrayBufferNotNeutered(view); |
1909 return AssignEnvironment(result); | 1753 return AssignEnvironment(result); |
1910 } | 1754 } |
1911 | 1755 |
1912 | |
1913 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1756 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
1914 LOperand* value = UseRegisterAtStart(instr->value()); | 1757 LOperand* value = UseRegisterAtStart(instr->value()); |
1915 LInstruction* result = new (zone()) LCheckInstanceType(value); | 1758 LInstruction* result = new (zone()) LCheckInstanceType(value); |
1916 return AssignEnvironment(result); | 1759 return AssignEnvironment(result); |
1917 } | 1760 } |
1918 | 1761 |
1919 | |
1920 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { | 1762 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { |
1921 LOperand* value = UseRegisterAtStart(instr->value()); | 1763 LOperand* value = UseRegisterAtStart(instr->value()); |
1922 return AssignEnvironment(new (zone()) LCheckValue(value)); | 1764 return AssignEnvironment(new (zone()) LCheckValue(value)); |
1923 } | 1765 } |
1924 | 1766 |
1925 | |
1926 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1767 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
1927 if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps; | 1768 if (instr->IsStabilityCheck()) return new (zone()) LCheckMaps; |
1928 LOperand* value = UseRegisterAtStart(instr->value()); | 1769 LOperand* value = UseRegisterAtStart(instr->value()); |
1929 LOperand* temp = TempRegister(); | 1770 LOperand* temp = TempRegister(); |
1930 LInstruction* result = | 1771 LInstruction* result = |
1931 AssignEnvironment(new (zone()) LCheckMaps(value, temp)); | 1772 AssignEnvironment(new (zone()) LCheckMaps(value, temp)); |
1932 if (instr->HasMigrationTarget()) { | 1773 if (instr->HasMigrationTarget()) { |
1933 info()->MarkAsDeferredCalling(); | 1774 info()->MarkAsDeferredCalling(); |
1934 result = AssignPointerMap(result); | 1775 result = AssignPointerMap(result); |
1935 } | 1776 } |
1936 return result; | 1777 return result; |
1937 } | 1778 } |
1938 | 1779 |
1939 | |
1940 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1780 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
1941 HValue* value = instr->value(); | 1781 HValue* value = instr->value(); |
1942 Representation input_rep = value->representation(); | 1782 Representation input_rep = value->representation(); |
1943 LOperand* reg = UseRegister(value); | 1783 LOperand* reg = UseRegister(value); |
1944 if (input_rep.IsDouble()) { | 1784 if (input_rep.IsDouble()) { |
1945 return DefineAsRegister(new (zone()) LClampDToUint8(reg)); | 1785 return DefineAsRegister(new (zone()) LClampDToUint8(reg)); |
1946 } else if (input_rep.IsInteger32()) { | 1786 } else if (input_rep.IsInteger32()) { |
1947 return DefineAsRegister(new (zone()) LClampIToUint8(reg)); | 1787 return DefineAsRegister(new (zone()) LClampIToUint8(reg)); |
1948 } else { | 1788 } else { |
1949 DCHECK(input_rep.IsSmiOrTagged()); | 1789 DCHECK(input_rep.IsSmiOrTagged()); |
1950 LClampTToUint8* result = | 1790 LClampTToUint8* result = |
1951 new (zone()) LClampTToUint8(reg, TempDoubleRegister()); | 1791 new (zone()) LClampTToUint8(reg, TempDoubleRegister()); |
1952 return AssignEnvironment(DefineAsRegister(result)); | 1792 return AssignEnvironment(DefineAsRegister(result)); |
1953 } | 1793 } |
1954 } | 1794 } |
1955 | 1795 |
1956 | |
1957 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { | 1796 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { |
1958 HValue* value = instr->value(); | 1797 HValue* value = instr->value(); |
1959 DCHECK(value->representation().IsDouble()); | 1798 DCHECK(value->representation().IsDouble()); |
1960 return DefineAsRegister(new (zone()) LDoubleBits(UseRegister(value))); | 1799 return DefineAsRegister(new (zone()) LDoubleBits(UseRegister(value))); |
1961 } | 1800 } |
1962 | 1801 |
1963 | |
1964 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { | 1802 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { |
1965 LOperand* lo = UseRegister(instr->lo()); | 1803 LOperand* lo = UseRegister(instr->lo()); |
1966 LOperand* hi = UseRegister(instr->hi()); | 1804 LOperand* hi = UseRegister(instr->hi()); |
1967 return DefineAsRegister(new (zone()) LConstructDouble(hi, lo)); | 1805 return DefineAsRegister(new (zone()) LConstructDouble(hi, lo)); |
1968 } | 1806 } |
1969 | 1807 |
1970 | |
1971 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1808 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
1972 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL; | 1809 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), cp) : NULL; |
1973 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); | 1810 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
1974 return new (zone()) | 1811 return new (zone()) |
1975 LReturn(UseFixed(instr->value(), r3), context, parameter_count); | 1812 LReturn(UseFixed(instr->value(), r2), context, parameter_count); |
1976 } | 1813 } |
1977 | 1814 |
1978 | |
1979 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1815 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
1980 Representation r = instr->representation(); | 1816 Representation r = instr->representation(); |
1981 if (r.IsSmi()) { | 1817 if (r.IsSmi()) { |
1982 return DefineAsRegister(new (zone()) LConstantS); | 1818 return DefineAsRegister(new (zone()) LConstantS); |
1983 } else if (r.IsInteger32()) { | 1819 } else if (r.IsInteger32()) { |
1984 return DefineAsRegister(new (zone()) LConstantI); | 1820 return DefineAsRegister(new (zone()) LConstantI); |
1985 } else if (r.IsDouble()) { | 1821 } else if (r.IsDouble()) { |
1986 return DefineAsRegister(new (zone()) LConstantD); | 1822 return DefineAsRegister(new (zone()) LConstantD); |
1987 } else if (r.IsExternal()) { | 1823 } else if (r.IsExternal()) { |
1988 return DefineAsRegister(new (zone()) LConstantE); | 1824 return DefineAsRegister(new (zone()) LConstantE); |
1989 } else if (r.IsTagged()) { | 1825 } else if (r.IsTagged()) { |
1990 return DefineAsRegister(new (zone()) LConstantT); | 1826 return DefineAsRegister(new (zone()) LConstantT); |
1991 } else { | 1827 } else { |
1992 UNREACHABLE(); | 1828 UNREACHABLE(); |
1993 return NULL; | 1829 return NULL; |
1994 } | 1830 } |
1995 } | 1831 } |
1996 | 1832 |
1997 | |
1998 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { | 1833 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) { |
1999 LOperand* context = UseFixed(instr->context(), cp); | 1834 LOperand* context = UseFixed(instr->context(), cp); |
2000 LOperand* global_object = | 1835 LOperand* global_object = |
2001 UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister()); | 1836 UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister()); |
2002 LOperand* vector = NULL; | 1837 LOperand* vector = NULL; |
2003 if (instr->HasVectorAndSlot()) { | 1838 if (instr->HasVectorAndSlot()) { |
2004 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1839 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
2005 } | 1840 } |
2006 LLoadGlobalGeneric* result = | 1841 LLoadGlobalGeneric* result = |
2007 new (zone()) LLoadGlobalGeneric(context, global_object, vector); | 1842 new (zone()) LLoadGlobalGeneric(context, global_object, vector); |
2008 return MarkAsCall(DefineFixed(result, r3), instr); | 1843 return MarkAsCall(DefineFixed(result, r2), instr); |
2009 } | 1844 } |
2010 | 1845 |
2011 | |
2012 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1846 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
2013 LOperand* context = UseRegisterAtStart(instr->value()); | 1847 LOperand* context = UseRegisterAtStart(instr->value()); |
2014 LInstruction* result = | 1848 LInstruction* result = |
2015 DefineAsRegister(new (zone()) LLoadContextSlot(context)); | 1849 DefineAsRegister(new (zone()) LLoadContextSlot(context)); |
2016 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { | 1850 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
2017 result = AssignEnvironment(result); | 1851 result = AssignEnvironment(result); |
2018 } | 1852 } |
2019 return result; | 1853 return result; |
2020 } | 1854 } |
2021 | 1855 |
2022 | |
2023 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 1856 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
2024 LOperand* context; | 1857 LOperand* context; |
2025 LOperand* value; | 1858 LOperand* value; |
2026 if (instr->NeedsWriteBarrier()) { | 1859 if (instr->NeedsWriteBarrier()) { |
2027 context = UseTempRegister(instr->context()); | 1860 context = UseTempRegister(instr->context()); |
2028 value = UseTempRegister(instr->value()); | 1861 value = UseTempRegister(instr->value()); |
2029 } else { | 1862 } else { |
2030 context = UseRegister(instr->context()); | 1863 context = UseRegister(instr->context()); |
2031 value = UseRegister(instr->value()); | 1864 value = UseRegister(instr->value()); |
2032 } | 1865 } |
2033 LInstruction* result = new (zone()) LStoreContextSlot(context, value); | 1866 LInstruction* result = new (zone()) LStoreContextSlot(context, value); |
2034 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { | 1867 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
2035 result = AssignEnvironment(result); | 1868 result = AssignEnvironment(result); |
2036 } | 1869 } |
2037 return result; | 1870 return result; |
2038 } | 1871 } |
2039 | 1872 |
2040 | |
2041 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1873 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
2042 LOperand* obj = UseRegisterAtStart(instr->object()); | 1874 LOperand* obj = UseRegisterAtStart(instr->object()); |
2043 return DefineAsRegister(new (zone()) LLoadNamedField(obj)); | 1875 return DefineAsRegister(new (zone()) LLoadNamedField(obj)); |
2044 } | 1876 } |
2045 | 1877 |
2046 | |
2047 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1878 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
2048 LOperand* context = UseFixed(instr->context(), cp); | 1879 LOperand* context = UseFixed(instr->context(), cp); |
2049 LOperand* object = | 1880 LOperand* object = |
2050 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); | 1881 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); |
2051 LOperand* vector = NULL; | 1882 LOperand* vector = NULL; |
2052 if (instr->HasVectorAndSlot()) { | 1883 if (instr->HasVectorAndSlot()) { |
2053 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1884 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
2054 } | 1885 } |
2055 | 1886 |
2056 LInstruction* result = | 1887 LInstruction* result = |
2057 DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r3); | 1888 DefineFixed(new (zone()) LLoadNamedGeneric(context, object, vector), r2); |
2058 return MarkAsCall(result, instr); | 1889 return MarkAsCall(result, instr); |
2059 } | 1890 } |
2060 | 1891 |
2061 | |
2062 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( | 1892 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( |
2063 HLoadFunctionPrototype* instr) { | 1893 HLoadFunctionPrototype* instr) { |
2064 return AssignEnvironment(DefineAsRegister( | 1894 return AssignEnvironment(DefineAsRegister( |
2065 new (zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); | 1895 new (zone()) LLoadFunctionPrototype(UseRegister(instr->function())))); |
2066 } | 1896 } |
2067 | 1897 |
2068 | |
2069 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 1898 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
2070 return DefineAsRegister(new (zone()) LLoadRoot); | 1899 return DefineAsRegister(new (zone()) LLoadRoot); |
2071 } | 1900 } |
2072 | 1901 |
2073 | |
2074 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 1902 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
2075 DCHECK(instr->key()->representation().IsSmiOrInteger32()); | 1903 DCHECK(instr->key()->representation().IsSmiOrInteger32()); |
2076 ElementsKind elements_kind = instr->elements_kind(); | 1904 ElementsKind elements_kind = instr->elements_kind(); |
2077 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1905 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2078 LInstruction* result = NULL; | 1906 LInstruction* result = NULL; |
2079 | 1907 |
2080 if (!instr->is_fixed_typed_array()) { | 1908 if (!instr->is_fixed_typed_array()) { |
2081 LOperand* obj = NULL; | 1909 LOperand* obj = NULL; |
2082 if (instr->representation().IsDouble()) { | 1910 if (instr->representation().IsDouble()) { |
2083 obj = UseRegister(instr->elements()); | 1911 obj = UseRegister(instr->elements()); |
(...skipping 24 matching lines...) Expand all Loading... |
2108 instr->RequiresHoleCheck() || | 1936 instr->RequiresHoleCheck() || |
2109 (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub()); | 1937 (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub()); |
2110 } | 1938 } |
2111 | 1939 |
2112 if (needs_environment) { | 1940 if (needs_environment) { |
2113 result = AssignEnvironment(result); | 1941 result = AssignEnvironment(result); |
2114 } | 1942 } |
2115 return result; | 1943 return result; |
2116 } | 1944 } |
2117 | 1945 |
2118 | |
2119 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1946 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
2120 LOperand* context = UseFixed(instr->context(), cp); | 1947 LOperand* context = UseFixed(instr->context(), cp); |
2121 LOperand* object = | 1948 LOperand* object = |
2122 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); | 1949 UseFixed(instr->object(), LoadDescriptor::ReceiverRegister()); |
2123 LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister()); | 1950 LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister()); |
2124 LOperand* vector = NULL; | 1951 LOperand* vector = NULL; |
2125 if (instr->HasVectorAndSlot()) { | 1952 if (instr->HasVectorAndSlot()) { |
2126 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); | 1953 vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister()); |
2127 } | 1954 } |
2128 | 1955 |
2129 LInstruction* result = DefineFixed( | 1956 LInstruction* result = DefineFixed( |
2130 new (zone()) LLoadKeyedGeneric(context, object, key, vector), r3); | 1957 new (zone()) LLoadKeyedGeneric(context, object, key, vector), r2); |
2131 return MarkAsCall(result, instr); | 1958 return MarkAsCall(result, instr); |
2132 } | 1959 } |
2133 | 1960 |
2134 | |
2135 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 1961 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
2136 if (!instr->is_fixed_typed_array()) { | 1962 if (!instr->is_fixed_typed_array()) { |
2137 DCHECK(instr->elements()->representation().IsTagged()); | 1963 DCHECK(instr->elements()->representation().IsTagged()); |
2138 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 1964 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
2139 LOperand* object = NULL; | 1965 LOperand* object = NULL; |
2140 LOperand* key = NULL; | 1966 LOperand* key = NULL; |
2141 LOperand* val = NULL; | 1967 LOperand* val = NULL; |
2142 | 1968 |
2143 if (instr->value()->representation().IsDouble()) { | 1969 if (instr->value()->representation().IsDouble()) { |
2144 object = UseRegisterAtStart(instr->elements()); | 1970 object = UseRegisterAtStart(instr->elements()); |
(...skipping 19 matching lines...) Expand all Loading... |
2164 (instr->value()->representation().IsDouble() && | 1990 (instr->value()->representation().IsDouble() && |
2165 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 1991 IsDoubleOrFloatElementsKind(instr->elements_kind()))); |
2166 DCHECK(instr->elements()->representation().IsExternal()); | 1992 DCHECK(instr->elements()->representation().IsExternal()); |
2167 LOperand* val = UseRegister(instr->value()); | 1993 LOperand* val = UseRegister(instr->value()); |
2168 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 1994 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2169 LOperand* backing_store = UseRegister(instr->elements()); | 1995 LOperand* backing_store = UseRegister(instr->elements()); |
2170 LOperand* backing_store_owner = UseAny(instr->backing_store_owner()); | 1996 LOperand* backing_store_owner = UseAny(instr->backing_store_owner()); |
2171 return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner); | 1997 return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner); |
2172 } | 1998 } |
2173 | 1999 |
2174 | |
2175 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2000 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
2176 LOperand* context = UseFixed(instr->context(), cp); | 2001 LOperand* context = UseFixed(instr->context(), cp); |
2177 LOperand* obj = | 2002 LOperand* obj = |
2178 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); | 2003 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); |
2179 LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister()); | 2004 LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister()); |
2180 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); | 2005 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); |
2181 | 2006 |
2182 DCHECK(instr->object()->representation().IsTagged()); | 2007 DCHECK(instr->object()->representation().IsTagged()); |
2183 DCHECK(instr->key()->representation().IsTagged()); | 2008 DCHECK(instr->key()->representation().IsTagged()); |
2184 DCHECK(instr->value()->representation().IsTagged()); | 2009 DCHECK(instr->value()->representation().IsTagged()); |
2185 | 2010 |
2186 LOperand* slot = NULL; | 2011 LOperand* slot = NULL; |
2187 LOperand* vector = NULL; | 2012 LOperand* vector = NULL; |
2188 if (instr->HasVectorAndSlot()) { | 2013 if (instr->HasVectorAndSlot()) { |
2189 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); | 2014 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); |
2190 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); | 2015 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); |
2191 } | 2016 } |
2192 | 2017 |
2193 LStoreKeyedGeneric* result = | 2018 LStoreKeyedGeneric* result = |
2194 new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector); | 2019 new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector); |
2195 return MarkAsCall(result, instr); | 2020 return MarkAsCall(result, instr); |
2196 } | 2021 } |
2197 | 2022 |
2198 | |
2199 LInstruction* LChunkBuilder::DoTransitionElementsKind( | 2023 LInstruction* LChunkBuilder::DoTransitionElementsKind( |
2200 HTransitionElementsKind* instr) { | 2024 HTransitionElementsKind* instr) { |
2201 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2025 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
2202 LOperand* object = UseRegister(instr->object()); | 2026 LOperand* object = UseRegister(instr->object()); |
2203 LOperand* new_map_reg = TempRegister(); | 2027 LOperand* new_map_reg = TempRegister(); |
2204 LTransitionElementsKind* result = | 2028 LTransitionElementsKind* result = |
2205 new (zone()) LTransitionElementsKind(object, NULL, new_map_reg); | 2029 new (zone()) LTransitionElementsKind(object, NULL, new_map_reg); |
2206 return result; | 2030 return result; |
2207 } else { | 2031 } else { |
2208 LOperand* object = UseFixed(instr->object(), r3); | 2032 LOperand* object = UseFixed(instr->object(), r2); |
2209 LOperand* context = UseFixed(instr->context(), cp); | 2033 LOperand* context = UseFixed(instr->context(), cp); |
2210 LTransitionElementsKind* result = | 2034 LTransitionElementsKind* result = |
2211 new (zone()) LTransitionElementsKind(object, context, NULL); | 2035 new (zone()) LTransitionElementsKind(object, context, NULL); |
2212 return MarkAsCall(result, instr); | 2036 return MarkAsCall(result, instr); |
2213 } | 2037 } |
2214 } | 2038 } |
2215 | 2039 |
2216 | |
2217 LInstruction* LChunkBuilder::DoTrapAllocationMemento( | 2040 LInstruction* LChunkBuilder::DoTrapAllocationMemento( |
2218 HTrapAllocationMemento* instr) { | 2041 HTrapAllocationMemento* instr) { |
2219 LOperand* object = UseRegister(instr->object()); | 2042 LOperand* object = UseRegister(instr->object()); |
2220 LOperand* temp = TempRegister(); | 2043 LOperand* temp = TempRegister(); |
2221 LTrapAllocationMemento* result = | 2044 LTrapAllocationMemento* result = |
2222 new (zone()) LTrapAllocationMemento(object, temp); | 2045 new (zone()) LTrapAllocationMemento(object, temp); |
2223 return AssignEnvironment(result); | 2046 return AssignEnvironment(result); |
2224 } | 2047 } |
2225 | 2048 |
2226 | |
2227 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) { | 2049 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) { |
2228 info()->MarkAsDeferredCalling(); | 2050 info()->MarkAsDeferredCalling(); |
2229 LOperand* context = UseFixed(instr->context(), cp); | 2051 LOperand* context = UseFixed(instr->context(), cp); |
2230 LOperand* object = Use(instr->object()); | 2052 LOperand* object = Use(instr->object()); |
2231 LOperand* elements = Use(instr->elements()); | 2053 LOperand* elements = Use(instr->elements()); |
2232 LOperand* key = UseRegisterOrConstant(instr->key()); | 2054 LOperand* key = UseRegisterOrConstant(instr->key()); |
2233 LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity()); | 2055 LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity()); |
2234 | 2056 |
2235 LMaybeGrowElements* result = new (zone()) | 2057 LMaybeGrowElements* result = new (zone()) |
2236 LMaybeGrowElements(context, object, elements, key, current_capacity); | 2058 LMaybeGrowElements(context, object, elements, key, current_capacity); |
2237 DefineFixed(result, r3); | 2059 DefineFixed(result, r2); |
2238 return AssignPointerMap(AssignEnvironment(result)); | 2060 return AssignPointerMap(AssignEnvironment(result)); |
2239 } | 2061 } |
2240 | 2062 |
2241 | |
2242 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { | 2063 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { |
2243 bool is_in_object = instr->access().IsInobject(); | 2064 bool is_in_object = instr->access().IsInobject(); |
2244 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2065 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
2245 bool needs_write_barrier_for_map = | 2066 bool needs_write_barrier_for_map = |
2246 instr->has_transition() && instr->NeedsWriteBarrierForMap(); | 2067 instr->has_transition() && instr->NeedsWriteBarrierForMap(); |
2247 | 2068 |
2248 LOperand* obj; | 2069 LOperand* obj; |
2249 if (needs_write_barrier) { | 2070 if (needs_write_barrier) { |
2250 obj = is_in_object ? UseRegister(instr->object()) | 2071 obj = is_in_object ? UseRegister(instr->object()) |
2251 : UseTempRegister(instr->object()); | 2072 : UseTempRegister(instr->object()); |
(...skipping 10 matching lines...) Expand all Loading... |
2262 } else { | 2083 } else { |
2263 val = UseRegister(instr->value()); | 2084 val = UseRegister(instr->value()); |
2264 } | 2085 } |
2265 | 2086 |
2266 // We need a temporary register for write barrier of the map field. | 2087 // We need a temporary register for write barrier of the map field. |
2267 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; | 2088 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; |
2268 | 2089 |
2269 return new (zone()) LStoreNamedField(obj, val, temp); | 2090 return new (zone()) LStoreNamedField(obj, val, temp); |
2270 } | 2091 } |
2271 | 2092 |
2272 | |
2273 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2093 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
2274 LOperand* context = UseFixed(instr->context(), cp); | 2094 LOperand* context = UseFixed(instr->context(), cp); |
2275 LOperand* obj = | 2095 LOperand* obj = |
2276 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); | 2096 UseFixed(instr->object(), StoreDescriptor::ReceiverRegister()); |
2277 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); | 2097 LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister()); |
2278 LOperand* slot = NULL; | 2098 LOperand* slot = NULL; |
2279 LOperand* vector = NULL; | 2099 LOperand* vector = NULL; |
2280 if (instr->HasVectorAndSlot()) { | 2100 if (instr->HasVectorAndSlot()) { |
2281 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); | 2101 slot = FixedTemp(VectorStoreICDescriptor::SlotRegister()); |
2282 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); | 2102 vector = FixedTemp(VectorStoreICDescriptor::VectorRegister()); |
2283 } | 2103 } |
2284 | 2104 |
2285 LStoreNamedGeneric* result = | 2105 LStoreNamedGeneric* result = |
2286 new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector); | 2106 new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector); |
2287 return MarkAsCall(result, instr); | 2107 return MarkAsCall(result, instr); |
2288 } | 2108 } |
2289 | 2109 |
2290 | |
2291 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { | 2110 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) { |
2292 LOperand* context = UseFixed(instr->context(), cp); | 2111 LOperand* context = UseFixed(instr->context(), cp); |
2293 LOperand* left = UseFixed(instr->left(), r4); | 2112 LOperand* left = UseFixed(instr->left(), r3); |
2294 LOperand* right = UseFixed(instr->right(), r3); | 2113 LOperand* right = UseFixed(instr->right(), r2); |
2295 return MarkAsCall( | 2114 return MarkAsCall( |
2296 DefineFixed(new (zone()) LStringAdd(context, left, right), r3), instr); | 2115 DefineFixed(new (zone()) LStringAdd(context, left, right), r2), instr); |
2297 } | 2116 } |
2298 | 2117 |
2299 | |
2300 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2118 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
2301 LOperand* string = UseTempRegister(instr->string()); | 2119 LOperand* string = UseTempRegister(instr->string()); |
2302 LOperand* index = UseTempRegister(instr->index()); | 2120 LOperand* index = UseTempRegister(instr->index()); |
2303 LOperand* context = UseAny(instr->context()); | 2121 LOperand* context = UseAny(instr->context()); |
2304 LStringCharCodeAt* result = | 2122 LStringCharCodeAt* result = |
2305 new (zone()) LStringCharCodeAt(context, string, index); | 2123 new (zone()) LStringCharCodeAt(context, string, index); |
2306 return AssignPointerMap(DefineAsRegister(result)); | 2124 return AssignPointerMap(DefineAsRegister(result)); |
2307 } | 2125 } |
2308 | 2126 |
2309 | |
2310 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { | 2127 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
2311 LOperand* char_code = UseRegister(instr->value()); | 2128 LOperand* char_code = UseRegister(instr->value()); |
2312 LOperand* context = UseAny(instr->context()); | 2129 LOperand* context = UseAny(instr->context()); |
2313 LStringCharFromCode* result = | 2130 LStringCharFromCode* result = |
2314 new (zone()) LStringCharFromCode(context, char_code); | 2131 new (zone()) LStringCharFromCode(context, char_code); |
2315 return AssignPointerMap(DefineAsRegister(result)); | 2132 return AssignPointerMap(DefineAsRegister(result)); |
2316 } | 2133 } |
2317 | 2134 |
2318 | |
2319 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { | 2135 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) { |
2320 info()->MarkAsDeferredCalling(); | 2136 info()->MarkAsDeferredCalling(); |
2321 LOperand* context = UseAny(instr->context()); | 2137 LOperand* context = UseAny(instr->context()); |
2322 LOperand* size = UseRegisterOrConstant(instr->size()); | 2138 LOperand* size = UseRegisterOrConstant(instr->size()); |
2323 LOperand* temp1 = TempRegister(); | 2139 LOperand* temp1 = TempRegister(); |
2324 LOperand* temp2 = TempRegister(); | 2140 LOperand* temp2 = TempRegister(); |
2325 LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2); | 2141 LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2); |
2326 return AssignPointerMap(DefineAsRegister(result)); | 2142 return AssignPointerMap(DefineAsRegister(result)); |
2327 } | 2143 } |
2328 | 2144 |
2329 | |
2330 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 2145 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
2331 DCHECK(argument_count_ == 0); | 2146 DCHECK(argument_count_ == 0); |
2332 allocator_->MarkAsOsrEntry(); | 2147 allocator_->MarkAsOsrEntry(); |
2333 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 2148 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
2334 return AssignEnvironment(new (zone()) LOsrEntry); | 2149 return AssignEnvironment(new (zone()) LOsrEntry); |
2335 } | 2150 } |
2336 | 2151 |
2337 | |
2338 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 2152 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
2339 LParameter* result = new (zone()) LParameter; | 2153 LParameter* result = new (zone()) LParameter; |
2340 if (instr->kind() == HParameter::STACK_PARAMETER) { | 2154 if (instr->kind() == HParameter::STACK_PARAMETER) { |
2341 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 2155 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
2342 return DefineAsSpilled(result, spill_index); | 2156 return DefineAsSpilled(result, spill_index); |
2343 } else { | 2157 } else { |
2344 DCHECK(info()->IsStub()); | 2158 DCHECK(info()->IsStub()); |
2345 CallInterfaceDescriptor descriptor = graph()->descriptor(); | 2159 CallInterfaceDescriptor descriptor = graph()->descriptor(); |
2346 int index = static_cast<int>(instr->index()); | 2160 int index = static_cast<int>(instr->index()); |
2347 Register reg = descriptor.GetRegisterParameter(index); | 2161 Register reg = descriptor.GetRegisterParameter(index); |
2348 return DefineFixed(result, reg); | 2162 return DefineFixed(result, reg); |
2349 } | 2163 } |
2350 } | 2164 } |
2351 | 2165 |
2352 | |
2353 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 2166 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
2354 // Use an index that corresponds to the location in the unoptimized frame, | 2167 // Use an index that corresponds to the location in the unoptimized frame, |
2355 // which the optimized frame will subsume. | 2168 // which the optimized frame will subsume. |
2356 int env_index = instr->index(); | 2169 int env_index = instr->index(); |
2357 int spill_index = 0; | 2170 int spill_index = 0; |
2358 if (instr->environment()->is_parameter_index(env_index)) { | 2171 if (instr->environment()->is_parameter_index(env_index)) { |
2359 spill_index = chunk()->GetParameterStackSlot(env_index); | 2172 spill_index = chunk()->GetParameterStackSlot(env_index); |
2360 } else { | 2173 } else { |
2361 spill_index = env_index - instr->environment()->first_local_index(); | 2174 spill_index = env_index - instr->environment()->first_local_index(); |
2362 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { | 2175 if (spill_index > LUnallocated::kMaxFixedSlotIndex) { |
2363 Retry(kTooManySpillSlotsNeededForOSR); | 2176 Retry(kTooManySpillSlotsNeededForOSR); |
2364 spill_index = 0; | 2177 spill_index = 0; |
2365 } | 2178 } |
2366 spill_index += StandardFrameConstants::kFixedSlotCount; | 2179 spill_index += StandardFrameConstants::kFixedSlotCount; |
2367 } | 2180 } |
2368 return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index); | 2181 return DefineAsSpilled(new (zone()) LUnknownOSRValue, spill_index); |
2369 } | 2182 } |
2370 | 2183 |
2371 | |
2372 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { | 2184 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { |
2373 // There are no real uses of the arguments object. | 2185 // There are no real uses of the arguments object. |
2374 // arguments.length and element access are supported directly on | 2186 // arguments.length and element access are supported directly on |
2375 // stack arguments, and any real arguments object use causes a bailout. | 2187 // stack arguments, and any real arguments object use causes a bailout. |
2376 // So this value is never used. | 2188 // So this value is never used. |
2377 return NULL; | 2189 return NULL; |
2378 } | 2190 } |
2379 | 2191 |
2380 | |
2381 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) { | 2192 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) { |
2382 instr->ReplayEnvironment(current_block_->last_environment()); | 2193 instr->ReplayEnvironment(current_block_->last_environment()); |
2383 | 2194 |
2384 // There are no real uses of a captured object. | 2195 // There are no real uses of a captured object. |
2385 return NULL; | 2196 return NULL; |
2386 } | 2197 } |
2387 | 2198 |
2388 | |
2389 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 2199 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
2390 info()->MarkAsRequiresFrame(); | 2200 info()->MarkAsRequiresFrame(); |
2391 LOperand* args = UseRegister(instr->arguments()); | 2201 LOperand* args = UseRegister(instr->arguments()); |
2392 LOperand* length = UseRegisterOrConstantAtStart(instr->length()); | 2202 LOperand* length = UseRegisterOrConstantAtStart(instr->length()); |
2393 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); | 2203 LOperand* index = UseRegisterOrConstantAtStart(instr->index()); |
2394 return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index)); | 2204 return DefineAsRegister(new (zone()) LAccessArgumentsAt(args, length, index)); |
2395 } | 2205 } |
2396 | 2206 |
2397 | |
2398 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) { | 2207 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) { |
2399 LOperand* object = UseFixed(instr->value(), r3); | 2208 LOperand* object = UseFixed(instr->value(), r2); |
2400 LToFastProperties* result = new (zone()) LToFastProperties(object); | 2209 LToFastProperties* result = new (zone()) LToFastProperties(object); |
2401 return MarkAsCall(DefineFixed(result, r3), instr); | 2210 return MarkAsCall(DefineFixed(result, r2), instr); |
2402 } | 2211 } |
2403 | 2212 |
2404 | |
2405 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 2213 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
2406 LOperand* context = UseFixed(instr->context(), cp); | 2214 LOperand* context = UseFixed(instr->context(), cp); |
2407 LOperand* value = UseFixed(instr->value(), r6); | 2215 LOperand* value = UseFixed(instr->value(), r5); |
2408 LTypeof* result = new (zone()) LTypeof(context, value); | 2216 LTypeof* result = new (zone()) LTypeof(context, value); |
2409 return MarkAsCall(DefineFixed(result, r3), instr); | 2217 return MarkAsCall(DefineFixed(result, r2), instr); |
2410 } | 2218 } |
2411 | 2219 |
2412 | |
2413 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { | 2220 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { |
2414 return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value())); | 2221 return new (zone()) LTypeofIsAndBranch(UseRegister(instr->value())); |
2415 } | 2222 } |
2416 | 2223 |
2417 | |
2418 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2224 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
2419 instr->ReplayEnvironment(current_block_->last_environment()); | 2225 instr->ReplayEnvironment(current_block_->last_environment()); |
2420 return NULL; | 2226 return NULL; |
2421 } | 2227 } |
2422 | 2228 |
2423 | |
2424 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2229 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
2425 if (instr->is_function_entry()) { | 2230 if (instr->is_function_entry()) { |
2426 LOperand* context = UseFixed(instr->context(), cp); | 2231 LOperand* context = UseFixed(instr->context(), cp); |
2427 return MarkAsCall(new (zone()) LStackCheck(context), instr); | 2232 return MarkAsCall(new (zone()) LStackCheck(context), instr); |
2428 } else { | 2233 } else { |
2429 DCHECK(instr->is_backwards_branch()); | 2234 DCHECK(instr->is_backwards_branch()); |
2430 LOperand* context = UseAny(instr->context()); | 2235 LOperand* context = UseAny(instr->context()); |
2431 return AssignEnvironment( | 2236 return AssignEnvironment( |
2432 AssignPointerMap(new (zone()) LStackCheck(context))); | 2237 AssignPointerMap(new (zone()) LStackCheck(context))); |
2433 } | 2238 } |
2434 } | 2239 } |
2435 | 2240 |
2436 | |
2437 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { | 2241 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { |
2438 HEnvironment* outer = current_block_->last_environment(); | 2242 HEnvironment* outer = current_block_->last_environment(); |
2439 outer->set_ast_id(instr->ReturnId()); | 2243 outer->set_ast_id(instr->ReturnId()); |
2440 HConstant* undefined = graph()->GetConstantUndefined(); | 2244 HConstant* undefined = graph()->GetConstantUndefined(); |
2441 HEnvironment* inner = outer->CopyForInlining( | 2245 HEnvironment* inner = outer->CopyForInlining( |
2442 instr->closure(), instr->arguments_count(), instr->function(), undefined, | 2246 instr->closure(), instr->arguments_count(), instr->function(), undefined, |
2443 instr->inlining_kind()); | 2247 instr->inlining_kind()); |
2444 // Only replay binding of arguments object if it wasn't removed from graph. | 2248 // Only replay binding of arguments object if it wasn't removed from graph. |
2445 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) { | 2249 if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) { |
2446 inner->Bind(instr->arguments_var(), instr->arguments_object()); | 2250 inner->Bind(instr->arguments_var(), instr->arguments_object()); |
2447 } | 2251 } |
2448 inner->BindContext(instr->closure_context()); | 2252 inner->BindContext(instr->closure_context()); |
2449 inner->set_entry(instr); | 2253 inner->set_entry(instr); |
2450 current_block_->UpdateEnvironment(inner); | 2254 current_block_->UpdateEnvironment(inner); |
2451 chunk_->AddInlinedFunction(instr->shared()); | 2255 chunk_->AddInlinedFunction(instr->shared()); |
2452 return NULL; | 2256 return NULL; |
2453 } | 2257 } |
2454 | 2258 |
2455 | |
2456 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2259 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
2457 LInstruction* pop = NULL; | 2260 LInstruction* pop = NULL; |
2458 | 2261 |
2459 HEnvironment* env = current_block_->last_environment(); | 2262 HEnvironment* env = current_block_->last_environment(); |
2460 | 2263 |
2461 if (env->entry()->arguments_pushed()) { | 2264 if (env->entry()->arguments_pushed()) { |
2462 int argument_count = env->arguments_environment()->parameter_count(); | 2265 int argument_count = env->arguments_environment()->parameter_count(); |
2463 pop = new (zone()) LDrop(argument_count); | 2266 pop = new (zone()) LDrop(argument_count); |
2464 DCHECK(instr->argument_delta() == -argument_count); | 2267 DCHECK(instr->argument_delta() == -argument_count); |
2465 } | 2268 } |
2466 | 2269 |
2467 HEnvironment* outer = | 2270 HEnvironment* outer = |
2468 current_block_->last_environment()->DiscardInlined(false); | 2271 current_block_->last_environment()->DiscardInlined(false); |
2469 current_block_->UpdateEnvironment(outer); | 2272 current_block_->UpdateEnvironment(outer); |
2470 | 2273 |
2471 return pop; | 2274 return pop; |
2472 } | 2275 } |
2473 | 2276 |
2474 | |
2475 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { | 2277 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) { |
2476 LOperand* context = UseFixed(instr->context(), cp); | 2278 LOperand* context = UseFixed(instr->context(), cp); |
2477 LOperand* object = UseFixed(instr->enumerable(), r3); | 2279 LOperand* object = UseFixed(instr->enumerable(), r2); |
2478 LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object); | 2280 LForInPrepareMap* result = new (zone()) LForInPrepareMap(context, object); |
2479 return MarkAsCall(DefineFixed(result, r3), instr, CAN_DEOPTIMIZE_EAGERLY); | 2281 return MarkAsCall(DefineFixed(result, r2), instr, CAN_DEOPTIMIZE_EAGERLY); |
2480 } | 2282 } |
2481 | 2283 |
2482 | |
2483 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { | 2284 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) { |
2484 LOperand* map = UseRegister(instr->map()); | 2285 LOperand* map = UseRegister(instr->map()); |
2485 return AssignEnvironment( | 2286 return AssignEnvironment( |
2486 DefineAsRegister(new (zone()) LForInCacheArray(map))); | 2287 DefineAsRegister(new (zone()) LForInCacheArray(map))); |
2487 } | 2288 } |
2488 | 2289 |
2489 | |
2490 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { | 2290 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) { |
2491 LOperand* value = UseRegisterAtStart(instr->value()); | 2291 LOperand* value = UseRegisterAtStart(instr->value()); |
2492 LOperand* map = UseRegisterAtStart(instr->map()); | 2292 LOperand* map = UseRegisterAtStart(instr->map()); |
2493 return AssignEnvironment(new (zone()) LCheckMapValue(value, map)); | 2293 return AssignEnvironment(new (zone()) LCheckMapValue(value, map)); |
2494 } | 2294 } |
2495 | 2295 |
2496 | |
2497 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2296 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2498 LOperand* object = UseRegister(instr->object()); | 2297 LOperand* object = UseRegister(instr->object()); |
2499 LOperand* index = UseTempRegister(instr->index()); | 2298 LOperand* index = UseTempRegister(instr->index()); |
2500 LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index); | 2299 LLoadFieldByIndex* load = new (zone()) LLoadFieldByIndex(object, index); |
2501 LInstruction* result = DefineSameAsFirst(load); | 2300 LInstruction* result = DefineSameAsFirst(load); |
2502 return AssignPointerMap(result); | 2301 return AssignPointerMap(result); |
2503 } | 2302 } |
2504 | 2303 |
2505 | |
2506 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) { | 2304 LInstruction* LChunkBuilder::DoStoreFrameContext(HStoreFrameContext* instr) { |
2507 LOperand* context = UseRegisterAtStart(instr->context()); | 2305 LOperand* context = UseRegisterAtStart(instr->context()); |
2508 return new (zone()) LStoreFrameContext(context); | 2306 return new (zone()) LStoreFrameContext(context); |
2509 } | 2307 } |
2510 | 2308 |
2511 } // namespace internal | 2309 } // namespace internal |
2512 } // namespace v8 | 2310 } // namespace v8 |
OLD | NEW |