| 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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 Visit(expr->value()); | 286 Visit(expr->value()); |
| 287 } | 287 } |
| 288 | 288 |
| 289 | 289 |
| 290 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { | 290 void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) { |
| 291 BAILOUT("Throw"); | 291 BAILOUT("Throw"); |
| 292 } | 292 } |
| 293 | 293 |
| 294 | 294 |
| 295 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { | 295 void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) { |
| 296 BAILOUT("Property"); | 296 // We support named this property references. |
| 297 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 298 if (proxy == NULL || !proxy->var()->is_this()) { |
| 299 BAILOUT("Non-this-property reference"); |
| 300 } |
| 301 if (!expr->key()->IsPropertyName()) { |
| 302 BAILOUT("Non-named-property reference"); |
| 303 } |
| 304 |
| 305 // We will only specialize for fields on the object itself. |
| 306 // Expression::IsPropertyName implies that the name is a literal |
| 307 // symbol but we do not assume that. |
| 308 Literal* key = expr->key()->AsLiteral(); |
| 309 if (key != NULL && key->handle()->IsString()) { |
| 310 Handle<Object> receiver = info()->receiver(); |
| 311 Handle<String> name = Handle<String>::cast(key->handle()); |
| 312 LookupResult lookup; |
| 313 receiver->Lookup(*name, &lookup); |
| 314 if (lookup.holder() != *receiver) BAILOUT("Non-own property reference"); |
| 315 if (!lookup.type() == FIELD) BAILOUT("Non-field property reference"); |
| 316 } else { |
| 317 UNREACHABLE(); |
| 318 BAILOUT("Unexpected non-string-literal property key"); |
| 319 } |
| 297 } | 320 } |
| 298 | 321 |
| 299 | 322 |
| 300 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) { | 323 void FastCodeGenSyntaxChecker::VisitCall(Call* expr) { |
| 301 BAILOUT("Call"); | 324 BAILOUT("Call"); |
| 302 } | 325 } |
| 303 | 326 |
| 304 | 327 |
| 305 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { | 328 void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { |
| 306 BAILOUT("CallNew"); | 329 BAILOUT("CallNew"); |
| 307 } | 330 } |
| 308 | 331 |
| 309 | 332 |
| 310 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { | 333 void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { |
| 311 BAILOUT("CallRuntime"); | 334 BAILOUT("CallRuntime"); |
| 312 } | 335 } |
| 313 | 336 |
| 314 | 337 |
| 315 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { | 338 void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { |
| 316 BAILOUT("UnaryOperation"); | 339 BAILOUT("UnaryOperation"); |
| 317 } | 340 } |
| 318 | 341 |
| 319 | 342 |
| 320 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { | 343 void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { |
| 321 BAILOUT("CountOperation"); | 344 BAILOUT("CountOperation"); |
| 322 } | 345 } |
| 323 | 346 |
| 324 | 347 |
| 325 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { | 348 void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { |
| 326 BAILOUT("BinaryOperation"); | 349 // We support bitwise OR. |
| 350 switch (expr->op()) { |
| 351 case Token::COMMA: |
| 352 BAILOUT("BinaryOperation COMMA"); |
| 353 case Token::OR: |
| 354 BAILOUT("BinaryOperation OR"); |
| 355 case Token::AND: |
| 356 BAILOUT("BinaryOperation AND"); |
| 357 |
| 358 case Token::BIT_OR: |
| 359 // We support expressions nested on the left because they only require |
| 360 // a pair of registers to keep all intermediate values in registers |
| 361 // (i.e., the expression stack has height no more than two). |
| 362 if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right"); |
| 363 Visit(expr->left()); |
| 364 CHECK_BAILOUT; |
| 365 Visit(expr->right()); |
| 366 break; |
| 367 |
| 368 case Token::BIT_XOR: |
| 369 BAILOUT("BinaryOperation BIT_XOR"); |
| 370 case Token::BIT_AND: |
| 371 BAILOUT("BinaryOperation BIT_AND"); |
| 372 case Token::SHL: |
| 373 BAILOUT("BinaryOperation SHL"); |
| 374 case Token::SAR: |
| 375 BAILOUT("BinaryOperation SAR"); |
| 376 case Token::SHR: |
| 377 BAILOUT("BinaryOperation SHR"); |
| 378 case Token::ADD: |
| 379 BAILOUT("BinaryOperation ADD"); |
| 380 case Token::SUB: |
| 381 BAILOUT("BinaryOperation SUB"); |
| 382 case Token::MUL: |
| 383 BAILOUT("BinaryOperation MUL"); |
| 384 case Token::DIV: |
| 385 BAILOUT("BinaryOperation DIV"); |
| 386 case Token::MOD: |
| 387 BAILOUT("BinaryOperation MOD"); |
| 388 default: |
| 389 UNREACHABLE(); |
| 390 } |
| 327 } | 391 } |
| 328 | 392 |
| 329 | 393 |
| 330 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { | 394 void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { |
| 331 BAILOUT("CompareOperation"); | 395 BAILOUT("CompareOperation"); |
| 332 } | 396 } |
| 333 | 397 |
| 334 | 398 |
| 335 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { | 399 void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { |
| 336 BAILOUT("ThisFunction"); | 400 BAILOUT("ThisFunction"); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 } | 546 } |
| 483 | 547 |
| 484 | 548 |
| 485 void FastCodeGenerator::VisitSlot(Slot* expr) { | 549 void FastCodeGenerator::VisitSlot(Slot* expr) { |
| 486 UNREACHABLE(); | 550 UNREACHABLE(); |
| 487 } | 551 } |
| 488 | 552 |
| 489 | 553 |
| 490 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 554 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 491 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); | 555 ASSERT(expr->var()->is_global() && !expr->var()->is_this()); |
| 492 Comment cmnt(masm(), ";; Global"); | |
| 493 if (FLAG_print_ir) { | |
| 494 SmartPointer<char> name = expr->name()->ToCString(); | |
| 495 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); | |
| 496 } | |
| 497 | |
| 498 // Check if we can compile a global variable load directly from the cell. | 556 // Check if we can compile a global variable load directly from the cell. |
| 499 ASSERT(info()->has_global_object()); | 557 ASSERT(info()->has_global_object()); |
| 500 LookupResult lookup; | 558 LookupResult lookup; |
| 501 info()->global_object()->Lookup(*expr->name(), &lookup); | 559 info()->global_object()->Lookup(*expr->name(), &lookup); |
| 502 // We only support DontDelete properties for now. | 560 // We only support DontDelete properties for now. |
| 503 ASSERT(lookup.IsValid()); | 561 ASSERT(lookup.IsValid()); |
| 504 ASSERT(lookup.IsDontDelete()); | 562 ASSERT(lookup.IsDontDelete()); |
| 505 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); | 563 Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup)); |
| 506 EmitGlobalVariableLoad(cell); | 564 |
| 565 // Global variable lookups do not have side effects, so we do not need to |
| 566 // emit code if we are in an effect context. |
| 567 if (!destination().is(no_reg)) { |
| 568 Comment cmnt(masm(), ";; Global"); |
| 569 if (FLAG_print_ir) { |
| 570 SmartPointer<char> name = expr->name()->ToCString(); |
| 571 PrintF("%d: t%d = Global(%s)\n", expr->num(), expr->num(), *name); |
| 572 } |
| 573 EmitGlobalVariableLoad(cell); |
| 574 } |
| 507 } | 575 } |
| 508 | 576 |
| 509 | 577 |
| 510 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 578 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
| 511 UNREACHABLE(); | 579 UNREACHABLE(); |
| 512 } | 580 } |
| 513 | 581 |
| 514 | 582 |
| 515 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 583 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 516 UNREACHABLE(); | 584 UNREACHABLE(); |
| 517 } | 585 } |
| 518 | 586 |
| 519 | 587 |
| 520 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 588 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 521 UNREACHABLE(); | 589 UNREACHABLE(); |
| 522 } | 590 } |
| 523 | 591 |
| 524 | 592 |
| 525 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 593 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 526 UNREACHABLE(); | 594 UNREACHABLE(); |
| 527 } | 595 } |
| 528 | 596 |
| 529 | 597 |
| 530 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 598 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 531 UNREACHABLE(); | 599 UNREACHABLE(); |
| 532 } | 600 } |
| 533 | 601 |
| 534 | 602 |
| 535 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 603 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 536 // Known to be a simple this property assignment. | 604 // Known to be a simple this property assignment. Effectively a unary |
| 537 Visit(expr->value()); | 605 // operation. |
| 606 { Register my_destination = destination(); |
| 607 set_destination(accumulator0()); |
| 608 Visit(expr->value()); |
| 609 set_destination(my_destination); |
| 610 } |
| 538 | 611 |
| 539 Property* prop = expr->target()->AsProperty(); | 612 Property* prop = expr->target()->AsProperty(); |
| 540 ASSERT_NOT_NULL(prop); | 613 ASSERT_NOT_NULL(prop); |
| 541 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); | 614 ASSERT_NOT_NULL(prop->obj()->AsVariableProxy()); |
| 542 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); | 615 ASSERT(prop->obj()->AsVariableProxy()->var()->is_this()); |
| 543 ASSERT(prop->key()->IsPropertyName()); | 616 ASSERT(prop->key()->IsPropertyName()); |
| 544 Handle<String> name = | 617 Handle<String> name = |
| 545 Handle<String>::cast(prop->key()->AsLiteral()->handle()); | 618 Handle<String>::cast(prop->key()->AsLiteral()->handle()); |
| 546 | 619 |
| 547 Comment cmnt(masm(), ";; Store(this)"); | 620 Comment cmnt(masm(), ";; Store to this"); |
| 548 if (FLAG_print_ir) { | 621 if (FLAG_print_ir) { |
| 549 SmartPointer<char> name_string = name->ToCString(); | 622 SmartPointer<char> name_string = name->ToCString(); |
| 550 PrintF("%d: t%d = Store(this, \"%s\", t%d)\n", | 623 PrintF("%d: ", expr->num()); |
| 551 expr->num(), expr->num(), *name_string, expr->value()->num()); | 624 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
| 625 PrintF("Store(this, \"%s\", t%d)\n", *name_string, expr->value()->num()); |
| 552 } | 626 } |
| 553 | 627 |
| 554 EmitThisPropertyStore(name); | 628 EmitThisPropertyStore(name); |
| 555 } | 629 } |
| 556 | 630 |
| 557 | 631 |
| 558 void FastCodeGenerator::VisitThrow(Throw* expr) { | 632 void FastCodeGenerator::VisitThrow(Throw* expr) { |
| 559 UNREACHABLE(); | 633 UNREACHABLE(); |
| 560 } | 634 } |
| 561 | 635 |
| 562 | 636 |
| 563 void FastCodeGenerator::VisitProperty(Property* expr) { | 637 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 564 UNREACHABLE(); | 638 ASSERT_NOT_NULL(expr->obj()->AsVariableProxy()); |
| 639 ASSERT(expr->obj()->AsVariableProxy()->var()->is_this()); |
| 640 ASSERT(expr->key()->IsPropertyName()); |
| 641 if (!destination().is(no_reg)) { |
| 642 Handle<String> name = |
| 643 Handle<String>::cast(expr->key()->AsLiteral()->handle()); |
| 644 |
| 645 Comment cmnt(masm(), ";; Load from this"); |
| 646 if (FLAG_print_ir) { |
| 647 SmartPointer<char> name_string = name->ToCString(); |
| 648 PrintF("%d: t%d = Load(this, \"%s\")\n", |
| 649 expr->num(), expr->num(), *name_string); |
| 650 } |
| 651 EmitThisPropertyLoad(name); |
| 652 } |
| 565 } | 653 } |
| 566 | 654 |
| 567 | 655 |
| 568 void FastCodeGenerator::VisitCall(Call* expr) { | 656 void FastCodeGenerator::VisitCall(Call* expr) { |
| 569 UNREACHABLE(); | 657 UNREACHABLE(); |
| 570 } | 658 } |
| 571 | 659 |
| 572 | 660 |
| 573 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 661 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
| 574 UNREACHABLE(); | 662 UNREACHABLE(); |
| 575 } | 663 } |
| 576 | 664 |
| 577 | 665 |
| 578 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 666 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 579 UNREACHABLE(); | 667 UNREACHABLE(); |
| 580 } | 668 } |
| 581 | 669 |
| 582 | 670 |
| 583 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 671 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 584 UNREACHABLE(); | 672 UNREACHABLE(); |
| 585 } | 673 } |
| 586 | 674 |
| 587 | 675 |
| 588 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 676 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 589 UNREACHABLE(); | 677 UNREACHABLE(); |
| 590 } | 678 } |
| 591 | 679 |
| 592 | 680 |
| 593 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 681 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 594 UNREACHABLE(); | 682 // We support limited binary operations: bitwise OR only allowed to be |
| 683 // nested on the left. |
| 684 ASSERT(expr->op() == Token::BIT_OR); |
| 685 ASSERT(expr->right()->IsLeaf()); |
| 686 |
| 687 { Register my_destination = destination(); |
| 688 set_destination(accumulator1()); |
| 689 Visit(expr->left()); |
| 690 set_destination(accumulator0()); |
| 691 Visit(expr->right()); |
| 692 set_destination(my_destination); |
| 693 } |
| 694 |
| 695 Comment cmnt(masm(), ";; BIT_OR"); |
| 696 if (FLAG_print_ir) { |
| 697 PrintF("%d: ", expr->num()); |
| 698 if (!destination().is(no_reg)) PrintF("t%d = ", expr->num()); |
| 699 PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num()); |
| 700 } |
| 701 EmitBitOr(); |
| 595 } | 702 } |
| 596 | 703 |
| 597 | 704 |
| 598 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 705 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 599 UNREACHABLE(); | 706 UNREACHABLE(); |
| 600 } | 707 } |
| 601 | 708 |
| 602 | 709 |
| 603 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 710 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 604 UNREACHABLE(); | 711 UNREACHABLE(); |
| 605 } | 712 } |
| 606 | 713 |
| 607 #undef __ | 714 #undef __ |
| 608 | 715 |
| 609 | 716 |
| 610 } } // namespace v8::internal | 717 } } // namespace v8::internal |
| OLD | NEW |