| 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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 if (FLAG_debug_code) { | 357 if (FLAG_debug_code) { |
| 358 // Check if we have the correct context pointer. | 358 // Check if we have the correct context pointer. |
| 359 __ ldr(r1, CodeGenerator::ContextOperand( | 359 __ ldr(r1, CodeGenerator::ContextOperand( |
| 360 cp, Context::FCONTEXT_INDEX)); | 360 cp, Context::FCONTEXT_INDEX)); |
| 361 __ cmp(r1, cp); | 361 __ cmp(r1, cp); |
| 362 __ Check(eq, "Unexpected declaration in current context."); | 362 __ Check(eq, "Unexpected declaration in current context."); |
| 363 } | 363 } |
| 364 __ str(r0, CodeGenerator::ContextOperand(cp, slot->index())); | 364 __ str(r0, CodeGenerator::ContextOperand(cp, slot->index())); |
| 365 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 365 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 366 __ mov(r2, Operand(offset)); | 366 __ mov(r2, Operand(offset)); |
| 367 // We know that we have written a function, which is not a smi. |
| 367 __ RecordWrite(cp, r2, r0); | 368 __ RecordWrite(cp, r2, r0); |
| 368 } | 369 } |
| 369 break; | 370 break; |
| 370 default: | 371 default: |
| 371 UNREACHABLE(); | 372 UNREACHABLE(); |
| 372 } | 373 } |
| 373 } | 374 } |
| 374 | 375 |
| 375 | 376 |
| 376 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 377 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 __ stm(db_w, sp, cp.bit() | r0.bit()); | 415 __ stm(db_w, sp, cp.bit() | r0.bit()); |
| 415 __ CallRuntime(Runtime::kNewClosure, 2); | 416 __ CallRuntime(Runtime::kNewClosure, 2); |
| 416 Move(expr->context(), r0); | 417 Move(expr->context(), r0); |
| 417 } | 418 } |
| 418 | 419 |
| 419 | 420 |
| 420 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 421 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 421 Comment cmnt(masm_, "[ VariableProxy"); | 422 Comment cmnt(masm_, "[ VariableProxy"); |
| 422 Expression* rewrite = expr->var()->rewrite(); | 423 Expression* rewrite = expr->var()->rewrite(); |
| 423 if (rewrite == NULL) { | 424 if (rewrite == NULL) { |
| 425 ASSERT(expr->var()->is_global()); |
| 424 Comment cmnt(masm_, "Global variable"); | 426 Comment cmnt(masm_, "Global variable"); |
| 425 // Use inline caching. Variable name is passed in r2 and the global | 427 // Use inline caching. Variable name is passed in r2 and the global |
| 426 // object on the stack. | 428 // object on the stack. |
| 427 __ ldr(ip, CodeGenerator::GlobalObject()); | 429 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 428 __ push(ip); | 430 __ push(ip); |
| 429 __ mov(r2, Operand(expr->name())); | 431 __ mov(r2, Operand(expr->name())); |
| 430 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 432 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 431 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 433 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 432 DropAndMove(expr->context(), r0); | 434 DropAndMove(expr->context(), r0); |
| 433 } else { | 435 } else { |
| 434 Comment cmnt(masm_, "Stack slot"); | 436 Slot* slot = rewrite->AsSlot(); |
| 435 Move(expr->context(), rewrite->AsSlot()); | 437 ASSERT_NE(NULL, slot); |
| 438 switch (slot->type()) { |
| 439 case Slot::LOCAL: |
| 440 case Slot::PARAMETER: { |
| 441 Comment cmnt(masm_, "Stack slot"); |
| 442 Move(expr->context(), rewrite->AsSlot()); |
| 443 break; |
| 444 } |
| 445 |
| 446 case Slot::CONTEXT: { |
| 447 Comment cmnt(masm_, "Context slot"); |
| 448 int chain_length = |
| 449 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 450 if (chain_length > 0) { |
| 451 // Move up the chain of contexts to the context containing the slot. |
| 452 __ ldr(r0, CodeGenerator::ContextOperand(cp, Context::CLOSURE_INDEX)); |
| 453 // Load the function context (which is the incoming, outer context). |
| 454 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 455 for (int i = 1; i < chain_length; i++) { |
| 456 __ ldr(r0, |
| 457 CodeGenerator::ContextOperand(r0, Context::CLOSURE_INDEX)); |
| 458 // Load the function context (which is the incoming, outer context). |
| 459 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 460 } |
| 461 // The context may be an intermediate context, not a function context. |
| 462 __ ldr(r0, |
| 463 CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX)); |
| 464 } else { // Slot is in the current context. |
| 465 __ ldr(r0, |
| 466 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX)); |
| 467 } |
| 468 __ ldr(r0, CodeGenerator::ContextOperand(r0, slot->index())); |
| 469 Move(expr->context(), r0); |
| 470 break; |
| 471 } |
| 472 |
| 473 case Slot::LOOKUP: |
| 474 UNREACHABLE(); |
| 475 break; |
| 476 } |
| 436 } | 477 } |
| 437 } | 478 } |
| 438 | 479 |
| 439 | 480 |
| 440 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 481 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 441 Comment cmnt(masm_, "[ RegExpLiteral"); | 482 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 442 Label done; | 483 Label done; |
| 443 // Registers will be used as follows: | 484 // Registers will be used as follows: |
| 444 // r4 = JS function, literals array | 485 // r4 = JS function, literals array |
| 445 // r3 = literal index | 486 // r3 = literal index |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 __ pop(r0); | 739 __ pop(r0); |
| 699 __ mov(r2, Operand(var->name())); | 740 __ mov(r2, Operand(var->name())); |
| 700 __ ldr(ip, CodeGenerator::GlobalObject()); | 741 __ ldr(ip, CodeGenerator::GlobalObject()); |
| 701 __ push(ip); | 742 __ push(ip); |
| 702 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 743 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 703 __ Call(ic, RelocInfo::CODE_TARGET); | 744 __ Call(ic, RelocInfo::CODE_TARGET); |
| 704 // Overwrite the global object on the stack with the result if needed. | 745 // Overwrite the global object on the stack with the result if needed. |
| 705 DropAndMove(expr->context(), r0); | 746 DropAndMove(expr->context(), r0); |
| 706 | 747 |
| 707 } else { | 748 } else { |
| 708 switch (expr->context()) { | 749 Slot* slot = var->slot(); |
| 709 case Expression::kUninitialized: | 750 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. |
| 710 UNREACHABLE(); | 751 switch (slot->type()) { |
| 711 case Expression::kEffect: | 752 case Slot::LOCAL: |
| 712 // Perform assignment and discard value. | 753 case Slot::PARAMETER: { |
| 713 __ pop(r0); | 754 switch (expr->context()) { |
| 714 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 755 case Expression::kUninitialized: |
| 715 break; | 756 UNREACHABLE(); |
| 716 case Expression::kValue: | 757 case Expression::kEffect: |
| 717 // Perform assignment and preserve value. | 758 // Perform assignment and discard value. |
| 718 __ ldr(r0, MemOperand(sp)); | 759 __ pop(r0); |
| 719 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 760 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 720 break; | 761 break; |
| 721 case Expression::kTest: | 762 case Expression::kValue: |
| 722 // Perform assignment and test (and discard) value. | 763 // Perform assignment and preserve value. |
| 723 __ pop(r0); | 764 __ ldr(r0, MemOperand(sp)); |
| 724 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 765 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 725 TestAndBranch(r0, true_label_, false_label_); | 766 break; |
| 726 break; | 767 case Expression::kTest: |
| 727 case Expression::kValueTest: { | 768 // Perform assignment and test (and discard) value. |
| 728 Label discard; | 769 __ pop(r0); |
| 729 __ ldr(r0, MemOperand(sp)); | 770 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 730 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 771 TestAndBranch(r0, true_label_, false_label_); |
| 731 TestAndBranch(r0, true_label_, &discard); | 772 break; |
| 732 __ bind(&discard); | 773 case Expression::kValueTest: { |
| 733 __ pop(); | 774 Label discard; |
| 734 __ jmp(false_label_); | 775 __ ldr(r0, MemOperand(sp)); |
| 776 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 777 TestAndBranch(r0, true_label_, &discard); |
| 778 __ bind(&discard); |
| 779 __ pop(); |
| 780 __ jmp(false_label_); |
| 781 break; |
| 782 } |
| 783 case Expression::kTestValue: { |
| 784 Label discard; |
| 785 __ ldr(r0, MemOperand(sp)); |
| 786 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 787 TestAndBranch(r0, &discard, false_label_); |
| 788 __ bind(&discard); |
| 789 __ pop(); |
| 790 __ jmp(true_label_); |
| 791 break; |
| 792 } |
| 793 } |
| 735 break; | 794 break; |
| 736 } | 795 } |
| 737 case Expression::kTestValue: { | 796 |
| 738 Label discard; | 797 case Slot::CONTEXT: { |
| 739 __ ldr(r0, MemOperand(sp)); | 798 int chain_length = |
| 740 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 799 function_->scope()->ContextChainLength(slot->var()->scope()); |
| 741 TestAndBranch(r0, &discard, false_label_); | 800 if (chain_length > 0) { |
| 742 __ bind(&discard); | 801 // Move up the chain of contexts to the context containing the slot. |
| 743 __ pop(); | 802 __ ldr(r0, CodeGenerator::ContextOperand(cp, Context::CLOSURE_INDEX)); |
| 744 __ jmp(true_label_); | 803 // Load the function context (which is the incoming, outer context). |
| 804 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 805 for (int i = 1; i < chain_length; i++) { |
| 806 __ ldr(r0, |
| 807 CodeGenerator::ContextOperand(r0, Context::CLOSURE_INDEX)); |
| 808 __ ldr(r0, FieldMemOperand(r0, JSFunction::kContextOffset)); |
| 809 } |
| 810 } else { // Slot is in the current context. Generate optimized code. |
| 811 __ mov(r0, cp); |
| 812 } |
| 813 // The context may be an intermediate context, not a function context. |
| 814 __ ldr(r0, CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX)); |
| 815 __ pop(r1); |
| 816 __ str(r1, CodeGenerator::ContextOperand(r0, slot->index())); |
| 817 |
| 818 // RecordWrite may destroy all its register arguments. |
| 819 if (expr->context() == Expression::kValue) { |
| 820 __ push(r1); |
| 821 } else if (expr->context() != Expression::kEffect) { |
| 822 __ mov(r3, r1); |
| 823 } |
| 824 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 825 |
| 826 // Update the write barrier for the array store with r0 as the scratch |
| 827 // register. Skip the write barrier if r0 is a smi. |
| 828 // The smi test is part of RecordWrite on other platforms, not on arm. |
| 829 Label exit; |
| 830 __ tst(r0, Operand(kSmiTagMask)); |
| 831 __ b(eq, &exit); |
| 832 |
| 833 __ mov(r2, Operand(offset)); |
| 834 __ RecordWrite(r0, r2, r1); |
| 835 __ bind(&exit); |
| 836 if (expr->context() != Expression::kEffect && |
| 837 expr->context() != Expression::kValue) { |
| 838 Move(expr->context(), r3); |
| 839 } |
| 745 break; | 840 break; |
| 746 } | 841 } |
| 842 |
| 843 case Slot::LOOKUP: |
| 844 UNREACHABLE(); |
| 845 break; |
| 747 } | 846 } |
| 748 } | 847 } |
| 749 } | 848 } |
| 750 | 849 |
| 751 | 850 |
| 752 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 851 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 753 // Assignment to a property, using a named store IC. | 852 // Assignment to a property, using a named store IC. |
| 754 Property* prop = expr->target()->AsProperty(); | 853 Property* prop = expr->target()->AsProperty(); |
| 755 ASSERT(prop != NULL); | 854 ASSERT(prop != NULL); |
| 756 ASSERT(prop->key()->AsLiteral() != NULL); | 855 ASSERT(prop->key()->AsLiteral() != NULL); |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1426 true_label_ = saved_true; | 1525 true_label_ = saved_true; |
| 1427 false_label_ = saved_false; | 1526 false_label_ = saved_false; |
| 1428 // Convert current context to test context: End post-test code. | 1527 // Convert current context to test context: End post-test code. |
| 1429 } | 1528 } |
| 1430 | 1529 |
| 1431 | 1530 |
| 1432 #undef __ | 1531 #undef __ |
| 1433 | 1532 |
| 1434 | 1533 |
| 1435 } } // namespace v8::internal | 1534 } } // namespace v8::internal |
| OLD | NEW |