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

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

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h"
29
30 #if defined(V8_TARGET_ARCH_IA32)
31
32 #include "lithium-allocator-inl.h"
28 #include "ia32/lithium-ia32.h" 33 #include "ia32/lithium-ia32.h"
29 #include "ia32/lithium-codegen-ia32.h" 34 #include "ia32/lithium-codegen-ia32.h"
30 35
31 namespace v8 { 36 namespace v8 {
32 namespace internal { 37 namespace internal {
33 38
34 #define DEFINE_COMPILE(type) \ 39 #define DEFINE_COMPILE(type) \
35 void L##type::CompileToNative(LCodeGen* generator) { \ 40 void L##type::CompileToNative(LCodeGen* generator) { \
36 generator->Do##type(this); \ 41 generator->Do##type(this); \
37 } 42 }
(...skipping 19 matching lines...) Expand all
57 62
58 63
59 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, 64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
60 LOperand* spill_operand) { 65 LOperand* spill_operand) {
61 ASSERT(spill_operand->IsDoubleStackSlot()); 66 ASSERT(spill_operand->IsDoubleStackSlot());
62 ASSERT(double_register_spills_[allocation_index] == NULL); 67 ASSERT(double_register_spills_[allocation_index] == NULL);
63 double_register_spills_[allocation_index] = spill_operand; 68 double_register_spills_[allocation_index] = spill_operand;
64 } 69 }
65 70
66 71
67 void LInstruction::PrintTo(StringStream* stream) const { 72 #ifdef DEBUG
73 void LInstruction::VerifyCall() {
74 // Call instructions can use only fixed registers as
75 // temporaries and outputs because all registers
76 // are blocked by the calling convention.
77 // Inputs must use a fixed register.
78 ASSERT(Output() == NULL ||
79 LUnallocated::cast(Output())->HasFixedPolicy() ||
80 !LUnallocated::cast(Output())->HasRegisterPolicy());
81 for (UseIterator it(this); it.HasNext(); it.Advance()) {
82 LOperand* operand = it.Next();
83 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
84 !LUnallocated::cast(operand)->HasRegisterPolicy());
85 }
86 for (TempIterator it(this); it.HasNext(); it.Advance()) {
87 LOperand* operand = it.Next();
88 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
89 !LUnallocated::cast(operand)->HasRegisterPolicy());
90 }
91 }
92 #endif
93
94
95 void LInstruction::PrintTo(StringStream* stream) {
68 stream->Add("%s ", this->Mnemonic()); 96 stream->Add("%s ", this->Mnemonic());
69 if (HasResult()) { 97
70 result()->PrintTo(stream); 98 PrintOutputOperandTo(stream);
71 stream->Add(" "); 99
72 }
73 PrintDataTo(stream); 100 PrintDataTo(stream);
74 101
75 if (HasEnvironment()) { 102 if (HasEnvironment()) {
76 stream->Add(" "); 103 stream->Add(" ");
77 environment()->PrintTo(stream); 104 environment()->PrintTo(stream);
78 } 105 }
79 106
80 if (HasPointerMap()) { 107 if (HasPointerMap()) {
81 stream->Add(" "); 108 stream->Add(" ");
82 pointer_map()->PrintTo(stream); 109 pointer_map()->PrintTo(stream);
83 } 110 }
84 } 111 }
85 112
86 113
87 void LLabel::PrintDataTo(StringStream* stream) const { 114 template<int R, int I, int T>
115 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
116 stream->Add("= ");
117 inputs_.PrintOperandsTo(stream);
118 }
119
120
121 template<int R, int I, int T>
122 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
123 results_.PrintOperandsTo(stream);
124 }
125
126
127 template<typename T, int N>
128 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
129 for (int i = 0; i < N; i++) {
130 if (i > 0) stream->Add(" ");
131 elems_[i]->PrintTo(stream);
132 }
133 }
134
135
136 void LLabel::PrintDataTo(StringStream* stream) {
88 LGap::PrintDataTo(stream); 137 LGap::PrintDataTo(stream);
89 LLabel* rep = replacement(); 138 LLabel* rep = replacement();
90 if (rep != NULL) { 139 if (rep != NULL) {
91 stream->Add(" Dead block replaced with B%d", rep->block_id()); 140 stream->Add(" Dead block replaced with B%d", rep->block_id());
92 } 141 }
93 } 142 }
94 143
95
96 bool LParallelMove::IsRedundant() const {
97 for (int i = 0; i < move_operands_.length(); ++i) {
98 if (!move_operands_[i].IsRedundant()) return false;
99 }
100 return true;
101 }
102
103
104 void LParallelMove::PrintDataTo(StringStream* stream) const {
105 for (int i = move_operands_.length() - 1; i >= 0; --i) {
106 if (!move_operands_[i].IsEliminated()) {
107 LOperand* from = move_operands_[i].from();
108 LOperand* to = move_operands_[i].to();
109 if (from->Equals(to)) {
110 to->PrintTo(stream);
111 } else {
112 to->PrintTo(stream);
113 stream->Add(" = ");
114 from->PrintTo(stream);
115 }
116 stream->Add("; ");
117 }
118 }
119 }
120
121 144
122 bool LGap::IsRedundant() const { 145 bool LGap::IsRedundant() const {
123 for (int i = 0; i < 4; i++) { 146 for (int i = 0; i < 4; i++) {
124 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) { 147 if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
125 return false; 148 return false;
126 } 149 }
127 } 150 }
128 151
129 return true; 152 return true;
130 } 153 }
131 154
132 155
133 void LGap::PrintDataTo(StringStream* stream) const { 156 void LGap::PrintDataTo(StringStream* stream) {
134 for (int i = 0; i < 4; i++) { 157 for (int i = 0; i < 4; i++) {
135 stream->Add("("); 158 stream->Add("(");
136 if (parallel_moves_[i] != NULL) { 159 if (parallel_moves_[i] != NULL) {
137 parallel_moves_[i]->PrintDataTo(stream); 160 parallel_moves_[i]->PrintDataTo(stream);
138 } 161 }
139 stream->Add(") "); 162 stream->Add(") ");
140 } 163 }
141 } 164 }
142 165
143 166
(...skipping 11 matching lines...) Expand all
155 } 178 }
156 179
157 180
158 const char* LArithmeticT::Mnemonic() const { 181 const char* LArithmeticT::Mnemonic() const {
159 switch (op()) { 182 switch (op()) {
160 case Token::ADD: return "add-t"; 183 case Token::ADD: return "add-t";
161 case Token::SUB: return "sub-t"; 184 case Token::SUB: return "sub-t";
162 case Token::MUL: return "mul-t"; 185 case Token::MUL: return "mul-t";
163 case Token::MOD: return "mod-t"; 186 case Token::MOD: return "mod-t";
164 case Token::DIV: return "div-t"; 187 case Token::DIV: return "div-t";
188 case Token::BIT_AND: return "bit-and-t";
189 case Token::BIT_OR: return "bit-or-t";
190 case Token::BIT_XOR: return "bit-xor-t";
191 case Token::SHL: return "sal-t";
192 case Token::SAR: return "sar-t";
193 case Token::SHR: return "shr-t";
165 default: 194 default:
166 UNREACHABLE(); 195 UNREACHABLE();
167 return NULL; 196 return NULL;
168 } 197 }
169 } 198 }
170 199
171 200
172 201 void LGoto::PrintDataTo(StringStream* stream) {
173 void LBinaryOperation::PrintDataTo(StringStream* stream) const {
174 stream->Add("= ");
175 left()->PrintTo(stream);
176 stream->Add(" ");
177 right()->PrintTo(stream);
178 }
179
180
181 void LGoto::PrintDataTo(StringStream* stream) const {
182 stream->Add("B%d", block_id()); 202 stream->Add("B%d", block_id());
183 } 203 }
184 204
185 205
186 void LBranch::PrintDataTo(StringStream* stream) const { 206 void LBranch::PrintDataTo(StringStream* stream) {
187 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); 207 stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
188 input()->PrintTo(stream); 208 InputAt(0)->PrintTo(stream);
189 } 209 }
190 210
191 211
192 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) const { 212 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
193 stream->Add("if "); 213 stream->Add("if ");
194 left()->PrintTo(stream); 214 InputAt(0)->PrintTo(stream);
195 stream->Add(" %s ", Token::String(op())); 215 stream->Add(" %s ", Token::String(op()));
196 right()->PrintTo(stream); 216 InputAt(1)->PrintTo(stream);
197 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); 217 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
198 } 218 }
199 219
200 220
201 void LIsNullAndBranch::PrintDataTo(StringStream* stream) const { 221 void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
202 stream->Add("if "); 222 stream->Add("if ");
203 input()->PrintTo(stream); 223 InputAt(0)->PrintTo(stream);
204 stream->Add(is_strict() ? " === null" : " == null"); 224 stream->Add(is_strict() ? " === null" : " == null");
205 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); 225 stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
206 } 226 }
207 227
208 228
209 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const { 229 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
210 stream->Add("if is_object("); 230 stream->Add("if is_object(");
211 input()->PrintTo(stream); 231 InputAt(0)->PrintTo(stream);
212 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); 232 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
213 } 233 }
214 234
215 235
216 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const { 236 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
217 stream->Add("if is_smi("); 237 stream->Add("if is_smi(");
218 input()->PrintTo(stream); 238 InputAt(0)->PrintTo(stream);
219 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); 239 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
220 } 240 }
221 241
222 242
223 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) const { 243 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
224 stream->Add("if has_instance_type("); 244 stream->Add("if has_instance_type(");
225 input()->PrintTo(stream); 245 InputAt(0)->PrintTo(stream);
226 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); 246 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
227 } 247 }
228 248
229 249
230 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) const { 250 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
231 stream->Add("if has_cached_array_index("); 251 stream->Add("if has_cached_array_index(");
232 input()->PrintTo(stream); 252 InputAt(0)->PrintTo(stream);
233 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); 253 stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
234 } 254 }
235 255
236 256
237 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) const { 257 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
238 stream->Add("if class_of_test("); 258 stream->Add("if class_of_test(");
239 input()->PrintTo(stream); 259 InputAt(0)->PrintTo(stream);
240 stream->Add(", \"%o\") then B%d else B%d", 260 stream->Add(", \"%o\") then B%d else B%d",
241 *hydrogen()->class_name(), 261 *hydrogen()->class_name(),
242 true_block_id(), 262 true_block_id(),
243 false_block_id()); 263 false_block_id());
244 } 264 }
245 265
246 266
247 void LTypeofIs::PrintDataTo(StringStream* stream) const { 267 void LTypeofIs::PrintDataTo(StringStream* stream) {
248 input()->PrintTo(stream); 268 InputAt(0)->PrintTo(stream);
249 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); 269 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
250 } 270 }
251 271
252 272
253 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) const { 273 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
254 stream->Add("if typeof "); 274 stream->Add("if typeof ");
255 input()->PrintTo(stream); 275 InputAt(0)->PrintTo(stream);
256 stream->Add(" == \"%s\" then B%d else B%d", 276 stream->Add(" == \"%s\" then B%d else B%d",
257 *hydrogen()->type_literal()->ToCString(), 277 *hydrogen()->type_literal()->ToCString(),
258 true_block_id(), false_block_id()); 278 true_block_id(), false_block_id());
259 } 279 }
260 280
261 281
262 void LCallConstantFunction::PrintDataTo(StringStream* stream) const { 282 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
263 stream->Add("#%d / ", arity()); 283 stream->Add("#%d / ", arity());
264 } 284 }
265 285
266 286
267 void LUnaryMathOperation::PrintDataTo(StringStream* stream) const { 287 void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
268 stream->Add("/%s ", hydrogen()->OpName()); 288 stream->Add("/%s ", hydrogen()->OpName());
269 input()->PrintTo(stream); 289 InputAt(0)->PrintTo(stream);
270 } 290 }
271 291
272 292
273 void LCallKeyed::PrintDataTo(StringStream* stream) const { 293 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
294 InputAt(0)->PrintTo(stream);
295 stream->Add("[%d]", slot_index());
296 }
297
298
299 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
300 InputAt(0)->PrintTo(stream);
301 stream->Add("[%d] <- ", slot_index());
302 InputAt(1)->PrintTo(stream);
303 }
304
305
306 void LCallKeyed::PrintDataTo(StringStream* stream) {
274 stream->Add("[ecx] #%d / ", arity()); 307 stream->Add("[ecx] #%d / ", arity());
275 } 308 }
276 309
277 310
278 void LCallNamed::PrintDataTo(StringStream* stream) const { 311 void LCallNamed::PrintDataTo(StringStream* stream) {
279 SmartPointer<char> name_string = name()->ToCString(); 312 SmartPointer<char> name_string = name()->ToCString();
280 stream->Add("%s #%d / ", *name_string, arity()); 313 stream->Add("%s #%d / ", *name_string, arity());
281 } 314 }
282 315
283 316
284 void LCallGlobal::PrintDataTo(StringStream* stream) const { 317 void LCallGlobal::PrintDataTo(StringStream* stream) {
285 SmartPointer<char> name_string = name()->ToCString(); 318 SmartPointer<char> name_string = name()->ToCString();
286 stream->Add("%s #%d / ", *name_string, arity()); 319 stream->Add("%s #%d / ", *name_string, arity());
287 } 320 }
288 321
289 322
290 void LCallKnownGlobal::PrintDataTo(StringStream* stream) const { 323 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
291 stream->Add("#%d / ", arity()); 324 stream->Add("#%d / ", arity());
292 } 325 }
293 326
294 327
295 void LCallNew::PrintDataTo(StringStream* stream) const { 328 void LCallNew::PrintDataTo(StringStream* stream) {
296 LUnaryOperation::PrintDataTo(stream); 329 stream->Add("= ");
330 InputAt(0)->PrintTo(stream);
297 stream->Add(" #%d / ", arity()); 331 stream->Add(" #%d / ", arity());
298 } 332 }
299 333
300 334
301 void LClassOfTest::PrintDataTo(StringStream* stream) const { 335 void LClassOfTest::PrintDataTo(StringStream* stream) {
302 stream->Add("= class_of_test("); 336 stream->Add("= class_of_test(");
303 input()->PrintTo(stream); 337 InputAt(0)->PrintTo(stream);
304 stream->Add(", \"%o\")", *hydrogen()->class_name()); 338 stream->Add(", \"%o\")", *hydrogen()->class_name());
305 } 339 }
306 340
307 341
308 void LUnaryOperation::PrintDataTo(StringStream* stream) const { 342 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
309 stream->Add("= ");
310 input()->PrintTo(stream);
311 }
312
313
314 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
315 arguments()->PrintTo(stream); 343 arguments()->PrintTo(stream);
316 344
317 stream->Add(" length "); 345 stream->Add(" length ");
318 length()->PrintTo(stream); 346 length()->PrintTo(stream);
319 347
320 stream->Add(" index "); 348 stream->Add(" index ");
321 index()->PrintTo(stream); 349 index()->PrintTo(stream);
322 } 350 }
323 351
324 352
325 LChunk::LChunk(HGraph* graph)
326 : spill_slot_count_(0),
327 graph_(graph),
328 instructions_(32),
329 pointer_maps_(8),
330 inlined_closures_(1) {
331 }
332
333
334 void LChunk::Verify() const {
335 // TODO(twuerthinger): Implement verification for chunk.
336 }
337
338
339 int LChunk::GetNextSpillIndex(bool is_double) { 353 int LChunk::GetNextSpillIndex(bool is_double) {
340 // Skip a slot if for a double-width slot. 354 // Skip a slot if for a double-width slot.
341 if (is_double) spill_slot_count_++; 355 if (is_double) spill_slot_count_++;
342 return spill_slot_count_++; 356 return spill_slot_count_++;
343 } 357 }
344 358
345 359
346 LOperand* LChunk::GetNextSpillSlot(bool is_double) { 360 LOperand* LChunk::GetNextSpillSlot(bool is_double) {
347 int index = GetNextSpillIndex(is_double); 361 int index = GetNextSpillIndex(is_double);
348 if (is_double) { 362 if (is_double) {
349 return LDoubleStackSlot::Create(index); 363 return LDoubleStackSlot::Create(index);
350 } else { 364 } else {
351 return LStackSlot::Create(index); 365 return LStackSlot::Create(index);
352 } 366 }
353 } 367 }
354 368
355 369
356 void LChunk::MarkEmptyBlocks() { 370 void LChunk::MarkEmptyBlocks() {
(...skipping 26 matching lines...) Expand all
383 397
384 if (can_eliminate) { 398 if (can_eliminate) {
385 label->set_replacement(GetLabel(goto_instr->block_id())); 399 label->set_replacement(GetLabel(goto_instr->block_id()));
386 } 400 }
387 } 401 }
388 } 402 }
389 } 403 }
390 } 404 }
391 405
392 406
393 void LStoreNamed::PrintDataTo(StringStream* stream) const { 407 void LStoreNamed::PrintDataTo(StringStream* stream) {
394 object()->PrintTo(stream); 408 object()->PrintTo(stream);
395 stream->Add("."); 409 stream->Add(".");
396 stream->Add(*String::cast(*name())->ToCString()); 410 stream->Add(*String::cast(*name())->ToCString());
397 stream->Add(" <- "); 411 stream->Add(" <- ");
398 value()->PrintTo(stream); 412 value()->PrintTo(stream);
399 } 413 }
400 414
401 415
402 void LStoreKeyed::PrintDataTo(StringStream* stream) const { 416 void LStoreKeyed::PrintDataTo(StringStream* stream) {
403 object()->PrintTo(stream); 417 object()->PrintTo(stream);
404 stream->Add("["); 418 stream->Add("[");
405 key()->PrintTo(stream); 419 key()->PrintTo(stream);
406 stream->Add("] <- "); 420 stream->Add("] <- ");
407 value()->PrintTo(stream); 421 value()->PrintTo(stream);
408 } 422 }
409 423
410 424
411 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { 425 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
412 LGap* gap = new LGap(block); 426 LGap* gap = new LGap(block);
413 int index = -1; 427 int index = -1;
414 if (instr->IsControl()) { 428 if (instr->IsControl()) {
415 instructions_.Add(gap); 429 instructions_.Add(gap);
416 index = instructions_.length(); 430 index = instructions_.length();
417 instructions_.Add(instr); 431 instructions_.Add(instr);
418 } else { 432 } else {
419 index = instructions_.length(); 433 index = instructions_.length();
420 instructions_.Add(instr); 434 instructions_.Add(instr);
421 instructions_.Add(gap); 435 instructions_.Add(gap);
422 } 436 }
423 if (instr->HasPointerMap()) { 437 if (instr->HasPointerMap()) {
424 pointer_maps_.Add(instr->pointer_map()); 438 pointer_maps_.Add(instr->pointer_map());
425 instr->pointer_map()->set_lithium_position(index); 439 instr->pointer_map()->set_lithium_position(index);
426 } 440 }
427 return index;
428 } 441 }
429 442
430 443
431 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { 444 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
432 return LConstantOperand::Create(constant->id()); 445 return LConstantOperand::Create(constant->id());
433 } 446 }
434 447
435 448
436 int LChunk::GetParameterStackSlot(int index) const { 449 int LChunk::GetParameterStackSlot(int index) const {
437 // The receiver is at index 0, the first parameter at index 1, so we 450 // The receiver is at index 0, the first parameter at index 1, so we
(...skipping 27 matching lines...) Expand all
465 while (!IsGapAt(index)) index--; 478 while (!IsGapAt(index)) index--;
466 return index; 479 return index;
467 } 480 }
468 481
469 482
470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { 483 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); 484 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
472 } 485 }
473 486
474 487
475 class LGapNode: public ZoneObject {
476 public:
477 explicit LGapNode(LOperand* operand)
478 : operand_(operand), resolved_(false), visited_id_(-1) { }
479
480 LOperand* operand() const { return operand_; }
481 bool IsResolved() const { return !IsAssigned() || resolved_; }
482 void MarkResolved() {
483 ASSERT(!IsResolved());
484 resolved_ = true;
485 }
486 int visited_id() const { return visited_id_; }
487 void set_visited_id(int id) {
488 ASSERT(id > visited_id_);
489 visited_id_ = id;
490 }
491
492 bool IsAssigned() const { return assigned_from_.is_set(); }
493 LGapNode* assigned_from() const { return assigned_from_.get(); }
494 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); }
495
496 private:
497 LOperand* operand_;
498 SetOncePointer<LGapNode> assigned_from_;
499 bool resolved_;
500 int visited_id_;
501 };
502
503
504 LGapResolver::LGapResolver(const ZoneList<LMoveOperands>* moves,
505 LOperand* marker_operand)
506 : nodes_(4),
507 identified_cycles_(4),
508 result_(4),
509 marker_operand_(marker_operand),
510 next_visited_id_(0) {
511 for (int i = 0; i < moves->length(); ++i) {
512 LMoveOperands move = moves->at(i);
513 if (!move.IsRedundant()) RegisterMove(move);
514 }
515 }
516
517
518 const ZoneList<LMoveOperands>* LGapResolver::ResolveInReverseOrder() {
519 for (int i = 0; i < identified_cycles_.length(); ++i) {
520 ResolveCycle(identified_cycles_[i]);
521 }
522
523 int unresolved_nodes;
524 do {
525 unresolved_nodes = 0;
526 for (int j = 0; j < nodes_.length(); j++) {
527 LGapNode* node = nodes_[j];
528 if (!node->IsResolved() && node->assigned_from()->IsResolved()) {
529 AddResultMove(node->assigned_from(), node);
530 node->MarkResolved();
531 }
532 if (!node->IsResolved()) ++unresolved_nodes;
533 }
534 } while (unresolved_nodes > 0);
535 return &result_;
536 }
537
538
539 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) {
540 AddResultMove(from->operand(), to->operand());
541 }
542
543
544 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) {
545 result_.Add(LMoveOperands(from, to));
546 }
547
548
549 void LGapResolver::ResolveCycle(LGapNode* start) {
550 ZoneList<LOperand*> circle_operands(8);
551 circle_operands.Add(marker_operand_);
552 LGapNode* cur = start;
553 do {
554 cur->MarkResolved();
555 circle_operands.Add(cur->operand());
556 cur = cur->assigned_from();
557 } while (cur != start);
558 circle_operands.Add(marker_operand_);
559
560 for (int i = circle_operands.length() - 1; i > 0; --i) {
561 LOperand* from = circle_operands[i];
562 LOperand* to = circle_operands[i - 1];
563 AddResultMove(from, to);
564 }
565 }
566
567
568 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) {
569 ASSERT(a != b);
570 LGapNode* cur = a;
571 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) {
572 cur->set_visited_id(visited_id);
573 cur = cur->assigned_from();
574 }
575
576 return cur == b;
577 }
578
579
580 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) {
581 ASSERT(a != b);
582 return CanReach(a, b, next_visited_id_++);
583 }
584
585
586 void LGapResolver::RegisterMove(LMoveOperands move) {
587 if (move.from()->IsConstantOperand()) {
588 // Constant moves should be last in the machine code. Therefore add them
589 // first to the result set.
590 AddResultMove(move.from(), move.to());
591 } else {
592 LGapNode* from = LookupNode(move.from());
593 LGapNode* to = LookupNode(move.to());
594 if (to->IsAssigned() && to->assigned_from() == from) {
595 move.Eliminate();
596 return;
597 }
598 ASSERT(!to->IsAssigned());
599 if (CanReach(from, to)) {
600 // This introduces a circle. Save.
601 identified_cycles_.Add(from);
602 }
603 to->set_assigned_from(from);
604 }
605 }
606
607
608 LGapNode* LGapResolver::LookupNode(LOperand* operand) {
609 for (int i = 0; i < nodes_.length(); ++i) {
610 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i];
611 }
612
613 // No node found => create a new one.
614 LGapNode* result = new LGapNode(operand);
615 nodes_.Add(result);
616 return result;
617 }
618
619
620 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { 488 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
621 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); 489 return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
622 } 490 }
623 491
624 492
625 Representation LChunk::LookupLiteralRepresentation( 493 Representation LChunk::LookupLiteralRepresentation(
626 LConstantOperand* operand) const { 494 LConstantOperand* operand) const {
627 return graph_->LookupValue(operand->index())->representation(); 495 return graph_->LookupValue(operand->index())->representation();
628 } 496 }
629 497
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 } 603 }
736 604
737 605
738 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { 606 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
739 return value->IsConstant() 607 return value->IsConstant()
740 ? chunk_->DefineConstantOperand(HConstant::cast(value)) 608 ? chunk_->DefineConstantOperand(HConstant::cast(value))
741 : UseRegisterAtStart(value); 609 : UseRegisterAtStart(value);
742 } 610 }
743 611
744 612
613 LOperand* LChunkBuilder::UseAny(HValue* value) {
614 return value->IsConstant()
615 ? chunk_->DefineConstantOperand(HConstant::cast(value))
616 : Use(value, new LUnallocated(LUnallocated::ANY));
617 }
618
619
745 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { 620 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
746 if (value->EmitAtUses()) { 621 if (value->EmitAtUses()) {
747 HInstruction* instr = HInstruction::cast(value); 622 HInstruction* instr = HInstruction::cast(value);
748 VisitInstruction(instr); 623 VisitInstruction(instr);
749 } 624 }
750 allocator_->RecordUse(value, operand); 625 allocator_->RecordUse(value, operand);
751 return operand; 626 return operand;
752 } 627 }
753 628
754 629
755 LInstruction* LChunkBuilder::Define(LInstruction* instr) { 630 template<int I, int T>
631 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
632 LUnallocated* result) {
633 allocator_->RecordDefinition(current_instruction_, result);
634 instr->set_result(result);
635 return instr;
636 }
637
638
639 template<int I, int T>
640 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
756 return Define(instr, new LUnallocated(LUnallocated::NONE)); 641 return Define(instr, new LUnallocated(LUnallocated::NONE));
757 } 642 }
758 643
759 644
760 LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) { 645 template<int I, int T>
646 LInstruction* LChunkBuilder::DefineAsRegister(
647 LTemplateInstruction<1, I, T>* instr) {
761 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); 648 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
762 } 649 }
763 650
764 651
765 LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) { 652 template<int I, int T>
653 LInstruction* LChunkBuilder::DefineAsSpilled(
654 LTemplateInstruction<1, I, T>* instr,
655 int index) {
766 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); 656 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
767 } 657 }
768 658
769 659
770 LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) { 660 template<int I, int T>
661 LInstruction* LChunkBuilder::DefineSameAsFirst(
662 LTemplateInstruction<1, I, T>* instr) {
771 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); 663 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
772 } 664 }
773 665
774 666
775 LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) { 667 template<int I, int T>
668 LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
669 Register reg) {
776 return Define(instr, ToUnallocated(reg)); 670 return Define(instr, ToUnallocated(reg));
777 } 671 }
778 672
779 673
780 LInstruction* LChunkBuilder::DefineFixedDouble(LInstruction* instr, 674 template<int I, int T>
781 XMMRegister reg) { 675 LInstruction* LChunkBuilder::DefineFixedDouble(
676 LTemplateInstruction<1, I, T>* instr,
677 XMMRegister reg) {
782 return Define(instr, ToUnallocated(reg)); 678 return Define(instr, ToUnallocated(reg));
783 } 679 }
784 680
785 681
786 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { 682 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
787 HEnvironment* hydrogen_env = current_block_->last_environment(); 683 HEnvironment* hydrogen_env = current_block_->last_environment();
788 instr->set_environment(CreateEnvironment(hydrogen_env)); 684 instr->set_environment(CreateEnvironment(hydrogen_env));
789 return instr; 685 return instr;
790 } 686 }
791 687
792 688
793 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment( 689 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
794 LInstruction* instr, int ast_id) { 690 LInstruction* instr, int ast_id) {
795 ASSERT(instructions_pending_deoptimization_environment_ == NULL); 691 ASSERT(instruction_pending_deoptimization_environment_ == NULL);
796 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); 692 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
797 instructions_pending_deoptimization_environment_ = instr; 693 instruction_pending_deoptimization_environment_ = instr;
798 pending_deoptimization_ast_id_ = ast_id; 694 pending_deoptimization_ast_id_ = ast_id;
799 return instr; 695 return instr;
800 } 696 }
801 697
802 698
803 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() { 699 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
804 instructions_pending_deoptimization_environment_ = NULL; 700 instruction_pending_deoptimization_environment_ = NULL;
805 pending_deoptimization_ast_id_ = AstNode::kNoNumber; 701 pending_deoptimization_ast_id_ = AstNode::kNoNumber;
806 } 702 }
807 703
808 704
809 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, 705 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
810 HInstruction* hinstr, 706 HInstruction* hinstr,
811 CanDeoptimize can_deoptimize) { 707 CanDeoptimize can_deoptimize) {
812 allocator_->MarkAsCall(); 708 #ifdef DEBUG
709 instr->VerifyCall();
710 #endif
711 instr->MarkAsCall();
813 instr = AssignPointerMap(instr); 712 instr = AssignPointerMap(instr);
814 713
815 if (hinstr->HasSideEffects()) { 714 if (hinstr->HasSideEffects()) {
816 ASSERT(hinstr->next()->IsSimulate()); 715 ASSERT(hinstr->next()->IsSimulate());
817 HSimulate* sim = HSimulate::cast(hinstr->next()); 716 HSimulate* sim = HSimulate::cast(hinstr->next());
818 instr = SetInstructionPendingDeoptimizationEnvironment( 717 instr = SetInstructionPendingDeoptimizationEnvironment(
819 instr, sim->ast_id()); 718 instr, sim->ast_id());
820 } 719 }
821 720
822 // If instruction does not have side-effects lazy deoptimization 721 // If instruction does not have side-effects lazy deoptimization
823 // after the call will try to deoptimize to the point before the call. 722 // after the call will try to deoptimize to the point before the call.
824 // Thus we still need to attach environment to this call even if 723 // Thus we still need to attach environment to this call even if
825 // call sequence can not deoptimize eagerly. 724 // call sequence can not deoptimize eagerly.
826 bool needs_environment = 725 bool needs_environment =
827 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); 726 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
828 if (needs_environment && !instr->HasEnvironment()) { 727 if (needs_environment && !instr->HasEnvironment()) {
829 instr = AssignEnvironment(instr); 728 instr = AssignEnvironment(instr);
830 } 729 }
831 730
832 return instr; 731 return instr;
833 } 732 }
834 733
835 734
735 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
736 instr->MarkAsSaveDoubles();
737 return instr;
738 }
739
740
836 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { 741 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
837 ASSERT(!instr->HasPointerMap()); 742 ASSERT(!instr->HasPointerMap());
838 instr->set_pointer_map(new LPointerMap(position_)); 743 instr->set_pointer_map(new LPointerMap(position_));
839 return instr; 744 return instr;
840 } 745 }
841 746
842 747
843 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) {
844 allocator_->RecordDefinition(current_instruction_, result);
845 instr->set_result(result);
846 return instr;
847 }
848
849
850 LOperand* LChunkBuilder::Temp() {
851 LUnallocated* operand = new LUnallocated(LUnallocated::NONE);
852 allocator_->RecordTemporary(operand);
853 return operand;
854 }
855
856
857 LUnallocated* LChunkBuilder::TempRegister() { 748 LUnallocated* LChunkBuilder::TempRegister() {
858 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); 749 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
859 allocator_->RecordTemporary(operand); 750 allocator_->RecordTemporary(operand);
860 return operand; 751 return operand;
861 } 752 }
862 753
863 754
864 LOperand* LChunkBuilder::FixedTemp(Register reg) { 755 LOperand* LChunkBuilder::FixedTemp(Register reg) {
865 LUnallocated* operand = ToUnallocated(reg); 756 LUnallocated* operand = ToUnallocated(reg);
866 allocator_->RecordTemporary(operand); 757 allocator_->RecordTemporary(operand);
(...skipping 13 matching lines...) Expand all
880 } 771 }
881 772
882 773
883 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { 774 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
884 return AssignEnvironment(new LDeoptimize); 775 return AssignEnvironment(new LDeoptimize);
885 } 776 }
886 777
887 778
888 LInstruction* LChunkBuilder::DoBit(Token::Value op, 779 LInstruction* LChunkBuilder::DoBit(Token::Value op,
889 HBitwiseBinaryOperation* instr) { 780 HBitwiseBinaryOperation* instr) {
890 ASSERT(instr->representation().IsInteger32()); 781 if (instr->representation().IsInteger32()) {
891 ASSERT(instr->left()->representation().IsInteger32()); 782 ASSERT(instr->left()->representation().IsInteger32());
892 ASSERT(instr->right()->representation().IsInteger32()); 783 ASSERT(instr->right()->representation().IsInteger32());
893 784
894 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); 785 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
895 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); 786 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
896 return DefineSameAsFirst(new LBitI(op, left, right)); 787 return DefineSameAsFirst(new LBitI(op, left, right));
788 } else {
789 ASSERT(instr->representation().IsTagged());
790 ASSERT(instr->left()->representation().IsTagged());
791 ASSERT(instr->right()->representation().IsTagged());
792
793 LOperand* left = UseFixed(instr->left(), edx);
794 LOperand* right = UseFixed(instr->right(), eax);
795 LArithmeticT* result = new LArithmeticT(op, left, right);
796 return MarkAsCall(DefineFixed(result, eax), instr);
797 }
897 } 798 }
898 799
899 800
900 LInstruction* LChunkBuilder::DoShift(Token::Value op, 801 LInstruction* LChunkBuilder::DoShift(Token::Value op,
901 HBitwiseBinaryOperation* instr) { 802 HBitwiseBinaryOperation* instr) {
803 if (instr->representation().IsTagged()) {
804 ASSERT(instr->left()->representation().IsTagged());
805 ASSERT(instr->right()->representation().IsTagged());
806
807 LOperand* left = UseFixed(instr->left(), edx);
808 LOperand* right = UseFixed(instr->right(), eax);
809 LArithmeticT* result = new LArithmeticT(op, left, right);
810 return MarkAsCall(DefineFixed(result, eax), instr);
811 }
812
902 ASSERT(instr->representation().IsInteger32()); 813 ASSERT(instr->representation().IsInteger32());
903 ASSERT(instr->OperandAt(0)->representation().IsInteger32()); 814 ASSERT(instr->OperandAt(0)->representation().IsInteger32());
904 ASSERT(instr->OperandAt(1)->representation().IsInteger32()); 815 ASSERT(instr->OperandAt(1)->representation().IsInteger32());
905 LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); 816 LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
906 817
907 HValue* right_value = instr->OperandAt(1); 818 HValue* right_value = instr->OperandAt(1);
908 LOperand* right = NULL; 819 LOperand* right = NULL;
909 int constant_value = 0; 820 int constant_value = 0;
910 if (right_value->IsConstant()) { 821 if (right_value->IsConstant()) {
911 HConstant* constant = HConstant::cast(right_value); 822 HConstant* constant = HConstant::cast(right_value);
(...skipping 10 matching lines...) Expand all
922 bool can_truncate = true; 833 bool can_truncate = true;
923 for (int i = 0; i < instr->uses()->length(); i++) { 834 for (int i = 0; i < instr->uses()->length(); i++) {
924 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { 835 if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
925 can_truncate = false; 836 can_truncate = false;
926 break; 837 break;
927 } 838 }
928 } 839 }
929 can_deopt = !can_truncate; 840 can_deopt = !can_truncate;
930 } 841 }
931 842
932 LInstruction* result = 843 LShiftI* result = new LShiftI(op, left, right, can_deopt);
933 DefineSameAsFirst(new LShiftI(op, left, right, can_deopt)); 844 return can_deopt
934 if (can_deopt) AssignEnvironment(result); 845 ? AssignEnvironment(DefineSameAsFirst(result))
935 return result; 846 : DefineSameAsFirst(result);
936 } 847 }
937 848
938 849
939 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, 850 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
940 HArithmeticBinaryOperation* instr) { 851 HArithmeticBinaryOperation* instr) {
941 ASSERT(instr->representation().IsDouble()); 852 ASSERT(instr->representation().IsDouble());
942 ASSERT(instr->left()->representation().IsDouble()); 853 ASSERT(instr->left()->representation().IsDouble());
943 ASSERT(instr->right()->representation().IsDouble()); 854 ASSERT(instr->right()->representation().IsDouble());
944 LOperand* left = UseRegisterAtStart(instr->left()); 855 LOperand* left = UseRegisterAtStart(instr->left());
945 LOperand* right = UseRegisterAtStart(instr->right()); 856 LOperand* right = UseRegisterAtStart(instr->right());
946 LArithmeticD* result = new LArithmeticD(op, left, right); 857 LArithmeticD* result = new LArithmeticD(op, left, right);
947 return DefineSameAsFirst(result); 858 return DefineSameAsFirst(result);
948 } 859 }
949 860
950 861
951 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, 862 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
952 HArithmeticBinaryOperation* instr) { 863 HArithmeticBinaryOperation* instr) {
953 ASSERT(op == Token::ADD || 864 ASSERT(op == Token::ADD ||
954 op == Token::DIV || 865 op == Token::DIV ||
955 op == Token::MOD || 866 op == Token::MOD ||
956 op == Token::MUL || 867 op == Token::MUL ||
957 op == Token::SUB); 868 op == Token::SUB);
958 HValue* left = instr->left(); 869 HValue* left = instr->left();
959 HValue* right = instr->right(); 870 HValue* right = instr->right();
960 ASSERT(left->representation().IsTagged()); 871 ASSERT(left->representation().IsTagged());
961 ASSERT(right->representation().IsTagged()); 872 ASSERT(right->representation().IsTagged());
962 LOperand* left_operand = UseFixed(left, edx); 873 LOperand* left_operand = UseFixed(left, edx);
963 LOperand* right_operand = UseFixed(right, eax); 874 LOperand* right_operand = UseFixed(right, eax);
964 LInstruction* result = new LArithmeticT(op, left_operand, right_operand); 875 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
965 return MarkAsCall(DefineFixed(result, eax), instr); 876 return MarkAsCall(DefineFixed(result, eax), instr);
966 } 877 }
967 878
968 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { 879 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
969 ASSERT(is_building()); 880 ASSERT(is_building());
970 current_block_ = block; 881 current_block_ = block;
971 next_block_ = next_block; 882 next_block_ = next_block;
972 if (block->IsStartBlock()) { 883 if (block->IsStartBlock()) {
973 block->UpdateEnvironment(graph_->start_environment()); 884 block->UpdateEnvironment(graph_->start_environment());
974 argument_count_ = 0; 885 argument_count_ = 0;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 } 935 }
1025 block->set_argument_count(argument_count_); 936 block->set_argument_count(argument_count_);
1026 next_block_ = NULL; 937 next_block_ = NULL;
1027 current_block_ = NULL; 938 current_block_ = NULL;
1028 } 939 }
1029 940
1030 941
1031 void LChunkBuilder::VisitInstruction(HInstruction* current) { 942 void LChunkBuilder::VisitInstruction(HInstruction* current) {
1032 HInstruction* old_current = current_instruction_; 943 HInstruction* old_current = current_instruction_;
1033 current_instruction_ = current; 944 current_instruction_ = current;
1034 allocator_->BeginInstruction();
1035 if (current->has_position()) position_ = current->position(); 945 if (current->has_position()) position_ = current->position();
1036 LInstruction* instr = current->CompileToLithium(this); 946 LInstruction* instr = current->CompileToLithium(this);
1037 947
1038 if (instr != NULL) { 948 if (instr != NULL) {
1039 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { 949 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
1040 instr = AssignPointerMap(instr); 950 instr = AssignPointerMap(instr);
1041 } 951 }
1042 if (FLAG_stress_environments && !instr->HasEnvironment()) { 952 if (FLAG_stress_environments && !instr->HasEnvironment()) {
1043 instr = AssignEnvironment(instr); 953 instr = AssignEnvironment(instr);
1044 } 954 }
1045 if (current->IsBranch()) { 955 if (current->IsTest() && !instr->IsGoto()) {
1046 instr->set_hydrogen_value(HBranch::cast(current)->value()); 956 ASSERT(instr->IsControl());
957 HTest* test = HTest::cast(current);
958 instr->set_hydrogen_value(test->value());
959 HBasicBlock* first = test->FirstSuccessor();
960 HBasicBlock* second = test->SecondSuccessor();
961 ASSERT(first != NULL && second != NULL);
962 instr->SetBranchTargets(first->block_id(), second->block_id());
1047 } else { 963 } else {
1048 instr->set_hydrogen_value(current); 964 instr->set_hydrogen_value(current);
1049 } 965 }
1050 966
1051 int index = chunk_->AddInstruction(instr, current_block_); 967 chunk_->AddInstruction(instr, current_block_);
1052 allocator_->SummarizeInstruction(index);
1053 } else {
1054 // This instruction should be omitted.
1055 allocator_->OmitInstruction();
1056 } 968 }
1057 current_instruction_ = old_current; 969 current_instruction_ = old_current;
1058 } 970 }
1059 971
1060 972
1061 void LEnvironment::WriteTranslation(LCodeGen* cgen,
1062 Translation* translation) const {
1063 if (this == NULL) return;
1064
1065 // The translation includes one command per value in the environment.
1066 int translation_size = values()->length();
1067 // The output frame height does not include the parameters.
1068 int height = translation_size - parameter_count();
1069
1070 outer()->WriteTranslation(cgen, translation);
1071 int closure_id = cgen->DefineDeoptimizationLiteral(closure());
1072 translation->BeginFrame(ast_id(), closure_id, height);
1073 for (int i = 0; i < translation_size; ++i) {
1074 LOperand* value = values()->at(i);
1075 // spilled_registers_ and spilled_double_registers_ are either
1076 // both NULL or both set.
1077 if (spilled_registers_ != NULL && value != NULL) {
1078 if (value->IsRegister() &&
1079 spilled_registers_[value->index()] != NULL) {
1080 translation->MarkDuplicate();
1081 cgen->AddToTranslation(translation,
1082 spilled_registers_[value->index()],
1083 HasTaggedValueAt(i));
1084 } else if (value->IsDoubleRegister() &&
1085 spilled_double_registers_[value->index()] != NULL) {
1086 translation->MarkDuplicate();
1087 cgen->AddToTranslation(translation,
1088 spilled_double_registers_[value->index()],
1089 false);
1090 }
1091 }
1092
1093 cgen->AddToTranslation(translation, value, HasTaggedValueAt(i));
1094 }
1095 }
1096
1097
1098 void LEnvironment::PrintTo(StringStream* stream) const {
1099 stream->Add("[id=%d|", ast_id());
1100 stream->Add("[parameters=%d|", parameter_count());
1101 stream->Add("[arguments_stack_height=%d|", arguments_stack_height());
1102 for (int i = 0; i < values_.length(); ++i) {
1103 if (i != 0) stream->Add(";");
1104 if (values_[i] == NULL) {
1105 stream->Add("[hole]");
1106 } else {
1107 values_[i]->PrintTo(stream);
1108 }
1109 }
1110 stream->Add("]");
1111 }
1112
1113
1114 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { 973 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
1115 if (hydrogen_env == NULL) return NULL; 974 if (hydrogen_env == NULL) return NULL;
1116 975
1117 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); 976 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
1118 int ast_id = hydrogen_env->ast_id(); 977 int ast_id = hydrogen_env->ast_id();
1119 ASSERT(ast_id != AstNode::kNoNumber); 978 ASSERT(ast_id != AstNode::kNoNumber);
1120 int value_count = hydrogen_env->length(); 979 int value_count = hydrogen_env->length();
1121 LEnvironment* result = new LEnvironment(hydrogen_env->closure(), 980 LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
1122 ast_id, 981 ast_id,
1123 hydrogen_env->parameter_count(), 982 hydrogen_env->parameter_count(),
1124 argument_count_, 983 argument_count_,
1125 value_count, 984 value_count,
1126 outer); 985 outer);
1127 int argument_index = 0; 986 int argument_index = 0;
1128 for (int i = 0; i < value_count; ++i) { 987 for (int i = 0; i < value_count; ++i) {
1129 HValue* value = hydrogen_env->values()->at(i); 988 HValue* value = hydrogen_env->values()->at(i);
1130 LOperand* op = NULL; 989 LOperand* op = NULL;
1131 if (value->IsArgumentsObject()) { 990 if (value->IsArgumentsObject()) {
1132 op = NULL; 991 op = NULL;
1133 } else if (value->IsPushArgument()) { 992 } else if (value->IsPushArgument()) {
1134 op = new LArgument(argument_index++); 993 op = new LArgument(argument_index++);
1135 } else { 994 } else {
1136 op = UseOrConstant(value); 995 op = UseAny(value);
1137 if (op->IsUnallocated()) {
1138 LUnallocated* unalloc = LUnallocated::cast(op);
1139 unalloc->set_policy(LUnallocated::ANY);
1140 }
1141 } 996 }
1142 result->AddValue(op, value->representation()); 997 result->AddValue(op, value->representation());
1143 } 998 }
1144 999
1145 return result; 1000 return result;
1146 } 1001 }
1147 1002
1148 1003
1149 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { 1004 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
1150 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(), 1005 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(),
1151 instr->include_stack_check()); 1006 instr->include_stack_check());
1152 if (instr->include_stack_check()) result = AssignPointerMap(result); 1007 return (instr->include_stack_check())
1153 return result; 1008 ? AssignPointerMap(result)
1009 : result;
1154 } 1010 }
1155 1011
1156 1012
1157 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { 1013 LInstruction* LChunkBuilder::DoTest(HTest* instr) {
1158 HValue* v = instr->value(); 1014 HValue* v = instr->value();
1159 HBasicBlock* first = instr->FirstSuccessor();
1160 HBasicBlock* second = instr->SecondSuccessor();
1161 ASSERT(first != NULL && second != NULL);
1162 int first_id = first->block_id();
1163 int second_id = second->block_id();
1164
1165 if (v->EmitAtUses()) { 1015 if (v->EmitAtUses()) {
1166 if (v->IsClassOfTest()) { 1016 if (v->IsClassOfTest()) {
1167 HClassOfTest* compare = HClassOfTest::cast(v); 1017 HClassOfTest* compare = HClassOfTest::cast(v);
1168 ASSERT(compare->value()->representation().IsTagged()); 1018 ASSERT(compare->value()->representation().IsTagged());
1169 1019
1170 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), 1020 return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
1171 TempRegister(), 1021 TempRegister(),
1172 TempRegister(), 1022 TempRegister());
1173 first_id,
1174 second_id);
1175 } else if (v->IsCompare()) { 1023 } else if (v->IsCompare()) {
1176 HCompare* compare = HCompare::cast(v); 1024 HCompare* compare = HCompare::cast(v);
1177 Token::Value op = compare->token(); 1025 Token::Value op = compare->token();
1178 HValue* left = compare->left(); 1026 HValue* left = compare->left();
1179 HValue* right = compare->right(); 1027 HValue* right = compare->right();
1180 if (left->representation().IsInteger32()) { 1028 Representation r = compare->GetInputRepresentation();
1029 if (r.IsInteger32()) {
1030 ASSERT(left->representation().IsInteger32());
1181 ASSERT(right->representation().IsInteger32()); 1031 ASSERT(right->representation().IsInteger32());
1182 return new LCmpIDAndBranch(op, 1032
1183 UseRegisterAtStart(left), 1033 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1184 UseOrConstantAtStart(right), 1034 UseOrConstantAtStart(right));
1185 first_id, 1035 } else if (r.IsDouble()) {
1186 second_id, 1036 ASSERT(left->representation().IsDouble());
1187 false);
1188 } else if (left->representation().IsDouble()) {
1189 ASSERT(right->representation().IsDouble()); 1037 ASSERT(right->representation().IsDouble());
1190 return new LCmpIDAndBranch(op, 1038
1191 UseRegisterAtStart(left), 1039 return new LCmpIDAndBranch(UseRegisterAtStart(left),
1192 UseRegisterAtStart(right), 1040 UseRegisterAtStart(right));
1193 first_id,
1194 second_id,
1195 true);
1196 } else { 1041 } else {
1197 ASSERT(left->representation().IsTagged()); 1042 ASSERT(left->representation().IsTagged());
1198 ASSERT(right->representation().IsTagged()); 1043 ASSERT(right->representation().IsTagged());
1199 bool reversed = op == Token::GT || op == Token::LTE; 1044 bool reversed = op == Token::GT || op == Token::LTE;
1200 LOperand* left_operand = UseFixed(left, reversed ? eax : edx); 1045 LOperand* left_operand = UseFixed(left, reversed ? eax : edx);
1201 LOperand* right_operand = UseFixed(right, reversed ? edx : eax); 1046 LOperand* right_operand = UseFixed(right, reversed ? edx : eax);
1202 LInstruction* result = new LCmpTAndBranch(left_operand, 1047 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand,
1203 right_operand, 1048 right_operand);
1204 first_id,
1205 second_id);
1206 return MarkAsCall(result, instr); 1049 return MarkAsCall(result, instr);
1207 } 1050 }
1208 } else if (v->IsIsSmi()) { 1051 } else if (v->IsIsSmi()) {
1209 HIsSmi* compare = HIsSmi::cast(v); 1052 HIsSmi* compare = HIsSmi::cast(v);
1210 ASSERT(compare->value()->representation().IsTagged()); 1053 ASSERT(compare->value()->representation().IsTagged());
1211 1054
1212 return new LIsSmiAndBranch(Use(compare->value()), 1055 return new LIsSmiAndBranch(Use(compare->value()));
1213 first_id,
1214 second_id);
1215 } else if (v->IsHasInstanceType()) { 1056 } else if (v->IsHasInstanceType()) {
1216 HHasInstanceType* compare = HHasInstanceType::cast(v); 1057 HHasInstanceType* compare = HHasInstanceType::cast(v);
1217 ASSERT(compare->value()->representation().IsTagged()); 1058 ASSERT(compare->value()->representation().IsTagged());
1218 1059
1219 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), 1060 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
1220 TempRegister(), 1061 TempRegister());
1221 first_id,
1222 second_id);
1223 } else if (v->IsHasCachedArrayIndex()) { 1062 } else if (v->IsHasCachedArrayIndex()) {
1224 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); 1063 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
1225 ASSERT(compare->value()->representation().IsTagged()); 1064 ASSERT(compare->value()->representation().IsTagged());
1226 1065
1227 return new LHasCachedArrayIndexAndBranch( 1066 return new LHasCachedArrayIndexAndBranch(
1228 UseRegisterAtStart(compare->value()), first_id, second_id); 1067 UseRegisterAtStart(compare->value()));
1229 } else if (v->IsIsNull()) { 1068 } else if (v->IsIsNull()) {
1230 HIsNull* compare = HIsNull::cast(v); 1069 HIsNull* compare = HIsNull::cast(v);
1231 ASSERT(compare->value()->representation().IsTagged()); 1070 ASSERT(compare->value()->representation().IsTagged());
1232 1071
1233 // We only need a temp register for non-strict compare. 1072 // We only need a temp register for non-strict compare.
1234 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); 1073 LOperand* temp = compare->is_strict() ? NULL : TempRegister();
1235 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), 1074 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
1236 compare->is_strict(), 1075 temp);
1237 temp,
1238 first_id,
1239 second_id);
1240 } else if (v->IsIsObject()) { 1076 } else if (v->IsIsObject()) {
1241 HIsObject* compare = HIsObject::cast(v); 1077 HIsObject* compare = HIsObject::cast(v);
1242 ASSERT(compare->value()->representation().IsTagged()); 1078 ASSERT(compare->value()->representation().IsTagged());
1243 1079
1244 LOperand* temp1 = TempRegister(); 1080 LOperand* temp1 = TempRegister();
1245 LOperand* temp2 = TempRegister(); 1081 LOperand* temp2 = TempRegister();
1246 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), 1082 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
1247 temp1, 1083 temp1,
1248 temp2, 1084 temp2);
1249 first_id,
1250 second_id);
1251 } else if (v->IsCompareJSObjectEq()) { 1085 } else if (v->IsCompareJSObjectEq()) {
1252 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); 1086 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
1253 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), 1087 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
1254 UseRegisterAtStart(compare->right()), 1088 UseRegisterAtStart(compare->right()));
1255 first_id,
1256 second_id);
1257 } else if (v->IsInstanceOf()) { 1089 } else if (v->IsInstanceOf()) {
1258 HInstanceOf* instance_of = HInstanceOf::cast(v); 1090 HInstanceOf* instance_of = HInstanceOf::cast(v);
1259 LInstruction* result = 1091 LOperand* left = UseFixed(instance_of->left(), InstanceofStub::left());
1260 new LInstanceOfAndBranch(UseFixed(instance_of->left(), eax), 1092 LOperand* right = UseFixed(instance_of->right(), InstanceofStub::right());
1261 UseFixed(instance_of->right(), edx), 1093 LOperand* context = UseFixed(instance_of->context(), esi);
1262 first_id, 1094 LInstanceOfAndBranch* result =
1263 second_id); 1095 new LInstanceOfAndBranch(context, left, right);
1264 return MarkAsCall(result, instr); 1096 return MarkAsCall(result, instr);
1265 } else if (v->IsTypeofIs()) { 1097 } else if (v->IsTypeofIs()) {
1266 HTypeofIs* typeof_is = HTypeofIs::cast(v); 1098 HTypeofIs* typeof_is = HTypeofIs::cast(v);
1267 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), 1099 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
1268 first_id, 1100 } else if (v->IsIsConstructCall()) {
1269 second_id); 1101 return new LIsConstructCallAndBranch(TempRegister());
1270 } else { 1102 } else {
1271 if (v->IsConstant()) { 1103 if (v->IsConstant()) {
1272 if (HConstant::cast(v)->handle()->IsTrue()) { 1104 if (HConstant::cast(v)->handle()->IsTrue()) {
1273 return new LGoto(first_id); 1105 return new LGoto(instr->FirstSuccessor()->block_id());
1274 } else if (HConstant::cast(v)->handle()->IsFalse()) { 1106 } else if (HConstant::cast(v)->handle()->IsFalse()) {
1275 return new LGoto(second_id); 1107 return new LGoto(instr->SecondSuccessor()->block_id());
1276 } 1108 }
1277 } 1109 }
1278 Abort("Undefined compare before branch"); 1110 Abort("Undefined compare before branch");
1279 return NULL; 1111 return NULL;
1280 } 1112 }
1281 } 1113 }
1282 return new LBranch(UseRegisterAtStart(v), first_id, second_id); 1114 return new LBranch(UseRegisterAtStart(v));
1283 } 1115 }
1284 1116
1285 1117
1286 LInstruction* LChunkBuilder::DoCompareMapAndBranch( 1118 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
1287 HCompareMapAndBranch* instr) {
1288 ASSERT(instr->value()->representation().IsTagged()); 1119 ASSERT(instr->value()->representation().IsTagged());
1289 LOperand* value = UseRegisterAtStart(instr->value()); 1120 LOperand* value = UseRegisterAtStart(instr->value());
1290 HBasicBlock* first = instr->FirstSuccessor(); 1121 return new LCmpMapAndBranch(value);
1291 HBasicBlock* second = instr->SecondSuccessor();
1292 return new LCmpMapAndBranch(value,
1293 instr->map(),
1294 first->block_id(),
1295 second->block_id());
1296 } 1122 }
1297 1123
1298 1124
1299 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { 1125 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
1300 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); 1126 return DefineAsRegister(new LArgumentsLength(Use(length->value())));
1301 } 1127 }
1302 1128
1303 1129
1304 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { 1130 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
1305 return DefineAsRegister(new LArgumentsElements); 1131 return DefineAsRegister(new LArgumentsElements);
1306 } 1132 }
1307 1133
1308 1134
1309 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { 1135 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
1310 LInstruction* result = 1136 LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
1311 new LInstanceOf(UseFixed(instr->left(), eax), 1137 LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
1312 UseFixed(instr->right(), edx)); 1138 LOperand* context = UseFixed(instr->context(), esi);
1139 LInstanceOf* result = new LInstanceOf(context, left, right);
1313 return MarkAsCall(DefineFixed(result, eax), instr); 1140 return MarkAsCall(DefineFixed(result, eax), instr);
1314 } 1141 }
1315 1142
1316 1143
1144 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
1145 HInstanceOfKnownGlobal* instr) {
1146 LInstanceOfKnownGlobal* result =
1147 new LInstanceOfKnownGlobal(
1148 UseFixed(instr->value(), InstanceofStub::left()),
1149 FixedTemp(edi));
1150 MarkAsSaveDoubles(result);
1151 return AssignEnvironment(AssignPointerMap(DefineFixed(result, eax)));
1152 }
1153
1154
1317 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { 1155 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
1318 LOperand* function = UseFixed(instr->function(), edi); 1156 LOperand* function = UseFixed(instr->function(), edi);
1319 LOperand* receiver = UseFixed(instr->receiver(), eax); 1157 LOperand* receiver = UseFixed(instr->receiver(), eax);
1320 LOperand* length = UseRegisterAtStart(instr->length()); 1158 LOperand* length = UseFixed(instr->length(), ebx);
1321 LOperand* elements = UseRegisterAtStart(instr->elements()); 1159 LOperand* elements = UseFixed(instr->elements(), ecx);
1322 LInstruction* result = new LApplyArguments(function, 1160 LOperand* temp = FixedTemp(edx);
1323 receiver, 1161 LApplyArguments* result = new LApplyArguments(function,
1324 length, 1162 receiver,
1325 elements); 1163 length,
1164 elements,
1165 temp);
1326 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); 1166 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
1327 } 1167 }
1328 1168
1329 1169
1330 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { 1170 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
1331 ++argument_count_; 1171 ++argument_count_;
1332 LOperand* argument = UseOrConstant(instr->argument()); 1172 LOperand* argument = UseOrConstant(instr->argument());
1333 return new LPushArgument(argument); 1173 return new LPushArgument(argument);
1334 } 1174 }
1335 1175
1336 1176
1177 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
1178 return DefineAsRegister(new LContext);
1179 }
1180
1181
1182 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
1183 LOperand* context = UseRegisterAtStart(instr->value());
1184 return DefineAsRegister(new LOuterContext(context));
1185 }
1186
1187
1337 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { 1188 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
1338 return DefineAsRegister(new LGlobalObject); 1189 LOperand* context = UseRegisterAtStart(instr->value());
1190 return DefineAsRegister(new LGlobalObject(context));
1339 } 1191 }
1340 1192
1341 1193
1342 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { 1194 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
1343 return DefineAsRegister(new LGlobalReceiver); 1195 LOperand* global_object = UseRegisterAtStart(instr->value());
1196 return DefineAsRegister(new LGlobalReceiver(global_object));
1344 } 1197 }
1345 1198
1346 1199
1347 LInstruction* LChunkBuilder::DoCallConstantFunction( 1200 LInstruction* LChunkBuilder::DoCallConstantFunction(
1348 HCallConstantFunction* instr) { 1201 HCallConstantFunction* instr) {
1349 argument_count_ -= instr->argument_count(); 1202 argument_count_ -= instr->argument_count();
1350 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr); 1203 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr);
1351 } 1204 }
1352 1205
1353 1206
1354 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { 1207 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
1355 BuiltinFunctionId op = instr->op(); 1208 BuiltinFunctionId op = instr->op();
1356 if (op == kMathLog || op == kMathSin || op == kMathCos) { 1209 if (op == kMathLog || op == kMathSin || op == kMathCos) {
1357 LOperand* input = UseFixedDouble(instr->value(), xmm1); 1210 LOperand* input = UseFixedDouble(instr->value(), xmm1);
1358 LInstruction* result = new LUnaryMathOperation(input); 1211 LUnaryMathOperation* result = new LUnaryMathOperation(input);
1359 return MarkAsCall(DefineFixedDouble(result, xmm1), instr); 1212 return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
1360 } else { 1213 } else {
1361 LOperand* input = UseRegisterAtStart(instr->value()); 1214 LOperand* input = UseRegisterAtStart(instr->value());
1362 LInstruction* result = new LUnaryMathOperation(input); 1215 LUnaryMathOperation* result = new LUnaryMathOperation(input);
1363 switch (op) { 1216 switch (op) {
1364 case kMathAbs: 1217 case kMathAbs:
1365 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); 1218 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1366 case kMathFloor: 1219 case kMathFloor:
1367 return AssignEnvironment(DefineAsRegister(result)); 1220 return AssignEnvironment(DefineAsRegister(result));
1368 case kMathRound: 1221 case kMathRound:
1369 return AssignEnvironment(DefineAsRegister(result)); 1222 return AssignEnvironment(DefineAsRegister(result));
1370 case kMathSqrt: 1223 case kMathSqrt:
1371 return DefineSameAsFirst(result); 1224 return DefineSameAsFirst(result);
1372 case kMathPowHalf: 1225 case kMathPowHalf:
1373 return AssignEnvironment(DefineSameAsFirst(result)); 1226 return AssignEnvironment(DefineSameAsFirst(result));
1374 default: 1227 default:
1375 UNREACHABLE(); 1228 UNREACHABLE();
1376 return NULL; 1229 return NULL;
1377 } 1230 }
1378 } 1231 }
1379 } 1232 }
1380 1233
1381 1234
1382 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { 1235 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
1383 ASSERT(instr->key()->representation().IsTagged()); 1236 ASSERT(instr->key()->representation().IsTagged());
1237 LOperand* context = UseFixed(instr->context(), esi);
1238 LOperand* key = UseFixed(instr->key(), ecx);
1384 argument_count_ -= instr->argument_count(); 1239 argument_count_ -= instr->argument_count();
1385 UseFixed(instr->key(), ecx); 1240 LCallKeyed* result = new LCallKeyed(context, key);
1386 return MarkAsCall(DefineFixed(new LCallKeyed, eax), instr); 1241 return MarkAsCall(DefineFixed(result, eax), instr);
1387 } 1242 }
1388 1243
1389 1244
1390 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { 1245 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
1246 LOperand* context = UseFixed(instr->context(), esi);
1391 argument_count_ -= instr->argument_count(); 1247 argument_count_ -= instr->argument_count();
1392 return MarkAsCall(DefineFixed(new LCallNamed, eax), instr); 1248 LCallNamed* result = new LCallNamed(context);
1249 return MarkAsCall(DefineFixed(result, eax), instr);
1393 } 1250 }
1394 1251
1395 1252
1396 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { 1253 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
1254 LOperand* context = UseFixed(instr->context(), esi);
1397 argument_count_ -= instr->argument_count(); 1255 argument_count_ -= instr->argument_count();
1398 return MarkAsCall(DefineFixed(new LCallGlobal, eax), instr); 1256 LCallGlobal* result = new LCallGlobal(context);
1257 return MarkAsCall(DefineFixed(result, eax), instr);
1399 } 1258 }
1400 1259
1401 1260
1402 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { 1261 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
1403 argument_count_ -= instr->argument_count(); 1262 argument_count_ -= instr->argument_count();
1404 return MarkAsCall(DefineFixed(new LCallKnownGlobal, eax), instr); 1263 return MarkAsCall(DefineFixed(new LCallKnownGlobal, eax), instr);
1405 } 1264 }
1406 1265
1407 1266
1408 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { 1267 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
1268 LOperand* context = UseFixed(instr->context(), esi);
1409 LOperand* constructor = UseFixed(instr->constructor(), edi); 1269 LOperand* constructor = UseFixed(instr->constructor(), edi);
1410 argument_count_ -= instr->argument_count(); 1270 argument_count_ -= instr->argument_count();
1411 LInstruction* result = new LCallNew(constructor); 1271 LCallNew* result = new LCallNew(context, constructor);
1412 return MarkAsCall(DefineFixed(result, eax), instr); 1272 return MarkAsCall(DefineFixed(result, eax), instr);
1413 } 1273 }
1414 1274
1415 1275
1416 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { 1276 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
1277 LOperand* context = UseFixed(instr->context(), esi);
1417 argument_count_ -= instr->argument_count(); 1278 argument_count_ -= instr->argument_count();
1418 return MarkAsCall(DefineFixed(new LCallFunction, eax), instr); 1279 LCallFunction* result = new LCallFunction(context);
1280 return MarkAsCall(DefineFixed(result, eax), instr);
1419 } 1281 }
1420 1282
1421 1283
1422 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) { 1284 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
1423 argument_count_ -= instr->argument_count(); 1285 argument_count_ -= instr->argument_count();
1424 return MarkAsCall(DefineFixed(new LCallRuntime, eax), instr); 1286 return MarkAsCall(DefineFixed(new LCallRuntime, eax), instr);
1425 } 1287 }
1426 1288
1427 1289
1428 LInstruction* LChunkBuilder::DoShr(HShr* instr) { 1290 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
(...skipping 12 matching lines...) Expand all
1441 1303
1442 1304
1443 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { 1305 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
1444 return DoBit(Token::BIT_AND, instr); 1306 return DoBit(Token::BIT_AND, instr);
1445 } 1307 }
1446 1308
1447 1309
1448 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { 1310 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
1449 ASSERT(instr->value()->representation().IsInteger32()); 1311 ASSERT(instr->value()->representation().IsInteger32());
1450 ASSERT(instr->representation().IsInteger32()); 1312 ASSERT(instr->representation().IsInteger32());
1451 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value()))); 1313 LOperand* input = UseRegisterAtStart(instr->value());
1314 LBitNotI* result = new LBitNotI(input);
1315 return DefineSameAsFirst(result);
1452 } 1316 }
1453 1317
1454 1318
1455 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { 1319 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
1456 return DoBit(Token::BIT_OR, instr); 1320 return DoBit(Token::BIT_OR, instr);
1457 } 1321 }
1458 1322
1459 1323
1460 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { 1324 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
1461 return DoBit(Token::BIT_XOR, instr); 1325 return DoBit(Token::BIT_XOR, instr);
1462 } 1326 }
1463 1327
1464 1328
1465 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1329 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1466 if (instr->representation().IsDouble()) { 1330 if (instr->representation().IsDouble()) {
1467 return DoArithmeticD(Token::DIV, instr); 1331 return DoArithmeticD(Token::DIV, instr);
1468 } else if (instr->representation().IsInteger32()) { 1332 } else if (instr->representation().IsInteger32()) {
1469 // The temporary operand is necessary to ensure that right is not allocated 1333 // The temporary operand is necessary to ensure that right is not allocated
1470 // into edx. 1334 // into edx.
1471 FixedTemp(edx); 1335 LOperand* temp = FixedTemp(edx);
1472 LOperand* value = UseFixed(instr->left(), eax); 1336 LOperand* dividend = UseFixed(instr->left(), eax);
1473 LOperand* divisor = UseRegister(instr->right()); 1337 LOperand* divisor = UseRegister(instr->right());
1474 return AssignEnvironment(DefineFixed(new LDivI(value, divisor), eax)); 1338 LDivI* result = new LDivI(dividend, divisor, temp);
1339 return AssignEnvironment(DefineFixed(result, eax));
1475 } else { 1340 } else {
1476 ASSERT(instr->representation().IsTagged()); 1341 ASSERT(instr->representation().IsTagged());
1477 return DoArithmeticT(Token::DIV, instr); 1342 return DoArithmeticT(Token::DIV, instr);
1478 } 1343 }
1479 } 1344 }
1480 1345
1481 1346
1482 LInstruction* LChunkBuilder::DoMod(HMod* instr) { 1347 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1483 if (instr->representation().IsInteger32()) { 1348 if (instr->representation().IsInteger32()) {
1484 ASSERT(instr->left()->representation().IsInteger32()); 1349 ASSERT(instr->left()->representation().IsInteger32());
1485 ASSERT(instr->right()->representation().IsInteger32()); 1350 ASSERT(instr->right()->representation().IsInteger32());
1486 // The temporary operand is necessary to ensure that right is not allocated 1351 // The temporary operand is necessary to ensure that right is not allocated
1487 // into edx. 1352 // into edx.
1488 FixedTemp(edx); 1353 LOperand* temp = FixedTemp(edx);
1489 LOperand* value = UseFixed(instr->left(), eax); 1354 LOperand* value = UseFixed(instr->left(), eax);
1490 LOperand* divisor = UseRegister(instr->right()); 1355 LOperand* divisor = UseRegister(instr->right());
1491 LInstruction* result = DefineFixed(new LModI(value, divisor), edx); 1356 LModI* mod = new LModI(value, divisor, temp);
1492 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || 1357 LInstruction* result = DefineFixed(mod, edx);
1493 instr->CheckFlag(HValue::kCanBeDivByZero)) { 1358 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
1494 result = AssignEnvironment(result); 1359 instr->CheckFlag(HValue::kCanBeDivByZero))
1495 } 1360 ? AssignEnvironment(result)
1496 return result; 1361 : result;
1497 } else if (instr->representation().IsTagged()) { 1362 } else if (instr->representation().IsTagged()) {
1498 return DoArithmeticT(Token::MOD, instr); 1363 return DoArithmeticT(Token::MOD, instr);
1499 } else { 1364 } else {
1500 ASSERT(instr->representation().IsDouble()); 1365 ASSERT(instr->representation().IsDouble());
1501 // We call a C function for double modulo. It can't trigger a GC. 1366 // We call a C function for double modulo. It can't trigger a GC.
1502 // We need to use fixed result register for the call. 1367 // We need to use fixed result register for the call.
1503 // TODO(fschneider): Allow any register as input registers. 1368 // TODO(fschneider): Allow any register as input registers.
1504 LOperand* left = UseFixedDouble(instr->left(), xmm1); 1369 LOperand* left = UseFixedDouble(instr->left(), xmm1);
1505 LOperand* right = UseFixedDouble(instr->right(), xmm2); 1370 LOperand* right = UseFixedDouble(instr->right(), xmm2);
1506 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); 1371 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
(...skipping 20 matching lines...) Expand all
1527 ASSERT(instr->representation().IsTagged()); 1392 ASSERT(instr->representation().IsTagged());
1528 return DoArithmeticT(Token::MUL, instr); 1393 return DoArithmeticT(Token::MUL, instr);
1529 } 1394 }
1530 } 1395 }
1531 1396
1532 1397
1533 LInstruction* LChunkBuilder::DoSub(HSub* instr) { 1398 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
1534 if (instr->representation().IsInteger32()) { 1399 if (instr->representation().IsInteger32()) {
1535 ASSERT(instr->left()->representation().IsInteger32()); 1400 ASSERT(instr->left()->representation().IsInteger32());
1536 ASSERT(instr->right()->representation().IsInteger32()); 1401 ASSERT(instr->right()->representation().IsInteger32());
1537 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); 1402 LOperand* left = UseRegisterAtStart(instr->left());
1538 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); 1403 LOperand* right = UseOrConstantAtStart(instr->right());
1539 LSubI* sub = new LSubI(left, right); 1404 LSubI* sub = new LSubI(left, right);
1540 LInstruction* result = DefineSameAsFirst(sub); 1405 LInstruction* result = DefineSameAsFirst(sub);
1541 if (instr->CheckFlag(HValue::kCanOverflow)) { 1406 if (instr->CheckFlag(HValue::kCanOverflow)) {
1542 result = AssignEnvironment(result); 1407 result = AssignEnvironment(result);
1543 } 1408 }
1544 return result; 1409 return result;
1545 } else if (instr->representation().IsDouble()) { 1410 } else if (instr->representation().IsDouble()) {
1546 return DoArithmeticD(Token::SUB, instr); 1411 return DoArithmeticD(Token::SUB, instr);
1547 } else { 1412 } else {
1548 ASSERT(instr->representation().IsTagged()); 1413 ASSERT(instr->representation().IsTagged());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1583 UseFixedDouble(instr->right(), xmm2) : 1448 UseFixedDouble(instr->right(), xmm2) :
1584 UseFixed(instr->right(), eax); 1449 UseFixed(instr->right(), eax);
1585 LPower* result = new LPower(left, right); 1450 LPower* result = new LPower(left, right);
1586 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, 1451 return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
1587 CAN_DEOPTIMIZE_EAGERLY); 1452 CAN_DEOPTIMIZE_EAGERLY);
1588 } 1453 }
1589 1454
1590 1455
1591 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { 1456 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
1592 Token::Value op = instr->token(); 1457 Token::Value op = instr->token();
1593 if (instr->left()->representation().IsInteger32()) { 1458 Representation r = instr->GetInputRepresentation();
1459 if (r.IsInteger32()) {
1460 ASSERT(instr->left()->representation().IsInteger32());
1594 ASSERT(instr->right()->representation().IsInteger32()); 1461 ASSERT(instr->right()->representation().IsInteger32());
1595 LOperand* left = UseRegisterAtStart(instr->left()); 1462 LOperand* left = UseRegisterAtStart(instr->left());
1596 LOperand* right = UseOrConstantAtStart(instr->right()); 1463 LOperand* right = UseOrConstantAtStart(instr->right());
1597 return DefineAsRegister(new LCmpID(op, left, right, false)); 1464 return DefineAsRegister(new LCmpID(left, right));
1598 } else if (instr->left()->representation().IsDouble()) { 1465 } else if (r.IsDouble()) {
1466 ASSERT(instr->left()->representation().IsDouble());
1599 ASSERT(instr->right()->representation().IsDouble()); 1467 ASSERT(instr->right()->representation().IsDouble());
1600 LOperand* left = UseRegisterAtStart(instr->left()); 1468 LOperand* left = UseRegisterAtStart(instr->left());
1601 LOperand* right = UseRegisterAtStart(instr->right()); 1469 LOperand* right = UseRegisterAtStart(instr->right());
1602 return DefineAsRegister(new LCmpID(op, left, right, true)); 1470 return DefineAsRegister(new LCmpID(left, right));
1603 } else { 1471 } else {
1472 ASSERT(instr->left()->representation().IsTagged());
1473 ASSERT(instr->right()->representation().IsTagged());
1604 bool reversed = (op == Token::GT || op == Token::LTE); 1474 bool reversed = (op == Token::GT || op == Token::LTE);
1605 LOperand* left = UseFixed(instr->left(), reversed ? eax : edx); 1475 LOperand* left = UseFixed(instr->left(), reversed ? eax : edx);
1606 LOperand* right = UseFixed(instr->right(), reversed ? edx : eax); 1476 LOperand* right = UseFixed(instr->right(), reversed ? edx : eax);
1607 LInstruction* result = new LCmpT(left, right); 1477 LCmpT* result = new LCmpT(left, right);
1608 return MarkAsCall(DefineFixed(result, eax), instr); 1478 return MarkAsCall(DefineFixed(result, eax), instr);
1609 } 1479 }
1610 } 1480 }
1611 1481
1612 1482
1613 LInstruction* LChunkBuilder::DoCompareJSObjectEq( 1483 LInstruction* LChunkBuilder::DoCompareJSObjectEq(
1614 HCompareJSObjectEq* instr) { 1484 HCompareJSObjectEq* instr) {
1615 LOperand* left = UseRegisterAtStart(instr->left()); 1485 LOperand* left = UseRegisterAtStart(instr->left());
1616 LOperand* right = UseRegisterAtStart(instr->right()); 1486 LOperand* right = UseRegisterAtStart(instr->right());
1617 LInstruction* result = new LCmpJSObjectEq(left, right); 1487 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
1618 return DefineAsRegister(result); 1488 return DefineAsRegister(result);
1619 } 1489 }
1620 1490
1621 1491
1622 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { 1492 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
1623 ASSERT(instr->value()->representation().IsTagged()); 1493 ASSERT(instr->value()->representation().IsTagged());
1624 LOperand* value = UseRegisterAtStart(instr->value()); 1494 LOperand* value = UseRegisterAtStart(instr->value());
1625 1495
1626 return DefineAsRegister(new LIsNull(value, 1496 return DefineAsRegister(new LIsNull(value));
1627 instr->is_strict()));
1628 } 1497 }
1629 1498
1630 1499
1631 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { 1500 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
1632 ASSERT(instr->value()->representation().IsTagged()); 1501 ASSERT(instr->value()->representation().IsTagged());
1633 LOperand* value = UseRegister(instr->value()); 1502 LOperand* value = UseRegister(instr->value());
1634 1503
1635 return DefineAsRegister(new LIsObject(value, TempRegister())); 1504 return DefineAsRegister(new LIsObject(value, TempRegister()));
1636 } 1505 }
1637 1506
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1674 return DefineAsRegister(new LJSArrayLength(array)); 1543 return DefineAsRegister(new LJSArrayLength(array));
1675 } 1544 }
1676 1545
1677 1546
1678 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { 1547 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
1679 LOperand* array = UseRegisterAtStart(instr->value()); 1548 LOperand* array = UseRegisterAtStart(instr->value());
1680 return DefineAsRegister(new LFixedArrayLength(array)); 1549 return DefineAsRegister(new LFixedArrayLength(array));
1681 } 1550 }
1682 1551
1683 1552
1553 LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
1554 LOperand* array = UseRegisterAtStart(instr->value());
1555 return DefineAsRegister(new LPixelArrayLength(array));
1556 }
1557
1558
1684 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { 1559 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
1685 LOperand* object = UseRegister(instr->value()); 1560 LOperand* object = UseRegister(instr->value());
1686 LInstruction* result = new LValueOf(object, TempRegister()); 1561 LValueOf* result = new LValueOf(object, TempRegister());
1687 return AssignEnvironment(DefineSameAsFirst(result)); 1562 return AssignEnvironment(DefineSameAsFirst(result));
1688 } 1563 }
1689 1564
1690 1565
1691 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { 1566 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
1692 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), 1567 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
1693 Use(instr->length()))); 1568 Use(instr->length())));
1694 } 1569 }
1695 1570
1696 1571
1572 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
1573 // The control instruction marking the end of a block that completed
1574 // abruptly (e.g., threw an exception). There is nothing specific to do.
1575 return NULL;
1576 }
1577
1578
1697 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { 1579 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
1698 LOperand* value = UseFixed(instr->value(), eax); 1580 LOperand* value = UseFixed(instr->value(), eax);
1699 return MarkAsCall(new LThrow(value), instr); 1581 return MarkAsCall(new LThrow(value), instr);
1700 } 1582 }
1701 1583
1702 1584
1703 LInstruction* LChunkBuilder::DoChange(HChange* instr) { 1585 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
1704 Representation from = instr->from(); 1586 Representation from = instr->from();
1705 Representation to = instr->to(); 1587 Representation to = instr->to();
1706 if (from.IsTagged()) { 1588 if (from.IsTagged()) {
1707 if (to.IsDouble()) { 1589 if (to.IsDouble()) {
1708 LOperand* value = UseRegister(instr->value()); 1590 LOperand* value = UseRegister(instr->value());
1709 LInstruction* res = new LNumberUntagD(value); 1591 LNumberUntagD* res = new LNumberUntagD(value);
1710 return AssignEnvironment(DefineAsRegister(res)); 1592 return AssignEnvironment(DefineAsRegister(res));
1711 } else { 1593 } else {
1712 ASSERT(to.IsInteger32()); 1594 ASSERT(to.IsInteger32());
1713 LOperand* value = UseRegister(instr->value()); 1595 LOperand* value = UseRegister(instr->value());
1714 bool needs_check = !instr->value()->type().IsSmi(); 1596 bool needs_check = !instr->value()->type().IsSmi();
1715 if (needs_check) { 1597 if (needs_check) {
1716 LOperand* xmm_temp = 1598 LOperand* xmm_temp =
1717 (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3)) 1599 (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3))
1718 ? NULL 1600 ? NULL
1719 : FixedTemp(xmm1); 1601 : FixedTemp(xmm1);
1720 LInstruction* res = new LTaggedToI(value, xmm_temp); 1602 LTaggedToI* res = new LTaggedToI(value, xmm_temp);
1721 return AssignEnvironment(DefineSameAsFirst(res)); 1603 return AssignEnvironment(DefineSameAsFirst(res));
1722 } else { 1604 } else {
1723 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); 1605 return DefineSameAsFirst(new LSmiUntag(value, needs_check));
1724 } 1606 }
1725 } 1607 }
1726 } else if (from.IsDouble()) { 1608 } else if (from.IsDouble()) {
1727 if (to.IsTagged()) { 1609 if (to.IsTagged()) {
1728 LOperand* value = UseRegister(instr->value()); 1610 LOperand* value = UseRegister(instr->value());
1729 LOperand* temp = TempRegister(); 1611 LOperand* temp = TempRegister();
1730 1612
1731 // Make sure that temp and result_temp are different registers. 1613 // Make sure that temp and result_temp are different registers.
1732 LUnallocated* result_temp = TempRegister(); 1614 LUnallocated* result_temp = TempRegister();
1733 LInstruction* result = new LNumberTagD(value, temp); 1615 LNumberTagD* result = new LNumberTagD(value, temp);
1734 return AssignPointerMap(Define(result, result_temp)); 1616 return AssignPointerMap(Define(result, result_temp));
1735 } else { 1617 } else {
1736 ASSERT(to.IsInteger32()); 1618 ASSERT(to.IsInteger32());
1737 LOperand* value = UseRegister(instr->value()); 1619 bool needs_temp = instr->CanTruncateToInt32() &&
1738 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value))); 1620 !CpuFeatures::IsSupported(SSE3);
1621 LOperand* value = needs_temp ?
1622 UseTempRegister(instr->value()) : UseRegister(instr->value());
1623 LOperand* temp = needs_temp ? TempRegister() : NULL;
1624 return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp)));
1739 } 1625 }
1740 } else if (from.IsInteger32()) { 1626 } else if (from.IsInteger32()) {
1741 if (to.IsTagged()) { 1627 if (to.IsTagged()) {
1742 HValue* val = instr->value(); 1628 HValue* val = instr->value();
1743 LOperand* value = UseRegister(val); 1629 LOperand* value = UseRegister(val);
1744 if (val->HasRange() && val->range()->IsInSmiRange()) { 1630 if (val->HasRange() && val->range()->IsInSmiRange()) {
1745 return DefineSameAsFirst(new LSmiTag(value)); 1631 return DefineSameAsFirst(new LSmiTag(value));
1746 } else { 1632 } else {
1747 LInstruction* result = new LNumberTagI(value); 1633 LNumberTagI* result = new LNumberTagI(value);
1748 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); 1634 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
1749 } 1635 }
1750 } else { 1636 } else {
1751 ASSERT(to.IsDouble()); 1637 ASSERT(to.IsDouble());
1752 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value()))); 1638 return DefineAsRegister(new LInteger32ToDouble(Use(instr->value())));
1753 } 1639 }
1754 } 1640 }
1755 UNREACHABLE(); 1641 UNREACHABLE();
1756 return NULL; 1642 return NULL;
1757 } 1643 }
1758 1644
1759 1645
1760 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { 1646 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
1761 LOperand* value = UseRegisterAtStart(instr->value()); 1647 LOperand* value = UseRegisterAtStart(instr->value());
1762 return AssignEnvironment(new LCheckSmi(value, zero)); 1648 return AssignEnvironment(new LCheckSmi(value, zero));
1763 } 1649 }
1764 1650
1765 1651
1766 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { 1652 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
1767 LOperand* value = UseRegisterAtStart(instr->value()); 1653 LOperand* value = UseRegisterAtStart(instr->value());
1768 LOperand* temp = TempRegister(); 1654 LOperand* temp = TempRegister();
1769 LInstruction* result = new LCheckInstanceType(value, temp); 1655 LCheckInstanceType* result = new LCheckInstanceType(value, temp);
1770 return AssignEnvironment(result); 1656 return AssignEnvironment(result);
1771 } 1657 }
1772 1658
1773 1659
1774 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { 1660 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
1775 LOperand* temp = TempRegister(); 1661 LOperand* temp = TempRegister();
1776 LInstruction* result = 1662 LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp);
1777 new LCheckPrototypeMaps(temp,
1778 instr->holder(),
1779 instr->receiver_map());
1780 return AssignEnvironment(result); 1663 return AssignEnvironment(result);
1781 } 1664 }
1782 1665
1783 1666
1784 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { 1667 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
1785 LOperand* value = UseRegisterAtStart(instr->value()); 1668 LOperand* value = UseRegisterAtStart(instr->value());
1786 return AssignEnvironment(new LCheckSmi(value, not_zero)); 1669 return AssignEnvironment(new LCheckSmi(value, not_zero));
1787 } 1670 }
1788 1671
1789 1672
1790 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { 1673 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
1791 LOperand* value = UseRegisterAtStart(instr->value()); 1674 LOperand* value = UseRegisterAtStart(instr->value());
1792 return AssignEnvironment(new LCheckFunction(value)); 1675 return AssignEnvironment(new LCheckFunction(value));
1793 } 1676 }
1794 1677
1795 1678
1796 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) { 1679 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
1797 LOperand* value = UseRegisterAtStart(instr->value()); 1680 LOperand* value = UseRegisterAtStart(instr->value());
1798 LInstruction* result = new LCheckMap(value); 1681 LCheckMap* result = new LCheckMap(value);
1799 return AssignEnvironment(result); 1682 return AssignEnvironment(result);
1800 } 1683 }
1801 1684
1802 1685
1803 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { 1686 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
1804 return new LReturn(UseFixed(instr->value(), eax)); 1687 return new LReturn(UseFixed(instr->value(), eax));
1805 } 1688 }
1806 1689
1807 1690
1808 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { 1691 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
1809 Representation r = instr->representation(); 1692 Representation r = instr->representation();
1810 if (r.IsInteger32()) { 1693 if (r.IsInteger32()) {
1811 int32_t value = instr->Integer32Value(); 1694 return DefineAsRegister(new LConstantI);
1812 return DefineAsRegister(new LConstantI(value));
1813 } else if (r.IsDouble()) { 1695 } else if (r.IsDouble()) {
1814 double value = instr->DoubleValue(); 1696 double value = instr->DoubleValue();
1815 return DefineAsRegister(new LConstantD(value)); 1697 LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
1698 ? TempRegister()
1699 : NULL;
1700 return DefineAsRegister(new LConstantD(temp));
1816 } else if (r.IsTagged()) { 1701 } else if (r.IsTagged()) {
1817 return DefineAsRegister(new LConstantT(instr->handle())); 1702 return DefineAsRegister(new LConstantT);
1818 } else { 1703 } else {
1819 Abort("unsupported constant of type double"); 1704 UNREACHABLE();
1820 return NULL; 1705 return NULL;
1821 } 1706 }
1822 } 1707 }
1823 1708
1824 1709
1825 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { 1710 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
1826 LInstruction* result = new LLoadGlobal; 1711 LLoadGlobal* result = new LLoadGlobal;
1827 return instr->check_hole_value() 1712 return instr->check_hole_value()
1828 ? AssignEnvironment(DefineAsRegister(result)) 1713 ? AssignEnvironment(DefineAsRegister(result))
1829 : DefineAsRegister(result); 1714 : DefineAsRegister(result);
1830 } 1715 }
1831 1716
1832 1717
1833 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { 1718 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
1834 return new LStoreGlobal(UseRegisterAtStart(instr->value())); 1719 LStoreGlobal* result = new LStoreGlobal(UseRegisterAtStart(instr->value()));
1720 return instr->check_hole_value() ? AssignEnvironment(result) : result;
1721 }
1722
1723
1724 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
1725 LOperand* context = UseRegisterAtStart(instr->value());
1726 return DefineAsRegister(new LLoadContextSlot(context));
1727 }
1728
1729
1730 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
1731 LOperand* context;
1732 LOperand* value;
1733 LOperand* temp;
1734 if (instr->NeedsWriteBarrier()) {
1735 context = UseTempRegister(instr->context());
1736 value = UseTempRegister(instr->value());
1737 temp = TempRegister();
1738 } else {
1739 context = UseRegister(instr->context());
1740 value = UseRegister(instr->value());
1741 temp = NULL;
1742 }
1743 return new LStoreContextSlot(context, value, temp);
1835 } 1744 }
1836 1745
1837 1746
1838 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { 1747 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
1839 return DefineAsRegister( 1748 ASSERT(instr->representation().IsTagged());
1840 new LLoadNamedField(UseRegisterAtStart(instr->object()))); 1749 LOperand* obj = UseRegisterAtStart(instr->object());
1750 return DefineAsRegister(new LLoadNamedField(obj));
1841 } 1751 }
1842 1752
1843 1753
1844 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { 1754 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
1755 LOperand* context = UseFixed(instr->context(), esi);
1845 LOperand* object = UseFixed(instr->object(), eax); 1756 LOperand* object = UseFixed(instr->object(), eax);
1846 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), eax); 1757 LLoadNamedGeneric* result = new LLoadNamedGeneric(context, object);
1847 return MarkAsCall(result, instr); 1758 return MarkAsCall(DefineFixed(result, eax), instr);
1848 } 1759 }
1849 1760
1850 1761
1851 LInstruction* LChunkBuilder::DoLoadFunctionPrototype( 1762 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
1852 HLoadFunctionPrototype* instr) { 1763 HLoadFunctionPrototype* instr) {
1853 return AssignEnvironment(DefineAsRegister( 1764 return AssignEnvironment(DefineAsRegister(
1854 new LLoadFunctionPrototype(UseRegister(instr->function()), 1765 new LLoadFunctionPrototype(UseRegister(instr->function()),
1855 TempRegister()))); 1766 TempRegister())));
1856 } 1767 }
1857 1768
1858 1769
1859 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) { 1770 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
1860 LOperand* input = UseRegisterAtStart(instr->value()); 1771 LOperand* input = UseRegisterAtStart(instr->value());
1861 return DefineSameAsFirst(new LLoadElements(input)); 1772 return DefineAsRegister(new LLoadElements(input));
1773 }
1774
1775
1776 LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
1777 HLoadPixelArrayExternalPointer* instr) {
1778 LOperand* input = UseRegisterAtStart(instr->value());
1779 return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
1862 } 1780 }
1863 1781
1864 1782
1865 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( 1783 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
1866 HLoadKeyedFastElement* instr) { 1784 HLoadKeyedFastElement* instr) {
1867 Representation r = instr->representation(); 1785 ASSERT(instr->representation().IsTagged());
1786 ASSERT(instr->key()->representation().IsInteger32());
1868 LOperand* obj = UseRegisterAtStart(instr->object()); 1787 LOperand* obj = UseRegisterAtStart(instr->object());
1788 LOperand* key = UseRegisterAtStart(instr->key());
1789 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
1790 return AssignEnvironment(DefineSameAsFirst(result));
1791 }
1792
1793
1794 LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
1795 HLoadPixelArrayElement* instr) {
1796 ASSERT(instr->representation().IsInteger32());
1869 ASSERT(instr->key()->representation().IsInteger32()); 1797 ASSERT(instr->key()->representation().IsInteger32());
1798 LOperand* external_pointer =
1799 UseRegisterAtStart(instr->external_pointer());
1870 LOperand* key = UseRegisterAtStart(instr->key()); 1800 LOperand* key = UseRegisterAtStart(instr->key());
1871 LOperand* load_result = NULL; 1801 LLoadPixelArrayElement* result =
1872 // Double needs an extra temp, because the result is converted from heap 1802 new LLoadPixelArrayElement(external_pointer, key);
1873 // number to a double register. 1803 return DefineSameAsFirst(result);
1874 if (r.IsDouble()) load_result = TempRegister();
1875 LInstruction* result = new LLoadKeyedFastElement(obj,
1876 key,
1877 load_result);
1878 if (r.IsDouble()) {
1879 result = DefineAsRegister(result);
1880 } else {
1881 result = DefineSameAsFirst(result);
1882 }
1883 return AssignEnvironment(result);
1884 } 1804 }
1885 1805
1886 1806
1887 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { 1807 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
1808 LOperand* context = UseFixed(instr->context(), esi);
1888 LOperand* object = UseFixed(instr->object(), edx); 1809 LOperand* object = UseFixed(instr->object(), edx);
1889 LOperand* key = UseFixed(instr->key(), eax); 1810 LOperand* key = UseFixed(instr->key(), eax);
1890 1811
1891 LInstruction* result = 1812 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key);
1892 DefineFixed(new LLoadKeyedGeneric(object, key), eax); 1813 return MarkAsCall(DefineFixed(result, eax), instr);
1893 return MarkAsCall(result, instr);
1894 } 1814 }
1895 1815
1896 1816
1897 LInstruction* LChunkBuilder::DoStoreKeyedFastElement( 1817 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
1898 HStoreKeyedFastElement* instr) { 1818 HStoreKeyedFastElement* instr) {
1899 bool needs_write_barrier = instr->NeedsWriteBarrier(); 1819 bool needs_write_barrier = instr->NeedsWriteBarrier();
1900 ASSERT(instr->value()->representation().IsTagged()); 1820 ASSERT(instr->value()->representation().IsTagged());
1901 ASSERT(instr->object()->representation().IsTagged()); 1821 ASSERT(instr->object()->representation().IsTagged());
1902 ASSERT(instr->key()->representation().IsInteger32()); 1822 ASSERT(instr->key()->representation().IsInteger32());
1903 1823
1904 LOperand* obj = UseTempRegister(instr->object()); 1824 LOperand* obj = UseTempRegister(instr->object());
1905 LOperand* val = needs_write_barrier 1825 LOperand* val = needs_write_barrier
1906 ? UseTempRegister(instr->value()) 1826 ? UseTempRegister(instr->value())
1907 : UseRegisterAtStart(instr->value()); 1827 : UseRegisterAtStart(instr->value());
1908 LOperand* key = needs_write_barrier 1828 LOperand* key = needs_write_barrier
1909 ? UseTempRegister(instr->key()) 1829 ? UseTempRegister(instr->key())
1910 : UseRegisterOrConstantAtStart(instr->key()); 1830 : UseRegisterOrConstantAtStart(instr->key());
1911 1831
1912 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); 1832 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
1913 } 1833 }
1914 1834
1915 1835
1916 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { 1836 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
1917 LOperand* obj = UseFixed(instr->object(), edx); 1837 LOperand* context = UseFixed(instr->context(), esi);
1838 LOperand* object = UseFixed(instr->object(), edx);
1918 LOperand* key = UseFixed(instr->key(), ecx); 1839 LOperand* key = UseFixed(instr->key(), ecx);
1919 LOperand* val = UseFixed(instr->value(), eax); 1840 LOperand* value = UseFixed(instr->value(), eax);
1920 1841
1921 ASSERT(instr->object()->representation().IsTagged()); 1842 ASSERT(instr->object()->representation().IsTagged());
1922 ASSERT(instr->key()->representation().IsTagged()); 1843 ASSERT(instr->key()->representation().IsTagged());
1923 ASSERT(instr->value()->representation().IsTagged()); 1844 ASSERT(instr->value()->representation().IsTagged());
1924 1845
1925 return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr); 1846 LStoreKeyedGeneric* result =
1847 new LStoreKeyedGeneric(context, object, key, value);
1848 return MarkAsCall(result, instr);
1926 } 1849 }
1927 1850
1928 1851
1929 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { 1852 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
1930 bool needs_write_barrier = instr->NeedsWriteBarrier(); 1853 bool needs_write_barrier = instr->NeedsWriteBarrier();
1931 1854
1932 LOperand* obj = needs_write_barrier 1855 LOperand* obj = needs_write_barrier
1933 ? UseTempRegister(instr->object()) 1856 ? UseTempRegister(instr->object())
1934 : UseRegisterAtStart(instr->object()); 1857 : UseRegisterAtStart(instr->object());
1935 1858
1936 LOperand* val = needs_write_barrier 1859 LOperand* val = needs_write_barrier
1937 ? UseTempRegister(instr->value()) 1860 ? UseTempRegister(instr->value())
1938 : UseRegister(instr->value()); 1861 : UseRegister(instr->value());
1939 1862
1940 // We only need a scratch register if we have a write barrier or we 1863 // We only need a scratch register if we have a write barrier or we
1941 // have a store into the properties array (not in-object-property). 1864 // have a store into the properties array (not in-object-property).
1942 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) 1865 LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
1943 ? TempRegister() : NULL; 1866 ? TempRegister()
1867 : NULL;
1944 1868
1945 return new LStoreNamedField(obj, 1869 return new LStoreNamedField(obj, val, temp);
1946 instr->name(),
1947 val,
1948 instr->is_in_object(),
1949 instr->offset(),
1950 temp,
1951 needs_write_barrier,
1952 instr->transition());
1953 } 1870 }
1954 1871
1955 1872
1956 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { 1873 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
1957 LOperand* obj = UseFixed(instr->object(), edx); 1874 LOperand* context = UseFixed(instr->context(), esi);
1958 LOperand* val = UseFixed(instr->value(), eax); 1875 LOperand* object = UseFixed(instr->object(), edx);
1876 LOperand* value = UseFixed(instr->value(), eax);
1959 1877
1960 LInstruction* result = new LStoreNamedGeneric(obj, instr->name(), val); 1878 LStoreNamedGeneric* result = new LStoreNamedGeneric(context, object, value);
1961 return MarkAsCall(result, instr); 1879 return MarkAsCall(result, instr);
1962 } 1880 }
1963 1881
1964 1882
1883 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
1884 LOperand* string = UseRegister(instr->string());
1885 LOperand* index = UseRegisterOrConstant(instr->index());
1886 LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
1887 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
1888 }
1889
1890
1891 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
1892 LOperand* string = UseRegisterAtStart(instr->value());
1893 return DefineAsRegister(new LStringLength(string));
1894 }
1895
1896
1965 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { 1897 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
1966 return MarkAsCall(DefineFixed(new LArrayLiteral, eax), instr); 1898 return MarkAsCall(DefineFixed(new LArrayLiteral, eax), instr);
1967 } 1899 }
1968 1900
1969 1901
1970 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { 1902 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
1971 return MarkAsCall(DefineFixed(new LObjectLiteral, eax), instr); 1903 LOperand* context = UseFixed(instr->context(), esi);
1904 return MarkAsCall(DefineFixed(new LObjectLiteral(context), eax), instr);
1972 } 1905 }
1973 1906
1974 1907
1975 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { 1908 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
1976 return MarkAsCall(DefineFixed(new LRegExpLiteral, eax), instr); 1909 return MarkAsCall(DefineFixed(new LRegExpLiteral, eax), instr);
1977 } 1910 }
1978 1911
1979 1912
1980 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { 1913 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
1981 return MarkAsCall(DefineFixed(new LFunctionLiteral, eax), instr); 1914 return MarkAsCall(DefineFixed(new LFunctionLiteral, eax), instr);
1982 } 1915 }
1983 1916
1984 1917
1985 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { 1918 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
1986 LInstruction* result = new LDeleteProperty(Use(instr->object()), 1919 LDeleteProperty* result = new LDeleteProperty(Use(instr->object()),
1987 UseOrConstant(instr->key())); 1920 UseOrConstant(instr->key()));
1988 return MarkAsCall(DefineFixed(result, eax), instr); 1921 return MarkAsCall(DefineFixed(result, eax), instr);
1989 } 1922 }
1990 1923
1991 1924
1992 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { 1925 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
1993 allocator_->MarkAsOsrEntry(); 1926 allocator_->MarkAsOsrEntry();
1994 current_block_->last_environment()->set_ast_id(instr->ast_id()); 1927 current_block_->last_environment()->set_ast_id(instr->ast_id());
1995 return AssignEnvironment(new LOsrEntry); 1928 return AssignEnvironment(new LOsrEntry);
1996 } 1929 }
1997 1930
1998 1931
1999 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { 1932 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
2000 int spill_index = chunk()->GetParameterStackSlot(instr->index()); 1933 int spill_index = chunk()->GetParameterStackSlot(instr->index());
2001 return DefineAsSpilled(new LParameter, spill_index); 1934 return DefineAsSpilled(new LParameter, spill_index);
2002 } 1935 }
2003 1936
2004 1937
2005 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { 1938 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
2006 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. 1939 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width.
2007 return DefineAsSpilled(new LUnknownOSRValue, spill_index); 1940 return DefineAsSpilled(new LUnknownOSRValue, spill_index);
2008 } 1941 }
2009 1942
2010 1943
2011 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { 1944 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
1945 LOperand* context = UseFixed(instr->context(), esi);
2012 argument_count_ -= instr->argument_count(); 1946 argument_count_ -= instr->argument_count();
2013 return MarkAsCall(DefineFixed(new LCallStub, eax), instr); 1947 LCallStub* result = new LCallStub(context);
1948 return MarkAsCall(DefineFixed(result, eax), instr);
2014 } 1949 }
2015 1950
2016 1951
2017 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) { 1952 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
2018 // There are no real uses of the arguments object (we bail out in all other 1953 // There are no real uses of the arguments object (we bail out in all other
2019 // cases). 1954 // cases).
2020 return NULL; 1955 return NULL;
2021 } 1956 }
2022 1957
2023 1958
2024 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { 1959 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
2025 LOperand* arguments = UseRegister(instr->arguments()); 1960 LOperand* arguments = UseRegister(instr->arguments());
2026 LOperand* length = UseTempRegister(instr->length()); 1961 LOperand* length = UseTempRegister(instr->length());
2027 LOperand* index = Use(instr->index()); 1962 LOperand* index = Use(instr->index());
2028 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); 1963 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
2029 return DefineAsRegister(AssignEnvironment(result)); 1964 return AssignEnvironment(DefineAsRegister(result));
2030 } 1965 }
2031 1966
2032 1967
2033 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { 1968 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
2034 LInstruction* result = new LTypeof(UseAtStart(instr->value())); 1969 LTypeof* result = new LTypeof(UseAtStart(instr->value()));
2035 return MarkAsCall(DefineFixed(result, eax), instr); 1970 return MarkAsCall(DefineFixed(result, eax), instr);
2036 } 1971 }
2037 1972
2038 1973
2039 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { 1974 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
2040 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); 1975 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
2041 } 1976 }
2042 1977
1978
1979 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
1980 return DefineAsRegister(new LIsConstructCall);
1981 }
1982
1983
2043 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { 1984 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
2044 HEnvironment* env = current_block_->last_environment(); 1985 HEnvironment* env = current_block_->last_environment();
2045 ASSERT(env != NULL); 1986 ASSERT(env != NULL);
2046 1987
2047 env->set_ast_id(instr->ast_id()); 1988 env->set_ast_id(instr->ast_id());
2048 1989
2049 env->Drop(instr->pop_count()); 1990 env->Drop(instr->pop_count());
2050 for (int i = 0; i < instr->values()->length(); ++i) { 1991 for (int i = 0; i < instr->values()->length(); ++i) {
2051 HValue* value = instr->values()->at(i); 1992 HValue* value = instr->values()->at(i);
2052 if (instr->HasAssignedIndexAt(i)) { 1993 if (instr->HasAssignedIndexAt(i)) {
2053 env->Bind(instr->GetAssignedIndexAt(i), value); 1994 env->Bind(instr->GetAssignedIndexAt(i), value);
2054 } else { 1995 } else {
2055 env->Push(value); 1996 env->Push(value);
2056 } 1997 }
2057 } 1998 }
2058 ASSERT(env->length() == instr->environment_length()); 1999 ASSERT(env->length() == instr->environment_length());
2059 2000
2060 // If there is an instruction pending deoptimization environment create a 2001 // If there is an instruction pending deoptimization environment create a
2061 // lazy bailout instruction to capture the environment. 2002 // lazy bailout instruction to capture the environment.
2062 if (pending_deoptimization_ast_id_ == instr->ast_id()) { 2003 if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
2063 LInstruction* result = new LLazyBailout; 2004 ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
2064 result = AssignEnvironment(result); 2005 LLazyBailout* lazy_bailout = new LLazyBailout;
2065 instructions_pending_deoptimization_environment_-> 2006 LInstruction* result = AssignEnvironment(lazy_bailout);
2007 instruction_pending_deoptimization_environment_->
2066 set_deoptimization_environment(result->environment()); 2008 set_deoptimization_environment(result->environment());
2067 ClearInstructionPendingDeoptimizationEnvironment(); 2009 ClearInstructionPendingDeoptimizationEnvironment();
2068 return result; 2010 return result;
2069 } 2011 }
2070 2012
2071 return NULL; 2013 return NULL;
2072 } 2014 }
2073 2015
2074 2016
2075 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { 2017 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
(...skipping 14 matching lines...) Expand all
2090 } 2032 }
2091 2033
2092 2034
2093 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { 2035 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
2094 HEnvironment* outer = current_block_->last_environment()->outer(); 2036 HEnvironment* outer = current_block_->last_environment()->outer();
2095 current_block_->UpdateEnvironment(outer); 2037 current_block_->UpdateEnvironment(outer);
2096 return NULL; 2038 return NULL;
2097 } 2039 }
2098 2040
2099 2041
2100 void LPointerMap::RecordPointer(LOperand* op) { 2042 } } // namespace v8::internal
2101 // Do not record arguments as pointers.
2102 if (op->IsStackSlot() && op->index() < 0) return;
2103 ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
2104 pointer_operands_.Add(op);
2105 }
2106 2043
2107 2044 #endif // V8_TARGET_ARCH_IA32
2108 void LPointerMap::PrintTo(StringStream* stream) const {
2109 stream->Add("{");
2110 for (int i = 0; i < pointer_operands_.length(); ++i) {
2111 if (i != 0) stream->Add(";");
2112 pointer_operands_[i]->PrintTo(stream);
2113 }
2114 stream->Add("} @%d", position());
2115 }
2116
2117 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/lithium-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698