OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 switch (location_) { | 214 switch (location_) { |
215 case kAccumulator: | 215 case kAccumulator: |
216 if (!reg.is(result_register())) __ movq(result_register(), reg); | 216 if (!reg.is(result_register())) __ movq(result_register(), reg); |
217 break; | 217 break; |
218 case kStack: | 218 case kStack: |
219 __ push(reg); | 219 __ push(reg); |
220 break; | 220 break; |
221 } | 221 } |
222 break; | 222 break; |
223 | 223 |
224 case Expression::kValueTest: | |
225 case Expression::kTestValue: | |
226 // Push an extra copy of the value in case it's needed. | |
227 __ push(reg); | |
228 // Fall through. | |
229 | |
230 case Expression::kTest: | 224 case Expression::kTest: |
231 // For simplicity we always test the accumulator register. | 225 // For simplicity we always test the accumulator register. |
232 if (!reg.is(result_register())) __ movq(result_register(), reg); | 226 if (!reg.is(result_register())) __ movq(result_register(), reg); |
233 DoTest(context); | 227 DoTest(context); |
234 break; | 228 break; |
| 229 |
| 230 case Expression::kValueTest: |
| 231 case Expression::kTestValue: |
| 232 if (!reg.is(result_register())) __ movq(result_register(), reg); |
| 233 switch (location_) { |
| 234 case kAccumulator: |
| 235 break; |
| 236 case kStack: |
| 237 __ push(result_register()); |
| 238 break; |
| 239 } |
| 240 DoTest(context); |
| 241 break; |
235 } | 242 } |
236 } | 243 } |
237 | 244 |
238 | 245 |
239 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 246 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
240 switch (context) { | 247 switch (context) { |
241 case Expression::kUninitialized: | 248 case Expression::kUninitialized: |
242 UNREACHABLE(); | 249 UNREACHABLE(); |
243 case Expression::kEffect: | 250 case Expression::kEffect: |
244 // Nothing to do. | 251 // Nothing to do. |
(...skipping 13 matching lines...) Expand all Loading... |
258 } | 265 } |
259 | 266 |
260 case Expression::kTest: | 267 case Expression::kTest: |
261 Move(result_register(), slot); | 268 Move(result_register(), slot); |
262 DoTest(context); | 269 DoTest(context); |
263 break; | 270 break; |
264 | 271 |
265 case Expression::kValueTest: | 272 case Expression::kValueTest: |
266 case Expression::kTestValue: | 273 case Expression::kTestValue: |
267 Move(result_register(), slot); | 274 Move(result_register(), slot); |
268 __ push(result_register()); | 275 switch (location_) { |
| 276 case kAccumulator: |
| 277 break; |
| 278 case kStack: |
| 279 __ push(result_register()); |
| 280 break; |
| 281 } |
269 DoTest(context); | 282 DoTest(context); |
270 break; | 283 break; |
271 } | 284 } |
272 } | 285 } |
273 | 286 |
274 | 287 |
275 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 288 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
276 switch (context) { | 289 switch (context) { |
277 case Expression::kUninitialized: | 290 case Expression::kUninitialized: |
278 UNREACHABLE(); | 291 UNREACHABLE(); |
(...skipping 12 matching lines...) Expand all Loading... |
291 break; | 304 break; |
292 | 305 |
293 case Expression::kTest: | 306 case Expression::kTest: |
294 __ Move(result_register(), lit->handle()); | 307 __ Move(result_register(), lit->handle()); |
295 DoTest(context); | 308 DoTest(context); |
296 break; | 309 break; |
297 | 310 |
298 case Expression::kValueTest: | 311 case Expression::kValueTest: |
299 case Expression::kTestValue: | 312 case Expression::kTestValue: |
300 __ Move(result_register(), lit->handle()); | 313 __ Move(result_register(), lit->handle()); |
301 __ push(result_register()); | 314 switch (location_) { |
| 315 case kAccumulator: |
| 316 break; |
| 317 case kStack: |
| 318 __ push(result_register()); |
| 319 break; |
| 320 } |
302 DoTest(context); | 321 DoTest(context); |
303 break; | 322 break; |
304 } | 323 } |
305 } | 324 } |
306 | 325 |
307 | 326 |
308 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 327 void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
309 switch (context) { | 328 switch (context) { |
310 case Expression::kUninitialized: | 329 case Expression::kUninitialized: |
311 UNREACHABLE(); | 330 UNREACHABLE(); |
(...skipping 12 matching lines...) Expand all Loading... |
324 } | 343 } |
325 break; | 344 break; |
326 | 345 |
327 case Expression::kTest: | 346 case Expression::kTest: |
328 __ pop(result_register()); | 347 __ pop(result_register()); |
329 DoTest(context); | 348 DoTest(context); |
330 break; | 349 break; |
331 | 350 |
332 case Expression::kValueTest: | 351 case Expression::kValueTest: |
333 case Expression::kTestValue: | 352 case Expression::kTestValue: |
334 __ movq(result_register(), Operand(rsp, 0)); | 353 switch (location_) { |
| 354 case kAccumulator: |
| 355 __ pop(result_register()); |
| 356 break; |
| 357 case kStack: |
| 358 __ movq(result_register(), Operand(rsp, 0)); |
| 359 break; |
| 360 } |
335 DoTest(context); | 361 DoTest(context); |
336 break; | 362 break; |
337 } | 363 } |
338 } | 364 } |
339 | 365 |
340 | 366 |
341 void FastCodeGenerator::DropAndApply(int count, | 367 void FastCodeGenerator::DropAndApply(int count, |
342 Expression::Context context, | 368 Expression::Context context, |
343 Register reg) { | 369 Register reg) { |
344 ASSERT(count > 0); | 370 ASSERT(count > 0); |
(...skipping 20 matching lines...) Expand all Loading... |
365 break; | 391 break; |
366 | 392 |
367 case Expression::kTest: | 393 case Expression::kTest: |
368 __ Drop(count); | 394 __ Drop(count); |
369 if (!reg.is(result_register())) __ movq(result_register(), reg); | 395 if (!reg.is(result_register())) __ movq(result_register(), reg); |
370 DoTest(context); | 396 DoTest(context); |
371 break; | 397 break; |
372 | 398 |
373 case Expression::kValueTest: | 399 case Expression::kValueTest: |
374 case Expression::kTestValue: | 400 case Expression::kTestValue: |
375 if (count > 1) __ Drop(count - 1); | 401 switch (location_) { |
376 if (!reg.is(result_register())) __ movq(result_register(), reg); | 402 case kAccumulator: |
377 __ movq(Operand(rsp, 0), result_register()); | 403 __ Drop(count); |
| 404 if (!reg.is(result_register())) __ movq(result_register(), reg); |
| 405 break; |
| 406 case kStack: |
| 407 if (count > 1) __ Drop(count - 1); |
| 408 __ movq(result_register(), reg); |
| 409 __ movq(Operand(rsp, 0), result_register()); |
| 410 break; |
| 411 } |
378 DoTest(context); | 412 DoTest(context); |
379 break; | 413 break; |
380 } | 414 } |
381 } | 415 } |
382 | 416 |
383 | 417 |
384 void FastCodeGenerator::Apply(Expression::Context context, | 418 void FastCodeGenerator::Apply(Expression::Context context, |
385 Label* materialize_true, | 419 Label* materialize_true, |
386 Label* materialize_false) { | 420 Label* materialize_false) { |
387 switch (context) { | 421 switch (context) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 __ Push(Factory::false_value()); | 473 __ Push(Factory::false_value()); |
440 break; | 474 break; |
441 } | 475 } |
442 __ jmp(false_label_); | 476 __ jmp(false_label_); |
443 break; | 477 break; |
444 } | 478 } |
445 } | 479 } |
446 | 480 |
447 | 481 |
448 void FastCodeGenerator::DoTest(Expression::Context context) { | 482 void FastCodeGenerator::DoTest(Expression::Context context) { |
449 // The value to test is in the accumulator, and duplicated on the stack if | 483 // The value to test is in the accumulator. If the value might be needed |
450 // necessary (for value/test and test/value contexts). | 484 // on the stack (value/test and test/value contexts with a stack location |
| 485 // desired), then the value is already duplicated on the stack. |
451 ASSERT_NE(NULL, true_label_); | 486 ASSERT_NE(NULL, true_label_); |
452 ASSERT_NE(NULL, false_label_); | 487 ASSERT_NE(NULL, false_label_); |
453 | 488 |
454 // If there is a value on the stack, use a discard label for the | 489 // In value/test and test/value expression contexts with stack as the |
455 // value-is-unneeded branch in the inlined part of the test. | 490 // desired location, there is already an extra value on the stack. Use a |
| 491 // label to discard it if unneeded. |
456 Label discard; | 492 Label discard; |
457 Label* if_true = | 493 Label* if_true = true_label_; |
458 (context == Expression::kTestValue) ? &discard : true_label_; | 494 Label* if_false = false_label_; |
459 Label* if_false = | 495 switch (context) { |
460 (context == Expression::kValueTest) ? &discard : false_label_; | 496 case Expression::kUninitialized: |
| 497 case Expression::kEffect: |
| 498 case Expression::kValue: |
| 499 UNREACHABLE(); |
| 500 case Expression::kTest: |
| 501 break; |
| 502 case Expression::kValueTest: |
| 503 switch (location_) { |
| 504 case kAccumulator: |
| 505 break; |
| 506 case kStack: |
| 507 if_false = &discard; |
| 508 break; |
| 509 } |
| 510 break; |
| 511 case Expression::kTestValue: |
| 512 switch (location_) { |
| 513 case kAccumulator: |
| 514 break; |
| 515 case kStack: |
| 516 if_true = &discard; |
| 517 break; |
| 518 } |
| 519 break; |
| 520 } |
461 | 521 |
462 // Emit the inlined tests assumed by the stub. | 522 // Emit the inlined tests assumed by the stub. |
463 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); | 523 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
464 __ j(equal, if_false); | 524 __ j(equal, if_false); |
465 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); | 525 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); |
466 __ j(equal, if_true); | 526 __ j(equal, if_true); |
467 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); | 527 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); |
468 __ j(equal, if_false); | 528 __ j(equal, if_false); |
469 ASSERT_EQ(0, kSmiTag); | 529 ASSERT_EQ(0, kSmiTag); |
470 __ SmiCompare(result_register(), Smi::FromInt(0)); | 530 __ SmiCompare(result_register(), Smi::FromInt(0)); |
471 __ j(equal, if_false); | 531 __ j(equal, if_false); |
472 Condition is_smi = masm_->CheckSmi(result_register()); | 532 Condition is_smi = masm_->CheckSmi(result_register()); |
473 __ j(is_smi, if_true); | 533 __ j(is_smi, if_true); |
474 | 534 |
| 535 // Save a copy of the value if it may be needed and isn't already saved. |
| 536 switch (context) { |
| 537 case Expression::kUninitialized: |
| 538 case Expression::kEffect: |
| 539 case Expression::kValue: |
| 540 UNREACHABLE(); |
| 541 case Expression::kTest: |
| 542 break; |
| 543 case Expression::kValueTest: |
| 544 switch (location_) { |
| 545 case kAccumulator: |
| 546 __ push(result_register()); |
| 547 break; |
| 548 case kStack: |
| 549 break; |
| 550 } |
| 551 break; |
| 552 case Expression::kTestValue: |
| 553 switch (location_) { |
| 554 case kAccumulator: |
| 555 __ push(result_register()); |
| 556 break; |
| 557 case kStack: |
| 558 break; |
| 559 } |
| 560 break; |
| 561 } |
| 562 |
475 // Call the ToBoolean stub for all other cases. | 563 // Call the ToBoolean stub for all other cases. |
476 ToBooleanStub stub; | 564 ToBooleanStub stub; |
477 __ push(result_register()); | 565 __ push(result_register()); |
478 __ CallStub(&stub); | 566 __ CallStub(&stub); |
479 __ testq(rax, rax); | 567 __ testq(rax, rax); |
480 | 568 |
481 // The stub returns nonzero for true. Complete based on the context. | 569 // The stub returns nonzero for true. Complete based on the context. |
482 switch (context) { | 570 switch (context) { |
483 case Expression::kUninitialized: | 571 case Expression::kUninitialized: |
484 case Expression::kEffect: | 572 case Expression::kEffect: |
(...skipping 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1722 __ movq(Operand(rsp, 0), rdx); | 1810 __ movq(Operand(rsp, 0), rdx); |
1723 // And return. | 1811 // And return. |
1724 __ ret(0); | 1812 __ ret(0); |
1725 } | 1813 } |
1726 | 1814 |
1727 | 1815 |
1728 #undef __ | 1816 #undef __ |
1729 | 1817 |
1730 | 1818 |
1731 } } // namespace v8::internal | 1819 } } // namespace v8::internal |
OLD | NEW |