Chromium Code Reviews| 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 the emit the code which is patchable and the | |
|
Alexandre
2011/02/09 13:57:16
typo: "the emit the code" -> "to emit the code" ?
Søren Thygesen Gjesse
2011/02/09 14:48:28
Done.
| |
| 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(r0, delta_to_patch_site % kOff12Mask); | |
|
Karl Klose
2011/02/09 14:35:30
The destination register of the cmp should be reg.
Søren Thygesen Gjesse
2011/02/09 14:48:28
Good catch, fixed.
| |
| 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 |
| 772 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 834 __ cmp(r0, Operand(0)); |
| 773 __ b(ne, &next_test); | 835 __ b(ne, &next_test); |
| 774 __ Drop(1); // Switch value is no longer needed. | 836 __ Drop(1); // Switch value is no longer needed. |
| 775 __ b(clause->body_target()->entry_label()); | 837 __ b(clause->body_target()->entry_label()); |
| 776 } | 838 } |
| 777 | 839 |
| 778 // Discard the test value and jump to the default if present, otherwise to | 840 // Discard the test value and jump to the default if present, otherwise to |
| 779 // the end of the statement. | 841 // the end of the statement. |
| 780 __ bind(&next_test); | 842 __ bind(&next_test); |
| 781 __ Drop(1); // Switch value is no longer needed. | 843 __ Drop(1); // Switch value is no longer needed. |
| 782 if (default_clause == NULL) { | 844 if (default_clause == NULL) { |
| (...skipping 2720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3503 cond = ge; | 3565 cond = ge; |
| 3504 __ pop(r1); | 3566 __ pop(r1); |
| 3505 break; | 3567 break; |
| 3506 case Token::IN: | 3568 case Token::IN: |
| 3507 case Token::INSTANCEOF: | 3569 case Token::INSTANCEOF: |
| 3508 default: | 3570 default: |
| 3509 UNREACHABLE(); | 3571 UNREACHABLE(); |
| 3510 } | 3572 } |
| 3511 | 3573 |
| 3512 bool inline_smi_code = ShouldInlineSmiCase(op); | 3574 bool inline_smi_code = ShouldInlineSmiCase(op); |
| 3575 JumpPatchSite patch_site(masm_); | |
| 3513 if (inline_smi_code) { | 3576 if (inline_smi_code) { |
| 3514 Label slow_case; | 3577 Label slow_case; |
| 3515 __ orr(r2, r0, Operand(r1)); | 3578 __ orr(r2, r0, Operand(r1)); |
| 3516 __ JumpIfNotSmi(r2, &slow_case); | 3579 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 3517 __ cmp(r1, r0); | 3580 __ cmp(r1, r0); |
| 3518 Split(cond, if_true, if_false, NULL); | 3581 Split(cond, if_true, if_false, NULL); |
| 3519 __ bind(&slow_case); | 3582 __ bind(&slow_case); |
| 3520 } | 3583 } |
| 3521 CompareFlags flags = inline_smi_code | 3584 |
| 3522 ? NO_SMI_COMPARE_IN_STUB | 3585 // Record position and call the compare IC. |
| 3523 : NO_COMPARE_FLAGS; | 3586 SetSourcePosition(expr->position()); |
| 3524 CompareStub stub(cond, strict, flags, r1, r0); | 3587 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 3525 __ CallStub(&stub); | 3588 EmitCallIC(ic, &patch_site); |
| 3526 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 3589 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 3527 __ cmp(r0, Operand(0, RelocInfo::NONE)); | 3590 __ cmp(r0, Operand(0)); |
| 3528 Split(cond, if_true, if_false, fall_through); | 3591 Split(cond, if_true, if_false, fall_through); |
| 3529 } | 3592 } |
| 3530 } | 3593 } |
| 3531 | 3594 |
| 3532 // Convert the result of the comparison into one expected for this | 3595 // Convert the result of the comparison into one expected for this |
| 3533 // expression's context. | 3596 // expression's context. |
| 3534 context()->Plug(if_true, if_false); | 3597 context()->Plug(if_true, if_false); |
| 3535 } | 3598 } |
| 3536 | 3599 |
| 3537 | 3600 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3584 } | 3647 } |
| 3585 | 3648 |
| 3586 | 3649 |
| 3587 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 3650 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 3588 ASSERT(mode == RelocInfo::CODE_TARGET || | 3651 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 3589 mode == RelocInfo::CODE_TARGET_CONTEXT); | 3652 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 3590 __ Call(ic, mode); | 3653 __ Call(ic, mode); |
| 3591 } | 3654 } |
| 3592 | 3655 |
| 3593 | 3656 |
| 3657 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { | |
| 3658 __ Call(ic, RelocInfo::CODE_TARGET); | |
| 3659 if (patch_site != NULL && patch_site->is_bound()) { | |
| 3660 patch_site->EmitPatchInfo(); | |
| 3661 } else { | |
| 3662 __ nop(); // Signals no inlined code. | |
| 3663 } | |
| 3664 } | |
| 3665 | |
| 3666 | |
| 3594 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 3667 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 3595 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 3668 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 3596 __ str(value, MemOperand(fp, frame_offset)); | 3669 __ str(value, MemOperand(fp, frame_offset)); |
| 3597 } | 3670 } |
| 3598 | 3671 |
| 3599 | 3672 |
| 3600 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 3673 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 3601 __ ldr(dst, ContextOperand(cp, context_index)); | 3674 __ ldr(dst, ContextOperand(cp, context_index)); |
| 3602 } | 3675 } |
| 3603 | 3676 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 3628 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3701 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3629 __ add(pc, r1, Operand(masm_->CodeObject())); | 3702 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3630 } | 3703 } |
| 3631 | 3704 |
| 3632 | 3705 |
| 3633 #undef __ | 3706 #undef __ |
| 3634 | 3707 |
| 3635 } } // namespace v8::internal | 3708 } } // namespace v8::internal |
| 3636 | 3709 |
| 3637 #endif // V8_TARGET_ARCH_ARM | 3710 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |