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 |