| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 27 matching lines...) Expand all Loading... |
| 38 #include "scopes.h" | 38 #include "scopes.h" |
| 39 #include "stub-cache.h" | 39 #include "stub-cache.h" |
| 40 | 40 |
| 41 #include "arm/code-stubs-arm.h" | 41 #include "arm/code-stubs-arm.h" |
| 42 | 42 |
| 43 namespace v8 { | 43 namespace v8 { |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 #define __ ACCESS_MASM(masm_) | 46 #define __ ACCESS_MASM(masm_) |
| 47 | 47 |
| 48 |
| 49 // A patch site is a location in the code which it is possible to patch. This |
| 50 // class has a number of methods to emit the code which is patchable and the |
| 51 // method EmitPatchInfo to record a marker back to the patchable code. This |
| 52 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit |
| 53 // immediate value is used) is the delta from the pc to the first instruction of |
| 54 // the patchable code. |
| 55 class JumpPatchSite BASE_EMBEDDED { |
| 56 public: |
| 57 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
| 58 #ifdef DEBUG |
| 59 info_emitted_ = false; |
| 60 #endif |
| 61 } |
| 62 |
| 63 ~JumpPatchSite() { |
| 64 ASSERT(patch_site_.is_bound() == info_emitted_); |
| 65 } |
| 66 |
| 67 // When initially emitting this ensure that a jump is always generated to skip |
| 68 // the inlined smi code. |
| 69 void EmitJumpIfNotSmi(Register reg, Label* target) { |
| 70 ASSERT(!patch_site_.is_bound() && !info_emitted_); |
| 71 __ bind(&patch_site_); |
| 72 __ cmp(reg, Operand(reg)); |
| 73 // Don't use b(al, ...) as that might emit the constant pool right after the |
| 74 // branch. After patching when the branch is no longer unconditional |
| 75 // execution can continue into the constant pool. |
| 76 __ b(eq, target); // Always taken before patched. |
| 77 } |
| 78 |
| 79 // When initially emitting this ensure that a jump is never generated to skip |
| 80 // the inlined smi code. |
| 81 void EmitJumpIfSmi(Register reg, Label* target) { |
| 82 ASSERT(!patch_site_.is_bound() && !info_emitted_); |
| 83 __ bind(&patch_site_); |
| 84 __ cmp(reg, Operand(reg)); |
| 85 __ b(ne, target); // Never taken before patched. |
| 86 } |
| 87 |
| 88 void EmitPatchInfo() { |
| 89 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); |
| 90 Register reg; |
| 91 reg.set_code(delta_to_patch_site / kOff12Mask); |
| 92 __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); |
| 93 #ifdef DEBUG |
| 94 info_emitted_ = true; |
| 95 #endif |
| 96 } |
| 97 |
| 98 bool is_bound() const { return patch_site_.is_bound(); } |
| 99 |
| 100 private: |
| 101 MacroAssembler* masm_; |
| 102 Label patch_site_; |
| 103 #ifdef DEBUG |
| 104 bool info_emitted_; |
| 105 #endif |
| 106 }; |
| 107 |
| 108 |
| 48 // Generate code for a JS function. On entry to the function the receiver | 109 // Generate code for a JS function. On entry to the function the receiver |
| 49 // and arguments have been pushed on the stack left to right. The actual | 110 // and arguments have been pushed on the stack left to right. The actual |
| 50 // argument count matches the formal parameter count expected by the | 111 // argument count matches the formal parameter count expected by the |
| 51 // function. | 112 // function. |
| 52 // | 113 // |
| 53 // The live registers are: | 114 // The live registers are: |
| 54 // o r1: the JS function object being called (ie, ourselves) | 115 // o r1: the JS function object being called (ie, ourselves) |
| 55 // o cp: our context | 116 // o cp: our context |
| 56 // o fp: our caller's frame pointer | 117 // o fp: our caller's frame pointer |
| 57 // o sp: stack pointer | 118 // o sp: stack pointer |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 Comment cmnt(masm_, "[ Case comparison"); | 806 Comment cmnt(masm_, "[ Case comparison"); |
| 746 __ bind(&next_test); | 807 __ bind(&next_test); |
| 747 next_test.Unuse(); | 808 next_test.Unuse(); |
| 748 | 809 |
| 749 // Compile the label expression. | 810 // Compile the label expression. |
| 750 VisitForAccumulatorValue(clause->label()); | 811 VisitForAccumulatorValue(clause->label()); |
| 751 | 812 |
| 752 // Perform the comparison as if via '==='. | 813 // Perform the comparison as if via '==='. |
| 753 __ ldr(r1, MemOperand(sp, 0)); // Switch value. | 814 __ ldr(r1, MemOperand(sp, 0)); // Switch value. |
| 754 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); | 815 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); |
| 816 JumpPatchSite patch_site(masm_); |
| 755 if (inline_smi_code) { | 817 if (inline_smi_code) { |
| 756 Label slow_case; | 818 Label slow_case; |
| 757 __ orr(r2, r1, r0); | 819 __ orr(r2, r1, r0); |
| 758 __ tst(r2, Operand(kSmiTagMask)); | 820 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 759 __ b(ne, &slow_case); | 821 |
| 760 __ cmp(r1, r0); | 822 __ cmp(r1, r0); |
| 761 __ b(ne, &next_test); | 823 __ b(ne, &next_test); |
| 762 __ Drop(1); // Switch value is no longer needed. | 824 __ Drop(1); // Switch value is no longer needed. |
| 763 __ b(clause->body_target()->entry_label()); | 825 __ b(clause->body_target()->entry_label()); |
| 764 __ bind(&slow_case); | 826 __ bind(&slow_case); |
| 765 } | 827 } |
| 766 | 828 |
| 767 CompareFlags flags = inline_smi_code | 829 // Record position before stub call for type feedback. |
| 768 ? NO_SMI_COMPARE_IN_STUB | 830 SetSourcePosition(clause->position()); |
| 769 : NO_COMPARE_FLAGS; | 831 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
| 770 CompareStub stub(eq, true, flags, r1, r0); | 832 EmitCallIC(ic, &patch_site); |
| 771 __ CallStub(&stub); | 833 __ cmp(r0, Operand(0)); |
| 772 __ cmp(r0, Operand(0, RelocInfo::NONE)); | |
| 773 __ b(ne, &next_test); | 834 __ b(ne, &next_test); |
| 774 __ Drop(1); // Switch value is no longer needed. | 835 __ Drop(1); // Switch value is no longer needed. |
| 775 __ b(clause->body_target()->entry_label()); | 836 __ b(clause->body_target()->entry_label()); |
| 776 } | 837 } |
| 777 | 838 |
| 778 // Discard the test value and jump to the default if present, otherwise to | 839 // Discard the test value and jump to the default if present, otherwise to |
| 779 // the end of the statement. | 840 // the end of the statement. |
| 780 __ bind(&next_test); | 841 __ bind(&next_test); |
| 781 __ Drop(1); // Switch value is no longer needed. | 842 __ Drop(1); // Switch value is no longer needed. |
| 782 if (default_clause == NULL) { | 843 if (default_clause == NULL) { |
| (...skipping 2720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3503 cond = ge; | 3564 cond = ge; |
| 3504 __ pop(r1); | 3565 __ pop(r1); |
| 3505 break; | 3566 break; |
| 3506 case Token::IN: | 3567 case Token::IN: |
| 3507 case Token::INSTANCEOF: | 3568 case Token::INSTANCEOF: |
| 3508 default: | 3569 default: |
| 3509 UNREACHABLE(); | 3570 UNREACHABLE(); |
| 3510 } | 3571 } |
| 3511 | 3572 |
| 3512 bool inline_smi_code = ShouldInlineSmiCase(op); | 3573 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 3574 JumpPatchSite patch_site(masm_); |
| 3513 if (inline_smi_code) { | 3575 if (inline_smi_code) { |
| 3514 Label slow_case; | 3576 Label slow_case; |
| 3515 __ orr(r2, r0, Operand(r1)); | 3577 __ orr(r2, r0, Operand(r1)); |
| 3516 __ JumpIfNotSmi(r2, &slow_case); | 3578 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 3517 __ cmp(r1, r0); | 3579 __ cmp(r1, r0); |
| 3518 Split(cond, if_true, if_false, NULL); | 3580 Split(cond, if_true, if_false, NULL); |
| 3519 __ bind(&slow_case); | 3581 __ bind(&slow_case); |
| 3520 } | 3582 } |
| 3521 CompareFlags flags = inline_smi_code | 3583 |
| 3522 ? NO_SMI_COMPARE_IN_STUB | 3584 // Record position and call the compare IC. |
| 3523 : NO_COMPARE_FLAGS; | 3585 SetSourcePosition(expr->position()); |
| 3524 CompareStub stub(cond, strict, flags, r1, r0); | 3586 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 3525 __ CallStub(&stub); | 3587 EmitCallIC(ic, &patch_site); |
| 3526 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3588 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3527 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 3589 __ cmp(r0, Operand(0)); |
| 3528 Split(cond, if_true, if_false, fall_through); | 3590 Split(cond, if_true, if_false, fall_through); |
| 3529 } | 3591 } |
| 3530 } | 3592 } |
| 3531 | 3593 |
| 3532 // Convert the result of the comparison into one expected for this | 3594 // Convert the result of the comparison into one expected for this |
| 3533 // expression's context. | 3595 // expression's context. |
| 3534 context()->Plug(if_true, if_false); | 3596 context()->Plug(if_true, if_false); |
| 3535 } | 3597 } |
| 3536 | 3598 |
| 3537 | 3599 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3584 } | 3646 } |
| 3585 | 3647 |
| 3586 | 3648 |
| 3587 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 3649 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 3588 ASSERT(mode == RelocInfo::CODE_TARGET || | 3650 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 3589 mode == RelocInfo::CODE_TARGET_CONTEXT); | 3651 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 3590 __ Call(ic, mode); | 3652 __ Call(ic, mode); |
| 3591 } | 3653 } |
| 3592 | 3654 |
| 3593 | 3655 |
| 3656 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
| 3657 __ Call(ic, RelocInfo::CODE_TARGET); |
| 3658 if (patch_site != NULL && patch_site->is_bound()) { |
| 3659 patch_site->EmitPatchInfo(); |
| 3660 } else { |
| 3661 __ nop(); // Signals no inlined code. |
| 3662 } |
| 3663 } |
| 3664 |
| 3665 |
| 3594 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 3666 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 3595 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 3667 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 3596 __ str(value, MemOperand(fp, frame_offset)); | 3668 __ str(value, MemOperand(fp, frame_offset)); |
| 3597 } | 3669 } |
| 3598 | 3670 |
| 3599 | 3671 |
| 3600 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 3672 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 3601 __ ldr(dst, ContextOperand(cp, context_index)); | 3673 __ ldr(dst, ContextOperand(cp, context_index)); |
| 3602 } | 3674 } |
| 3603 | 3675 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3628 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3700 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3629 __ add(pc, r1, Operand(masm_->CodeObject())); | 3701 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3630 } | 3702 } |
| 3631 | 3703 |
| 3632 | 3704 |
| 3633 #undef __ | 3705 #undef __ |
| 3634 | 3706 |
| 3635 } } // namespace v8::internal | 3707 } } // namespace v8::internal |
| 3636 | 3708 |
| 3637 #endif // V8_TARGET_ARCH_ARM | 3709 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |