| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 // r0 contains boilerplate. | 373 // r0 contains boilerplate. |
| 374 // Clone boilerplate. | 374 // Clone boilerplate. |
| 375 __ push(r0); | 375 __ push(r0); |
| 376 if (expr->depth() > 1) { | 376 if (expr->depth() > 1) { |
| 377 __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); | 377 __ CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); |
| 378 } else { | 378 } else { |
| 379 __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); | 379 __ CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); |
| 380 } | 380 } |
| 381 | 381 |
| 382 // If result_saved == true: the result is saved on top of the stack. | 382 // If result_saved == true: the result is saved on top of the stack. |
| 383 // If result_saved == false: the result is in eax. | 383 // If result_saved == false: the result is in r0. |
| 384 bool result_saved = false; | 384 bool result_saved = false; |
| 385 | 385 |
| 386 for (int i = 0; i < expr->properties()->length(); i++) { | 386 for (int i = 0; i < expr->properties()->length(); i++) { |
| 387 ObjectLiteral::Property* property = expr->properties()->at(i); | 387 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 388 if (property->IsCompileTimeValue()) continue; | 388 if (property->IsCompileTimeValue()) continue; |
| 389 | 389 |
| 390 Literal* key = property->key(); | 390 Literal* key = property->key(); |
| 391 Expression* value = property->value(); | 391 Expression* value = property->value(); |
| 392 if (!result_saved) { | 392 if (!result_saved) { |
| 393 __ push(r0); // Save result on stack | 393 __ push(r0); // Save result on stack |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 TestAndBranch(r0, &discard, false_label_); | 565 TestAndBranch(r0, &discard, false_label_); |
| 566 __ bind(&discard); | 566 __ bind(&discard); |
| 567 __ pop(); | 567 __ pop(); |
| 568 __ jmp(true_label_); | 568 __ jmp(true_label_); |
| 569 break; | 569 break; |
| 570 } | 570 } |
| 571 } | 571 } |
| 572 } | 572 } |
| 573 | 573 |
| 574 | 574 |
| 575 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 575 void FastCodeGenerator::EmitVariableAssignment(Expression::Context context, |
| 576 Comment cmnt(masm_, "[ Assignment"); | 576 Variable* var) { |
| 577 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 577 if (var->is_global()) { |
| 578 | |
| 579 // Record the source position for the assignment. | |
| 580 SetSourcePosition(expr->position()); | |
| 581 | |
| 582 // Left-hand side can only be a property, a global or | |
| 583 // a (parameter or local) slot. | |
| 584 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
| 585 Expression* rhs = expr->value(); | |
| 586 if (var == NULL) { | |
| 587 // Assignment to a property. | |
| 588 ASSERT(expr->target()->AsProperty() != NULL); | |
| 589 Property* prop = expr->target()->AsProperty(); | |
| 590 Visit(prop->obj()); | |
| 591 Literal* literal_key = prop->key()->AsLiteral(); | |
| 592 uint32_t dummy; | |
| 593 if (literal_key != NULL && | |
| 594 literal_key->handle()->IsSymbol() && | |
| 595 !String::cast(*(literal_key->handle()))->AsArrayIndex(&dummy)) { | |
| 596 // NAMED property assignment | |
| 597 Visit(rhs); | |
| 598 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 599 __ pop(r0); | |
| 600 __ mov(r2, Operand(literal_key->handle())); | |
| 601 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
| 602 __ Call(ic, RelocInfo::CODE_TARGET); | |
| 603 } else { | |
| 604 // KEYED property assignment | |
| 605 Visit(prop->key()); | |
| 606 Visit(rhs); | |
| 607 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 608 __ pop(r0); | |
| 609 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | |
| 610 __ Call(ic, RelocInfo::CODE_TARGET); | |
| 611 // Drop key from the stack | |
| 612 __ pop(); | |
| 613 } | |
| 614 // Overwrite the receiver on the stack with the result if needed. | |
| 615 DropAndMove(expr->context(), r0); | |
| 616 } else if (var->is_global()) { | |
| 617 // Assignment to a global variable, use inline caching. Right-hand-side | 578 // Assignment to a global variable, use inline caching. Right-hand-side |
| 618 // value is passed in r0, variable name in r2, and the global object on | 579 // value is passed in r0, variable name in r2, and the global object |
| 619 // the stack. | 580 // on the stack. |
| 620 | 581 __ pop(r0); |
| 621 // Code for the right-hand-side expression depends on its type. | |
| 622 if (rhs->AsLiteral() != NULL) { | |
| 623 __ mov(r0, Operand(rhs->AsLiteral()->handle())); | |
| 624 } else { | |
| 625 ASSERT_EQ(Expression::kValue, rhs->context()); | |
| 626 Visit(rhs); | |
| 627 __ pop(r0); | |
| 628 } | |
| 629 __ mov(r2, Operand(var->name())); | 582 __ mov(r2, Operand(var->name())); |
| 630 __ ldr(ip, CodeGenerator::GlobalObject()); | 583 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 631 __ push(ip); | 584 __ push(ip); |
| 632 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 585 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 633 __ Call(ic, RelocInfo::CODE_TARGET); | 586 __ Call(ic, RelocInfo::CODE_TARGET); |
| 634 // Overwrite the global object on the stack with the result if needed. | 587 // Overwrite the global object on the stack with the result if needed. |
| 635 DropAndMove(expr->context(), r0); | 588 DropAndMove(context, r0); |
| 636 } else { | 589 } else { |
| 637 // Local or parameter assignment. | 590 switch (context) { |
| 638 | 591 case Expression::kUninitialized: |
| 639 // Code for the right-hand side expression depends on its type. | 592 UNREACHABLE(); |
| 640 if (rhs->AsLiteral() != NULL) { | 593 case Expression::kEffect: |
| 641 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 594 // Perform assignment and discard value. |
| 642 // discarded result. Always perform the assignment. | 595 __ pop(r0); |
| 643 __ mov(ip, Operand(rhs->AsLiteral()->handle())); | 596 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 644 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 597 break; |
| 645 Move(expr->context(), ip); | 598 case Expression::kValue: |
| 646 } else { | 599 // Perform assignment and preserve value. |
| 647 ASSERT_EQ(Expression::kValue, rhs->context()); | 600 __ ldr(r0, MemOperand(sp)); |
| 648 Visit(rhs); | 601 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 649 // Load right-hand side into ip. | 602 break; |
| 650 switch (expr->context()) { | 603 case Expression::kTest: |
| 651 case Expression::kUninitialized: | 604 // Perform assignment and test (and discard) value. |
| 652 UNREACHABLE(); | 605 __ pop(r0); |
| 653 case Expression::kEffect: | 606 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 654 // Case 'var = temp'. Discard right-hand-side temporary. | 607 TestAndBranch(r0, true_label_, false_label_); |
| 655 __ pop(r0); | 608 break; |
| 656 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 609 case Expression::kValueTest: { |
| 657 break; | 610 Label discard; |
| 658 case Expression::kValue: | 611 __ ldr(r0, MemOperand(sp)); |
| 659 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 612 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 660 // temporary on the stack. | 613 TestAndBranch(r0, true_label_, &discard); |
| 661 __ ldr(r0, MemOperand(sp)); | 614 __ bind(&discard); |
| 662 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 615 __ pop(); |
| 663 break; | 616 __ jmp(false_label_); |
| 664 case Expression::kTest: | 617 break; |
| 665 // Case 'if (var = temp) ...'. | 618 } |
| 666 __ pop(r0); | 619 case Expression::kTestValue: { |
| 667 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 620 Label discard; |
| 668 TestAndBranch(r0, true_label_, false_label_); | 621 __ ldr(r0, MemOperand(sp)); |
| 669 break; | 622 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 670 case Expression::kValueTest: { | 623 TestAndBranch(r0, &discard, false_label_); |
| 671 // Case '(var = temp) || ...' in value context. | 624 __ bind(&discard); |
| 672 Label discard; | 625 __ pop(); |
| 673 __ ldr(r0, MemOperand(sp)); | 626 __ jmp(true_label_); |
| 674 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 627 break; |
| 675 TestAndBranch(r0, true_label_, &discard); | |
| 676 __ bind(&discard); | |
| 677 __ pop(); | |
| 678 __ jmp(false_label_); | |
| 679 break; | |
| 680 } | |
| 681 case Expression::kTestValue: { | |
| 682 // Case '(var = temp) && ...' in value context. | |
| 683 Label discard; | |
| 684 __ ldr(r0, MemOperand(sp)); | |
| 685 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | |
| 686 TestAndBranch(r0, &discard, false_label_); | |
| 687 __ bind(&discard); | |
| 688 __ pop(); | |
| 689 __ jmp(true_label_); | |
| 690 break; | |
| 691 } | |
| 692 } | 628 } |
| 693 } | 629 } |
| 694 } | 630 } |
| 695 } | 631 } |
| 696 | 632 |
| 697 | 633 |
| 634 void FastCodeGenerator::EmitNamedPropertyAssignment( |
| 635 Expression::Context context, |
| 636 Handle<Object> name) { |
| 637 __ pop(r0); |
| 638 __ mov(r2, Operand(name)); |
| 639 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 640 __ Call(ic, RelocInfo::CODE_TARGET); |
| 641 DropAndMove(context, r0); |
| 642 } |
| 643 |
| 644 |
| 645 void FastCodeGenerator::EmitKeyedPropertyAssignment( |
| 646 Expression::Context context) { |
| 647 __ pop(r0); |
| 648 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 649 __ Call(ic, RelocInfo::CODE_TARGET); |
| 650 // Receiver and key are still on stack. |
| 651 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 652 Move(context, r0); |
| 653 } |
| 654 |
| 655 |
| 698 void FastCodeGenerator::VisitProperty(Property* expr) { | 656 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 699 Comment cmnt(masm_, "[ Property"); | 657 Comment cmnt(masm_, "[ Property"); |
| 700 Expression* key = expr->key(); | 658 Expression* key = expr->key(); |
| 701 uint32_t dummy; | 659 uint32_t dummy; |
| 702 | 660 |
| 703 // Record the source position for the property load. | 661 // Record the source position for the property load. |
| 704 SetSourcePosition(expr->position()); | 662 SetSourcePosition(expr->position()); |
| 705 | 663 |
| 706 // Evaluate receiver. | 664 // Evaluate receiver. |
| 707 Visit(expr->obj()); | 665 Visit(expr->obj()); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 | 904 |
| 947 break; | 905 break; |
| 948 } | 906 } |
| 949 default: | 907 default: |
| 950 UNREACHABLE(); | 908 UNREACHABLE(); |
| 951 } | 909 } |
| 952 } | 910 } |
| 953 | 911 |
| 954 | 912 |
| 955 } } // namespace v8::internal | 913 } } // namespace v8::internal |
| OLD | NEW |