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