| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 break; | 246 break; |
| 247 case kStack: | 247 case kStack: |
| 248 __ push(reg); | 248 __ push(reg); |
| 249 break; | 249 break; |
| 250 } | 250 } |
| 251 break; | 251 break; |
| 252 | 252 |
| 253 case Expression::kTest: | 253 case Expression::kTest: |
| 254 // For simplicity we always test the accumulator register. | 254 // For simplicity we always test the accumulator register. |
| 255 if (!reg.is(result_register())) __ movq(result_register(), reg); | 255 if (!reg.is(result_register())) __ movq(result_register(), reg); |
| 256 DoTest(context); | 256 DoTest(true_label_, false_label_, NULL); |
| 257 break; | |
| 258 | |
| 259 case Expression::kValueTest: | |
| 260 case Expression::kTestValue: | |
| 261 if (!reg.is(result_register())) __ movq(result_register(), reg); | |
| 262 switch (location_) { | |
| 263 case kAccumulator: | |
| 264 break; | |
| 265 case kStack: | |
| 266 __ push(result_register()); | |
| 267 break; | |
| 268 } | |
| 269 DoTest(context); | |
| 270 break; | 257 break; |
| 271 } | 258 } |
| 272 } | 259 } |
| 273 | 260 |
| 274 | 261 |
| 275 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 262 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
| 276 switch (context) { | 263 switch (context) { |
| 277 case Expression::kUninitialized: | 264 case Expression::kUninitialized: |
| 278 UNREACHABLE(); | 265 UNREACHABLE(); |
| 279 case Expression::kEffect: | 266 case Expression::kEffect: |
| 280 // Nothing to do. | 267 // Nothing to do. |
| 281 break; | 268 break; |
| 282 case Expression::kValue: { | 269 case Expression::kValue: { |
| 283 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 270 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
| 284 switch (location_) { | 271 switch (location_) { |
| 285 case kAccumulator: | 272 case kAccumulator: |
| 286 __ movq(result_register(), slot_operand); | 273 __ movq(result_register(), slot_operand); |
| 287 break; | 274 break; |
| 288 case kStack: | 275 case kStack: |
| 289 // Memory operands can be pushed directly. | 276 // Memory operands can be pushed directly. |
| 290 __ push(slot_operand); | 277 __ push(slot_operand); |
| 291 break; | 278 break; |
| 292 } | 279 } |
| 293 break; | 280 break; |
| 294 } | 281 } |
| 295 | 282 |
| 296 case Expression::kTest: | 283 case Expression::kTest: |
| 297 Move(result_register(), slot); | 284 Move(result_register(), slot); |
| 298 DoTest(context); | 285 DoTest(true_label_, false_label_, NULL); |
| 299 break; | |
| 300 | |
| 301 case Expression::kValueTest: | |
| 302 case Expression::kTestValue: | |
| 303 Move(result_register(), slot); | |
| 304 switch (location_) { | |
| 305 case kAccumulator: | |
| 306 break; | |
| 307 case kStack: | |
| 308 __ push(result_register()); | |
| 309 break; | |
| 310 } | |
| 311 DoTest(context); | |
| 312 break; | 286 break; |
| 313 } | 287 } |
| 314 } | 288 } |
| 315 | 289 |
| 316 | 290 |
| 317 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 291 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
| 318 switch (context) { | 292 switch (context) { |
| 319 case Expression::kUninitialized: | 293 case Expression::kUninitialized: |
| 320 UNREACHABLE(); | 294 UNREACHABLE(); |
| 321 case Expression::kEffect: | 295 case Expression::kEffect: |
| 322 // Nothing to do. | 296 // Nothing to do. |
| 323 break; | 297 break; |
| 324 case Expression::kValue: | 298 case Expression::kValue: |
| 325 switch (location_) { | 299 switch (location_) { |
| 326 case kAccumulator: | 300 case kAccumulator: |
| 327 __ Move(result_register(), lit->handle()); | 301 __ Move(result_register(), lit->handle()); |
| 328 break; | 302 break; |
| 329 case kStack: | 303 case kStack: |
| 330 __ Push(lit->handle()); | 304 __ Push(lit->handle()); |
| 331 break; | 305 break; |
| 332 } | 306 } |
| 333 break; | 307 break; |
| 334 | 308 |
| 335 case Expression::kTest: | 309 case Expression::kTest: |
| 336 __ Move(result_register(), lit->handle()); | 310 __ Move(result_register(), lit->handle()); |
| 337 DoTest(context); | 311 DoTest(true_label_, false_label_, NULL); |
| 338 break; | |
| 339 | |
| 340 case Expression::kValueTest: | |
| 341 case Expression::kTestValue: | |
| 342 __ Move(result_register(), lit->handle()); | |
| 343 switch (location_) { | |
| 344 case kAccumulator: | |
| 345 break; | |
| 346 case kStack: | |
| 347 __ push(result_register()); | |
| 348 break; | |
| 349 } | |
| 350 DoTest(context); | |
| 351 break; | 312 break; |
| 352 } | 313 } |
| 353 } | 314 } |
| 354 | 315 |
| 355 | 316 |
| 356 void FullCodeGenerator::ApplyTOS(Expression::Context context) { | 317 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
| 357 switch (context) { | 318 switch (context) { |
| 358 case Expression::kUninitialized: | 319 case Expression::kUninitialized: |
| 359 UNREACHABLE(); | 320 UNREACHABLE(); |
| 360 | 321 |
| 361 case Expression::kEffect: | 322 case Expression::kEffect: |
| 362 __ Drop(1); | 323 __ Drop(1); |
| 363 break; | 324 break; |
| 364 | 325 |
| 365 case Expression::kValue: | 326 case Expression::kValue: |
| 366 switch (location_) { | 327 switch (location_) { |
| 367 case kAccumulator: | 328 case kAccumulator: |
| 368 __ pop(result_register()); | 329 __ pop(result_register()); |
| 369 break; | 330 break; |
| 370 case kStack: | 331 case kStack: |
| 371 break; | 332 break; |
| 372 } | 333 } |
| 373 break; | 334 break; |
| 374 | 335 |
| 375 case Expression::kTest: | 336 case Expression::kTest: |
| 376 __ pop(result_register()); | 337 __ pop(result_register()); |
| 377 DoTest(context); | 338 DoTest(true_label_, false_label_, NULL); |
| 378 break; | |
| 379 | |
| 380 case Expression::kValueTest: | |
| 381 case Expression::kTestValue: | |
| 382 switch (location_) { | |
| 383 case kAccumulator: | |
| 384 __ pop(result_register()); | |
| 385 break; | |
| 386 case kStack: | |
| 387 __ movq(result_register(), Operand(rsp, 0)); | |
| 388 break; | |
| 389 } | |
| 390 DoTest(context); | |
| 391 break; | 339 break; |
| 392 } | 340 } |
| 393 } | 341 } |
| 394 | 342 |
| 395 | 343 |
| 396 void FullCodeGenerator::DropAndApply(int count, | 344 void FullCodeGenerator::DropAndApply(int count, |
| 397 Expression::Context context, | 345 Expression::Context context, |
| 398 Register reg) { | 346 Register reg) { |
| 399 ASSERT(count > 0); | 347 ASSERT(count > 0); |
| 400 ASSERT(!reg.is(rsp)); | 348 ASSERT(!reg.is(rsp)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 415 case kStack: | 363 case kStack: |
| 416 if (count > 1) __ Drop(count - 1); | 364 if (count > 1) __ Drop(count - 1); |
| 417 __ movq(Operand(rsp, 0), reg); | 365 __ movq(Operand(rsp, 0), reg); |
| 418 break; | 366 break; |
| 419 } | 367 } |
| 420 break; | 368 break; |
| 421 | 369 |
| 422 case Expression::kTest: | 370 case Expression::kTest: |
| 423 __ Drop(count); | 371 __ Drop(count); |
| 424 if (!reg.is(result_register())) __ movq(result_register(), reg); | 372 if (!reg.is(result_register())) __ movq(result_register(), reg); |
| 425 DoTest(context); | 373 DoTest(true_label_, false_label_, NULL); |
| 426 break; | |
| 427 | |
| 428 case Expression::kValueTest: | |
| 429 case Expression::kTestValue: | |
| 430 switch (location_) { | |
| 431 case kAccumulator: | |
| 432 __ Drop(count); | |
| 433 if (!reg.is(result_register())) __ movq(result_register(), reg); | |
| 434 break; | |
| 435 case kStack: | |
| 436 if (count > 1) __ Drop(count - 1); | |
| 437 __ movq(result_register(), reg); | |
| 438 __ movq(Operand(rsp, 0), result_register()); | |
| 439 break; | |
| 440 } | |
| 441 DoTest(context); | |
| 442 break; | 374 break; |
| 443 } | 375 } |
| 444 } | 376 } |
| 445 | 377 |
| 446 | 378 |
| 447 void FullCodeGenerator::PrepareTest(Label* materialize_true, | 379 void FullCodeGenerator::PrepareTest(Label* materialize_true, |
| 448 Label* materialize_false, | 380 Label* materialize_false, |
| 449 Label** if_true, | 381 Label** if_true, |
| 450 Label** if_false) { | 382 Label** if_false) { |
| 451 switch (context_) { | 383 switch (context_) { |
| 452 case Expression::kUninitialized: | 384 case Expression::kUninitialized: |
| 453 UNREACHABLE(); | 385 UNREACHABLE(); |
| 454 break; | 386 break; |
| 455 case Expression::kEffect: | 387 case Expression::kEffect: |
| 456 // In an effect context, the true and the false case branch to the | 388 // In an effect context, the true and the false case branch to the |
| 457 // same label. | 389 // same label. |
| 458 *if_true = *if_false = materialize_true; | 390 *if_true = *if_false = materialize_true; |
| 459 break; | 391 break; |
| 460 case Expression::kValue: | 392 case Expression::kValue: |
| 461 *if_true = materialize_true; | 393 *if_true = materialize_true; |
| 462 *if_false = materialize_false; | 394 *if_false = materialize_false; |
| 463 break; | 395 break; |
| 464 case Expression::kTest: | 396 case Expression::kTest: |
| 465 *if_true = true_label_; | 397 *if_true = true_label_; |
| 466 *if_false = false_label_; | 398 *if_false = false_label_; |
| 467 break; | 399 break; |
| 468 case Expression::kValueTest: | |
| 469 *if_true = materialize_true; | |
| 470 *if_false = false_label_; | |
| 471 break; | |
| 472 case Expression::kTestValue: | |
| 473 *if_true = true_label_; | |
| 474 *if_false = materialize_false; | |
| 475 break; | |
| 476 } | 400 } |
| 477 } | 401 } |
| 478 | 402 |
| 479 | 403 |
| 480 void FullCodeGenerator::Apply(Expression::Context context, | 404 void FullCodeGenerator::Apply(Expression::Context context, |
| 481 Label* materialize_true, | 405 Label* materialize_true, |
| 482 Label* materialize_false) { | 406 Label* materialize_false) { |
| 483 switch (context) { | 407 switch (context) { |
| 484 case Expression::kUninitialized: | 408 case Expression::kUninitialized: |
| 485 | 409 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 505 __ bind(materialize_false); | 429 __ bind(materialize_false); |
| 506 __ Push(Factory::false_value()); | 430 __ Push(Factory::false_value()); |
| 507 break; | 431 break; |
| 508 } | 432 } |
| 509 __ bind(&done); | 433 __ bind(&done); |
| 510 break; | 434 break; |
| 511 } | 435 } |
| 512 | 436 |
| 513 case Expression::kTest: | 437 case Expression::kTest: |
| 514 break; | 438 break; |
| 515 | |
| 516 case Expression::kValueTest: | |
| 517 __ bind(materialize_true); | |
| 518 switch (location_) { | |
| 519 case kAccumulator: | |
| 520 __ Move(result_register(), Factory::true_value()); | |
| 521 break; | |
| 522 case kStack: | |
| 523 __ Push(Factory::true_value()); | |
| 524 break; | |
| 525 } | |
| 526 __ jmp(true_label_); | |
| 527 break; | |
| 528 | |
| 529 case Expression::kTestValue: | |
| 530 __ bind(materialize_false); | |
| 531 switch (location_) { | |
| 532 case kAccumulator: | |
| 533 __ Move(result_register(), Factory::false_value()); | |
| 534 break; | |
| 535 case kStack: | |
| 536 __ Push(Factory::false_value()); | |
| 537 break; | |
| 538 } | |
| 539 __ jmp(false_label_); | |
| 540 break; | |
| 541 } | 439 } |
| 542 } | 440 } |
| 543 | 441 |
| 544 | 442 |
| 545 // Convert constant control flow (true or false) to the result expected for | 443 // Convert constant control flow (true or false) to the result expected for |
| 546 // a given expression context. | 444 // a given expression context. |
| 547 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { | 445 void FullCodeGenerator::Apply(Expression::Context context, bool flag) { |
| 548 switch (context) { | 446 switch (context) { |
| 549 case Expression::kUninitialized: | 447 case Expression::kUninitialized: |
| 550 UNREACHABLE(); | 448 UNREACHABLE(); |
| 551 break; | 449 break; |
| 552 case Expression::kEffect: | 450 case Expression::kEffect: |
| 553 break; | 451 break; |
| 554 case Expression::kValue: { | 452 case Expression::kValue: { |
| 555 Heap::RootListIndex value_root_index = | 453 Heap::RootListIndex value_root_index = |
| 556 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; | 454 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
| 557 switch (location_) { | 455 switch (location_) { |
| 558 case kAccumulator: | 456 case kAccumulator: |
| 559 __ LoadRoot(result_register(), value_root_index); | 457 __ LoadRoot(result_register(), value_root_index); |
| 560 break; | 458 break; |
| 561 case kStack: | 459 case kStack: |
| 562 __ PushRoot(value_root_index); | 460 __ PushRoot(value_root_index); |
| 563 break; | 461 break; |
| 564 } | 462 } |
| 565 break; | 463 break; |
| 566 } | 464 } |
| 567 case Expression::kTest: | 465 case Expression::kTest: |
| 568 __ jmp(flag ? true_label_ : false_label_); | 466 __ jmp(flag ? true_label_ : false_label_); |
| 569 break; | 467 break; |
| 570 case Expression::kTestValue: | |
| 571 switch (location_) { | |
| 572 case kAccumulator: | |
| 573 // If value is false it's needed. | |
| 574 if (!flag) __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); | |
| 575 break; | |
| 576 case kStack: | |
| 577 // If value is false it's needed. | |
| 578 if (!flag) __ PushRoot(Heap::kFalseValueRootIndex); | |
| 579 break; | |
| 580 } | |
| 581 __ jmp(flag ? true_label_ : false_label_); | |
| 582 break; | |
| 583 case Expression::kValueTest: | |
| 584 switch (location_) { | |
| 585 case kAccumulator: | |
| 586 // If value is true it's needed. | |
| 587 if (flag) __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); | |
| 588 break; | |
| 589 case kStack: | |
| 590 // If value is true it's needed. | |
| 591 if (flag) __ PushRoot(Heap::kTrueValueRootIndex); | |
| 592 break; | |
| 593 } | |
| 594 __ jmp(flag ? true_label_ : false_label_); | |
| 595 break; | |
| 596 } | 468 } |
| 597 } | 469 } |
| 598 | 470 |
| 599 | 471 |
| 600 void FullCodeGenerator::DoTest(Expression::Context context) { | 472 void FullCodeGenerator::DoTest(Label* if_true, |
| 601 // The value to test is in the accumulator. If the value might be needed | 473 Label* if_false, |
| 602 // on the stack (value/test and test/value contexts with a stack location | 474 Label* fall_through) { |
| 603 // desired), then the value is already duplicated on the stack. | |
| 604 ASSERT_NE(NULL, true_label_); | |
| 605 ASSERT_NE(NULL, false_label_); | |
| 606 | |
| 607 // In value/test and test/value expression contexts with stack as the | |
| 608 // desired location, there is already an extra value on the stack. Use a | |
| 609 // label to discard it if unneeded. | |
| 610 Label discard; | |
| 611 Label* if_true = true_label_; | |
| 612 Label* if_false = false_label_; | |
| 613 switch (context) { | |
| 614 case Expression::kUninitialized: | |
| 615 case Expression::kEffect: | |
| 616 case Expression::kValue: | |
| 617 UNREACHABLE(); | |
| 618 case Expression::kTest: | |
| 619 break; | |
| 620 case Expression::kValueTest: | |
| 621 switch (location_) { | |
| 622 case kAccumulator: | |
| 623 break; | |
| 624 case kStack: | |
| 625 if_false = &discard; | |
| 626 break; | |
| 627 } | |
| 628 break; | |
| 629 case Expression::kTestValue: | |
| 630 switch (location_) { | |
| 631 case kAccumulator: | |
| 632 break; | |
| 633 case kStack: | |
| 634 if_true = &discard; | |
| 635 break; | |
| 636 } | |
| 637 break; | |
| 638 } | |
| 639 | |
| 640 // Emit the inlined tests assumed by the stub. | 475 // Emit the inlined tests assumed by the stub. |
| 641 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); | 476 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
| 642 __ j(equal, if_false); | 477 __ j(equal, if_false); |
| 643 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); | 478 __ CompareRoot(result_register(), Heap::kTrueValueRootIndex); |
| 644 __ j(equal, if_true); | 479 __ j(equal, if_true); |
| 645 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); | 480 __ CompareRoot(result_register(), Heap::kFalseValueRootIndex); |
| 646 __ j(equal, if_false); | 481 __ j(equal, if_false); |
| 647 ASSERT_EQ(0, kSmiTag); | 482 ASSERT_EQ(0, kSmiTag); |
| 648 __ SmiCompare(result_register(), Smi::FromInt(0)); | 483 __ SmiCompare(result_register(), Smi::FromInt(0)); |
| 649 __ j(equal, if_false); | 484 __ j(equal, if_false); |
| 650 Condition is_smi = masm_->CheckSmi(result_register()); | 485 Condition is_smi = masm_->CheckSmi(result_register()); |
| 651 __ j(is_smi, if_true); | 486 __ j(is_smi, if_true); |
| 652 | 487 |
| 653 // Save a copy of the value if it may be needed and isn't already saved. | |
| 654 switch (context) { | |
| 655 case Expression::kUninitialized: | |
| 656 case Expression::kEffect: | |
| 657 case Expression::kValue: | |
| 658 UNREACHABLE(); | |
| 659 case Expression::kTest: | |
| 660 break; | |
| 661 case Expression::kValueTest: | |
| 662 switch (location_) { | |
| 663 case kAccumulator: | |
| 664 __ push(result_register()); | |
| 665 break; | |
| 666 case kStack: | |
| 667 break; | |
| 668 } | |
| 669 break; | |
| 670 case Expression::kTestValue: | |
| 671 switch (location_) { | |
| 672 case kAccumulator: | |
| 673 __ push(result_register()); | |
| 674 break; | |
| 675 case kStack: | |
| 676 break; | |
| 677 } | |
| 678 break; | |
| 679 } | |
| 680 | |
| 681 // Call the ToBoolean stub for all other cases. | 488 // Call the ToBoolean stub for all other cases. |
| 682 ToBooleanStub stub; | 489 ToBooleanStub stub; |
| 683 __ push(result_register()); | 490 __ push(result_register()); |
| 684 __ CallStub(&stub); | 491 __ CallStub(&stub); |
| 685 __ testq(rax, rax); | 492 __ testq(rax, rax); |
| 686 | 493 |
| 687 // The stub returns nonzero for true. Complete based on the context. | 494 // The stub returns nonzero for true. |
| 688 switch (context) { | 495 Split(not_zero, if_true, if_false, fall_through); |
| 689 case Expression::kUninitialized: | 496 } |
| 690 case Expression::kEffect: | |
| 691 case Expression::kValue: | |
| 692 UNREACHABLE(); | |
| 693 | 497 |
| 694 case Expression::kTest: | |
| 695 __ j(not_zero, true_label_); | |
| 696 __ jmp(false_label_); | |
| 697 break; | |
| 698 | 498 |
| 699 case Expression::kValueTest: | 499 void FullCodeGenerator::Split(Condition cc, |
| 700 switch (location_) { | 500 Label* if_true, |
| 701 case kAccumulator: | 501 Label* if_false, |
| 702 __ j(zero, &discard); | 502 Label* fall_through) { |
| 703 __ pop(result_register()); | 503 if (if_false == fall_through) { |
| 704 __ jmp(true_label_); | 504 __ j(cc, if_true); |
| 705 break; | 505 } else if (if_true == fall_through) { |
| 706 case kStack: | 506 __ j(NegateCondition(cc), if_false); |
| 707 __ j(not_zero, true_label_); | 507 } else { |
| 708 break; | 508 __ j(cc, if_true); |
| 709 } | 509 __ jmp(if_false); |
| 710 __ bind(&discard); | |
| 711 __ Drop(1); | |
| 712 __ jmp(false_label_); | |
| 713 break; | |
| 714 | |
| 715 case Expression::kTestValue: | |
| 716 switch (location_) { | |
| 717 case kAccumulator: | |
| 718 __ j(not_zero, &discard); | |
| 719 __ pop(result_register()); | |
| 720 __ jmp(false_label_); | |
| 721 break; | |
| 722 case kStack: | |
| 723 __ j(zero, false_label_); | |
| 724 break; | |
| 725 } | |
| 726 __ bind(&discard); | |
| 727 __ Drop(1); | |
| 728 __ jmp(true_label_); | |
| 729 break; | |
| 730 } | 510 } |
| 731 } | 511 } |
| 732 | 512 |
| 733 | 513 |
| 734 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 514 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
| 735 switch (slot->type()) { | 515 switch (slot->type()) { |
| 736 case Slot::PARAMETER: | 516 case Slot::PARAMETER: |
| 737 case Slot::LOCAL: | 517 case Slot::LOCAL: |
| 738 return Operand(rbp, SlotOffset(slot)); | 518 return Operand(rbp, SlotOffset(slot)); |
| 739 case Slot::CONTEXT: { | 519 case Slot::CONTEXT: { |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 Comment cmnt(masm_, "[ RegExpLiteral"); | 979 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1200 Label materialized; | 980 Label materialized; |
| 1201 // Registers will be used as follows: | 981 // Registers will be used as follows: |
| 1202 // rdi = JS function. | 982 // rdi = JS function. |
| 1203 // rcx = literals array. | 983 // rcx = literals array. |
| 1204 // rbx = regexp literal. | 984 // rbx = regexp literal. |
| 1205 // rax = regexp literal clone. | 985 // rax = regexp literal clone. |
| 1206 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 986 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1207 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 987 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 1208 int literal_offset = | 988 int literal_offset = |
| 1209 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 989 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 1210 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 990 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
| 1211 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 991 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 1212 __ j(not_equal, &materialized); | 992 __ j(not_equal, &materialized); |
| 1213 | 993 |
| 1214 // Create regexp literal using runtime function | 994 // Create regexp literal using runtime function |
| 1215 // Result will be in rax. | 995 // Result will be in rax. |
| 1216 __ push(rcx); | 996 __ push(rcx); |
| 1217 __ Push(Smi::FromInt(expr->literal_index())); | 997 __ Push(Smi::FromInt(expr->literal_index())); |
| 1218 __ Push(expr->pattern()); | 998 __ Push(expr->pattern()); |
| 1219 __ Push(expr->flags()); | 999 __ Push(expr->flags()); |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1980 ASSERT(args->length() == 1); | 1760 ASSERT(args->length() == 1); |
| 1981 | 1761 |
| 1982 VisitForValue(args->at(0), kAccumulator); | 1762 VisitForValue(args->at(0), kAccumulator); |
| 1983 | 1763 |
| 1984 Label materialize_true, materialize_false; | 1764 Label materialize_true, materialize_false; |
| 1985 Label* if_true = NULL; | 1765 Label* if_true = NULL; |
| 1986 Label* if_false = NULL; | 1766 Label* if_false = NULL; |
| 1987 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1767 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 1988 | 1768 |
| 1989 Condition positive_smi = __ CheckPositiveSmi(rax); | 1769 Condition positive_smi = __ CheckPositiveSmi(rax); |
| 1990 __ j(positive_smi, if_true); | 1770 Split(positive_smi, if_true, if_false, NULL); |
| 1991 __ jmp(if_false); | |
| 1992 | 1771 |
| 1993 Apply(context_, if_true, if_false); | 1772 Apply(context_, if_true, if_false); |
| 1994 } | 1773 } |
| 1995 | 1774 |
| 1996 | 1775 |
| 1997 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1776 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
| 1998 ASSERT(args->length() == 1); | 1777 ASSERT(args->length() == 1); |
| 1999 | 1778 |
| 2000 VisitForValue(args->at(0), kAccumulator); | 1779 VisitForValue(args->at(0), kAccumulator); |
| 2001 | 1780 |
| 2002 Label materialize_true, materialize_false; | 1781 Label materialize_true, materialize_false; |
| 2003 Label* if_true = NULL; | 1782 Label* if_true = NULL; |
| 2004 Label* if_false = NULL; | 1783 Label* if_false = NULL; |
| 2005 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1784 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2006 | 1785 |
| 2007 __ JumpIfSmi(rax, if_false); | 1786 __ JumpIfSmi(rax, if_false); |
| 2008 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 1787 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
| 2009 __ j(equal, if_true); | 1788 __ j(equal, if_true); |
| 2010 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1789 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 2011 // Undetectable objects behave like undefined when tested with typeof. | 1790 // Undetectable objects behave like undefined when tested with typeof. |
| 2012 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1791 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
| 2013 Immediate(1 << Map::kIsUndetectable)); | 1792 Immediate(1 << Map::kIsUndetectable)); |
| 2014 __ j(not_zero, if_false); | 1793 __ j(not_zero, if_false); |
| 2015 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 1794 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
| 2016 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); | 1795 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); |
| 2017 __ j(below, if_false); | 1796 __ j(below, if_false); |
| 2018 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); | 1797 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); |
| 2019 __ j(below_equal, if_true); | 1798 Split(below_equal, if_true, if_false, NULL); |
| 2020 __ jmp(if_false); | |
| 2021 | 1799 |
| 2022 Apply(context_, if_true, if_false); | 1800 Apply(context_, if_true, if_false); |
| 2023 } | 1801 } |
| 2024 | 1802 |
| 2025 | 1803 |
| 2026 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1804 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
| 2027 ASSERT(args->length() == 1); | 1805 ASSERT(args->length() == 1); |
| 2028 | 1806 |
| 2029 VisitForValue(args->at(0), kAccumulator); | 1807 VisitForValue(args->at(0), kAccumulator); |
| 2030 | 1808 |
| 2031 Label materialize_true, materialize_false; | 1809 Label materialize_true, materialize_false; |
| 2032 Label* if_true = NULL; | 1810 Label* if_true = NULL; |
| 2033 Label* if_false = NULL; | 1811 Label* if_false = NULL; |
| 2034 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1812 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2035 | 1813 |
| 2036 __ JumpIfSmi(rax, if_false); | 1814 __ JumpIfSmi(rax, if_false); |
| 2037 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); | 1815 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); |
| 2038 __ j(above_equal, if_true); | 1816 Split(above_equal, if_true, if_false, NULL); |
| 2039 __ jmp(if_false); | |
| 2040 | 1817 |
| 2041 Apply(context_, if_true, if_false); | 1818 Apply(context_, if_true, if_false); |
| 2042 } | 1819 } |
| 2043 | 1820 |
| 2044 | 1821 |
| 2045 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1822 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
| 2046 ASSERT(args->length() == 1); | 1823 ASSERT(args->length() == 1); |
| 2047 | 1824 |
| 2048 VisitForValue(args->at(0), kAccumulator); | 1825 VisitForValue(args->at(0), kAccumulator); |
| 2049 | 1826 |
| 2050 Label materialize_true, materialize_false; | 1827 Label materialize_true, materialize_false; |
| 2051 Label* if_true = NULL; | 1828 Label* if_true = NULL; |
| 2052 Label* if_false = NULL; | 1829 Label* if_false = NULL; |
| 2053 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1830 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2054 | 1831 |
| 2055 __ JumpIfSmi(rax, if_false); | 1832 __ JumpIfSmi(rax, if_false); |
| 2056 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1833 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
| 2057 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1834 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
| 2058 Immediate(1 << Map::kIsUndetectable)); | 1835 Immediate(1 << Map::kIsUndetectable)); |
| 2059 __ j(not_zero, if_true); | 1836 Split(not_zero, if_true, if_false, NULL); |
| 2060 __ jmp(if_false); | |
| 2061 | 1837 |
| 2062 Apply(context_, if_true, if_false); | 1838 Apply(context_, if_true, if_false); |
| 2063 } | 1839 } |
| 2064 | 1840 |
| 2065 | 1841 |
| 2066 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1842 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
| 2067 ZoneList<Expression*>* args) { | 1843 ZoneList<Expression*>* args) { |
| 2068 ASSERT(args->length() == 1); | 1844 ASSERT(args->length() == 1); |
| 2069 | 1845 |
| 2070 VisitForValue(args->at(0), kAccumulator); | 1846 VisitForValue(args->at(0), kAccumulator); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2087 | 1863 |
| 2088 VisitForValue(args->at(0), kAccumulator); | 1864 VisitForValue(args->at(0), kAccumulator); |
| 2089 | 1865 |
| 2090 Label materialize_true, materialize_false; | 1866 Label materialize_true, materialize_false; |
| 2091 Label* if_true = NULL; | 1867 Label* if_true = NULL; |
| 2092 Label* if_false = NULL; | 1868 Label* if_false = NULL; |
| 2093 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1869 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2094 | 1870 |
| 2095 __ JumpIfSmi(rax, if_false); | 1871 __ JumpIfSmi(rax, if_false); |
| 2096 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 1872 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2097 __ j(equal, if_true); | 1873 Split(equal, if_true, if_false, NULL); |
| 2098 __ jmp(if_false); | |
| 2099 | 1874 |
| 2100 Apply(context_, if_true, if_false); | 1875 Apply(context_, if_true, if_false); |
| 2101 } | 1876 } |
| 2102 | 1877 |
| 2103 | 1878 |
| 2104 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1879 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
| 2105 ASSERT(args->length() == 1); | 1880 ASSERT(args->length() == 1); |
| 2106 | 1881 |
| 2107 VisitForValue(args->at(0), kAccumulator); | 1882 VisitForValue(args->at(0), kAccumulator); |
| 2108 | 1883 |
| 2109 Label materialize_true, materialize_false; | 1884 Label materialize_true, materialize_false; |
| 2110 Label* if_true = NULL; | 1885 Label* if_true = NULL; |
| 2111 Label* if_false = NULL; | 1886 Label* if_false = NULL; |
| 2112 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1887 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2113 | 1888 |
| 2114 __ JumpIfSmi(rax, if_false); | 1889 __ JumpIfSmi(rax, if_false); |
| 2115 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); | 1890 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); |
| 2116 __ j(equal, if_true); | 1891 Split(equal, if_true, if_false, NULL); |
| 2117 __ jmp(if_false); | |
| 2118 | 1892 |
| 2119 Apply(context_, if_true, if_false); | 1893 Apply(context_, if_true, if_false); |
| 2120 } | 1894 } |
| 2121 | 1895 |
| 2122 | 1896 |
| 2123 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1897 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
| 2124 ASSERT(args->length() == 1); | 1898 ASSERT(args->length() == 1); |
| 2125 | 1899 |
| 2126 VisitForValue(args->at(0), kAccumulator); | 1900 VisitForValue(args->at(0), kAccumulator); |
| 2127 | 1901 |
| 2128 Label materialize_true, materialize_false; | 1902 Label materialize_true, materialize_false; |
| 2129 Label* if_true = NULL; | 1903 Label* if_true = NULL; |
| 2130 Label* if_false = NULL; | 1904 Label* if_false = NULL; |
| 2131 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1905 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2132 | 1906 |
| 2133 __ JumpIfSmi(rax, if_false); | 1907 __ JumpIfSmi(rax, if_false); |
| 2134 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); | 1908 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); |
| 2135 __ j(equal, if_true); | 1909 Split(equal, if_true, if_false, NULL); |
| 2136 __ jmp(if_false); | |
| 2137 | 1910 |
| 2138 Apply(context_, if_true, if_false); | 1911 Apply(context_, if_true, if_false); |
| 2139 } | 1912 } |
| 2140 | 1913 |
| 2141 | 1914 |
| 2142 | 1915 |
| 2143 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1916 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
| 2144 ASSERT(args->length() == 0); | 1917 ASSERT(args->length() == 0); |
| 2145 | 1918 |
| 2146 Label materialize_true, materialize_false; | 1919 Label materialize_true, materialize_false; |
| 2147 Label* if_true = NULL; | 1920 Label* if_true = NULL; |
| 2148 Label* if_false = NULL; | 1921 Label* if_false = NULL; |
| 2149 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1922 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2150 | 1923 |
| 2151 // Get the frame pointer for the calling frame. | 1924 // Get the frame pointer for the calling frame. |
| 2152 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1925 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2153 | 1926 |
| 2154 // Skip the arguments adaptor frame if it exists. | 1927 // Skip the arguments adaptor frame if it exists. |
| 2155 Label check_frame_marker; | 1928 Label check_frame_marker; |
| 2156 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), | 1929 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), |
| 2157 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1930 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2158 __ j(not_equal, &check_frame_marker); | 1931 __ j(not_equal, &check_frame_marker); |
| 2159 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 1932 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
| 2160 | 1933 |
| 2161 // Check the marker in the calling frame. | 1934 // Check the marker in the calling frame. |
| 2162 __ bind(&check_frame_marker); | 1935 __ bind(&check_frame_marker); |
| 2163 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), | 1936 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), |
| 2164 Smi::FromInt(StackFrame::CONSTRUCT)); | 1937 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 2165 __ j(equal, if_true); | 1938 Split(equal, if_true, if_false, NULL); |
| 2166 __ jmp(if_false); | |
| 2167 | 1939 |
| 2168 Apply(context_, if_true, if_false); | 1940 Apply(context_, if_true, if_false); |
| 2169 } | 1941 } |
| 2170 | 1942 |
| 2171 | 1943 |
| 2172 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1944 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
| 2173 ASSERT(args->length() == 2); | 1945 ASSERT(args->length() == 2); |
| 2174 | 1946 |
| 2175 // Load the two objects into registers and perform the comparison. | 1947 // Load the two objects into registers and perform the comparison. |
| 2176 VisitForValue(args->at(0), kStack); | 1948 VisitForValue(args->at(0), kStack); |
| 2177 VisitForValue(args->at(1), kAccumulator); | 1949 VisitForValue(args->at(1), kAccumulator); |
| 2178 | 1950 |
| 2179 Label materialize_true, materialize_false; | 1951 Label materialize_true, materialize_false; |
| 2180 Label* if_true = NULL; | 1952 Label* if_true = NULL; |
| 2181 Label* if_false = NULL; | 1953 Label* if_false = NULL; |
| 2182 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1954 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 2183 | 1955 |
| 2184 __ pop(rbx); | 1956 __ pop(rbx); |
| 2185 __ cmpq(rax, rbx); | 1957 __ cmpq(rax, rbx); |
| 2186 __ j(equal, if_true); | 1958 Split(equal, if_true, if_false, NULL); |
| 2187 __ jmp(if_false); | |
| 2188 | 1959 |
| 2189 Apply(context_, if_true, if_false); | 1960 Apply(context_, if_true, if_false); |
| 2190 } | 1961 } |
| 2191 | 1962 |
| 2192 | 1963 |
| 2193 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1964 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
| 2194 ASSERT(args->length() == 1); | 1965 ASSERT(args->length() == 1); |
| 2195 | 1966 |
| 2196 // ArgumentsAccessStub expects the key in edx and the formal | 1967 // ArgumentsAccessStub expects the key in edx and the formal |
| 2197 // parameter count in eax. | 1968 // parameter count in eax. |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2833 case Expression::kValue: | 2604 case Expression::kValue: |
| 2834 switch (location_) { | 2605 switch (location_) { |
| 2835 case kAccumulator: | 2606 case kAccumulator: |
| 2836 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | 2607 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); |
| 2837 break; | 2608 break; |
| 2838 case kStack: | 2609 case kStack: |
| 2839 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2610 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 2840 break; | 2611 break; |
| 2841 } | 2612 } |
| 2842 break; | 2613 break; |
| 2843 case Expression::kTestValue: | |
| 2844 // Value is false so it's needed. | |
| 2845 switch (location_) { | |
| 2846 case kAccumulator: | |
| 2847 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex); | |
| 2848 break; | |
| 2849 case kStack: | |
| 2850 __ PushRoot(Heap::kUndefinedValueRootIndex); | |
| 2851 break; | |
| 2852 } | |
| 2853 // Fall through. | |
| 2854 case Expression::kTest: | 2614 case Expression::kTest: |
| 2855 case Expression::kValueTest: | |
| 2856 __ jmp(false_label_); | 2615 __ jmp(false_label_); |
| 2857 break; | 2616 break; |
| 2858 } | 2617 } |
| 2859 break; | 2618 break; |
| 2860 } | 2619 } |
| 2861 | 2620 |
| 2862 case Token::NOT: { | 2621 case Token::NOT: { |
| 2863 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2622 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
| 2864 Label materialize_true, materialize_false; | 2623 Label materialize_true, materialize_false; |
| 2865 Label* if_true = NULL; | 2624 Label* if_true = NULL; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3026 // Save result for postfix expressions. | 2785 // Save result for postfix expressions. |
| 3027 if (expr->is_postfix()) { | 2786 if (expr->is_postfix()) { |
| 3028 switch (context_) { | 2787 switch (context_) { |
| 3029 case Expression::kUninitialized: | 2788 case Expression::kUninitialized: |
| 3030 UNREACHABLE(); | 2789 UNREACHABLE(); |
| 3031 case Expression::kEffect: | 2790 case Expression::kEffect: |
| 3032 // Do not save result. | 2791 // Do not save result. |
| 3033 break; | 2792 break; |
| 3034 case Expression::kValue: | 2793 case Expression::kValue: |
| 3035 case Expression::kTest: | 2794 case Expression::kTest: |
| 3036 case Expression::kValueTest: | |
| 3037 case Expression::kTestValue: | |
| 3038 // Save the result on the stack. If we have a named or keyed property | 2795 // Save the result on the stack. If we have a named or keyed property |
| 3039 // we store the result under the receiver that is currently on top | 2796 // we store the result under the receiver that is currently on top |
| 3040 // of the stack. | 2797 // of the stack. |
| 3041 switch (assign_type) { | 2798 switch (assign_type) { |
| 3042 case VARIABLE: | 2799 case VARIABLE: |
| 3043 __ push(rax); | 2800 __ push(rax); |
| 3044 break; | 2801 break; |
| 3045 case NAMED_PROPERTY: | 2802 case NAMED_PROPERTY: |
| 3046 __ movq(Operand(rsp, kPointerSize), rax); | 2803 __ movq(Operand(rsp, kPointerSize), rax); |
| 3047 break; | 2804 break; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3131 ApplyTOS(context_); | 2888 ApplyTOS(context_); |
| 3132 } | 2889 } |
| 3133 } else { | 2890 } else { |
| 3134 Apply(context_, rax); | 2891 Apply(context_, rax); |
| 3135 } | 2892 } |
| 3136 break; | 2893 break; |
| 3137 } | 2894 } |
| 3138 } | 2895 } |
| 3139 } | 2896 } |
| 3140 | 2897 |
| 3141 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | |
| 3142 Comment cmnt(masm_, "[ BinaryOperation"); | |
| 3143 switch (expr->op()) { | |
| 3144 case Token::COMMA: | |
| 3145 VisitForEffect(expr->left()); | |
| 3146 Visit(expr->right()); | |
| 3147 break; | |
| 3148 | |
| 3149 case Token::OR: | |
| 3150 case Token::AND: | |
| 3151 EmitLogicalOperation(expr); | |
| 3152 break; | |
| 3153 | |
| 3154 case Token::ADD: | |
| 3155 case Token::SUB: | |
| 3156 case Token::DIV: | |
| 3157 case Token::MOD: | |
| 3158 case Token::MUL: | |
| 3159 case Token::BIT_OR: | |
| 3160 case Token::BIT_AND: | |
| 3161 case Token::BIT_XOR: | |
| 3162 case Token::SHL: | |
| 3163 case Token::SHR: | |
| 3164 case Token::SAR: | |
| 3165 VisitForValue(expr->left(), kStack); | |
| 3166 VisitForValue(expr->right(), kAccumulator); | |
| 3167 EmitBinaryOp(expr->op(), context_); | |
| 3168 break; | |
| 3169 | |
| 3170 default: | |
| 3171 UNREACHABLE(); | |
| 3172 } | |
| 3173 } | |
| 3174 | |
| 3175 | 2898 |
| 3176 void FullCodeGenerator::EmitNullCompare(bool strict, | 2899 void FullCodeGenerator::EmitNullCompare(bool strict, |
| 3177 Register obj, | 2900 Register obj, |
| 3178 Register null_const, | 2901 Register null_const, |
| 3179 Label* if_true, | 2902 Label* if_true, |
| 3180 Label* if_false, | 2903 Label* if_false, |
| 3181 Register scratch) { | 2904 Register scratch) { |
| 3182 __ cmpq(obj, null_const); | 2905 __ cmpq(obj, null_const); |
| 3183 if (strict) { | 2906 if (strict) { |
| 3184 __ j(equal, if_true); | 2907 Split(equal, if_true, if_false, NULL); |
| 3185 } else { | 2908 } else { |
| 3186 __ j(equal, if_true); | 2909 __ j(equal, if_true); |
| 3187 __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); | 2910 __ CompareRoot(obj, Heap::kUndefinedValueRootIndex); |
| 3188 __ j(equal, if_true); | 2911 __ j(equal, if_true); |
| 3189 __ JumpIfSmi(obj, if_false); | 2912 __ JumpIfSmi(obj, if_false); |
| 3190 // It can be an undetectable object. | 2913 // It can be an undetectable object. |
| 3191 __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); | 2914 __ movq(scratch, FieldOperand(obj, HeapObject::kMapOffset)); |
| 3192 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), | 2915 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
| 3193 Immediate(1 << Map::kIsUndetectable)); | 2916 Immediate(1 << Map::kIsUndetectable)); |
| 3194 __ j(not_zero, if_true); | 2917 Split(not_zero, if_true, if_false, NULL); |
| 3195 } | 2918 } |
| 3196 __ jmp(if_false); | |
| 3197 } | 2919 } |
| 3198 | 2920 |
| 3199 | 2921 |
| 3200 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2922 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 3201 Comment cmnt(masm_, "[ CompareOperation"); | 2923 Comment cmnt(masm_, "[ CompareOperation"); |
| 3202 | 2924 |
| 3203 // Always perform the comparison for its control flow. Pack the result | 2925 // Always perform the comparison for its control flow. Pack the result |
| 3204 // into the expression's context after the comparison is performed. | 2926 // into the expression's context after the comparison is performed. |
| 3205 Label materialize_true, materialize_false; | 2927 Label materialize_true, materialize_false; |
| 3206 Label* if_true = NULL; | 2928 Label* if_true = NULL; |
| 3207 Label* if_false = NULL; | 2929 Label* if_false = NULL; |
| 3208 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2930 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); |
| 3209 | 2931 |
| 3210 VisitForValue(expr->left(), kStack); | 2932 VisitForValue(expr->left(), kStack); |
| 3211 switch (expr->op()) { | 2933 switch (expr->op()) { |
| 3212 case Token::IN: | 2934 case Token::IN: |
| 3213 VisitForValue(expr->right(), kStack); | 2935 VisitForValue(expr->right(), kStack); |
| 3214 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 2936 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
| 3215 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 2937 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
| 3216 __ j(equal, if_true); | 2938 Split(equal, if_true, if_false, NULL); |
| 3217 __ jmp(if_false); | |
| 3218 break; | 2939 break; |
| 3219 | 2940 |
| 3220 case Token::INSTANCEOF: { | 2941 case Token::INSTANCEOF: { |
| 3221 VisitForValue(expr->right(), kStack); | 2942 VisitForValue(expr->right(), kStack); |
| 3222 InstanceofStub stub; | 2943 InstanceofStub stub; |
| 3223 __ CallStub(&stub); | 2944 __ CallStub(&stub); |
| 3224 __ testq(rax, rax); | 2945 __ testq(rax, rax); |
| 3225 __ j(zero, if_true); // The stub returns 0 for true. | 2946 // The stub returns 0 for true. |
| 3226 __ jmp(if_false); | 2947 Split(zero, if_true, if_false, NULL); |
| 3227 break; | 2948 break; |
| 3228 } | 2949 } |
| 3229 | 2950 |
| 3230 default: { | 2951 default: { |
| 3231 VisitForValue(expr->right(), kAccumulator); | 2952 VisitForValue(expr->right(), kAccumulator); |
| 3232 Condition cc = no_condition; | 2953 Condition cc = no_condition; |
| 3233 bool strict = false; | 2954 bool strict = false; |
| 3234 switch (expr->op()) { | 2955 switch (expr->op()) { |
| 3235 case Token::EQ_STRICT: | 2956 case Token::EQ_STRICT: |
| 3236 strict = true; | 2957 strict = true; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3284 Label slow_case; | 3005 Label slow_case; |
| 3285 __ JumpIfNotBothSmi(rax, rdx, &slow_case); | 3006 __ JumpIfNotBothSmi(rax, rdx, &slow_case); |
| 3286 __ SmiCompare(rdx, rax); | 3007 __ SmiCompare(rdx, rax); |
| 3287 __ j(cc, if_true); | 3008 __ j(cc, if_true); |
| 3288 __ jmp(if_false); | 3009 __ jmp(if_false); |
| 3289 | 3010 |
| 3290 __ bind(&slow_case); | 3011 __ bind(&slow_case); |
| 3291 CompareStub stub(cc, strict); | 3012 CompareStub stub(cc, strict); |
| 3292 __ CallStub(&stub); | 3013 __ CallStub(&stub); |
| 3293 __ testq(rax, rax); | 3014 __ testq(rax, rax); |
| 3294 __ j(cc, if_true); | 3015 Split(cc, if_true, if_false, NULL); |
| 3295 __ jmp(if_false); | |
| 3296 } | 3016 } |
| 3297 } | 3017 } |
| 3298 | 3018 |
| 3299 // Convert the result of the comparison into one expected for this | 3019 // Convert the result of the comparison into one expected for this |
| 3300 // expression's context. | 3020 // expression's context. |
| 3301 Apply(context_, if_true, if_false); | 3021 Apply(context_, if_true, if_false); |
| 3302 } | 3022 } |
| 3303 | 3023 |
| 3304 | 3024 |
| 3305 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3025 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3358 __ ret(0); | 3078 __ ret(0); |
| 3359 } | 3079 } |
| 3360 | 3080 |
| 3361 | 3081 |
| 3362 #undef __ | 3082 #undef __ |
| 3363 | 3083 |
| 3364 | 3084 |
| 3365 } } // namespace v8::internal | 3085 } } // namespace v8::internal |
| 3366 | 3086 |
| 3367 #endif // V8_TARGET_ARCH_X64 | 3087 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |