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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 55 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
56 #ifdef DEBUG | 56 #ifdef DEBUG |
57 info_emitted_ = false; | 57 info_emitted_ = false; |
58 #endif | 58 #endif |
59 } | 59 } |
60 | 60 |
61 ~JumpPatchSite() { | 61 ~JumpPatchSite() { |
62 ASSERT(patch_site_.is_bound() == info_emitted_); | 62 ASSERT(patch_site_.is_bound() == info_emitted_); |
63 } | 63 } |
64 | 64 |
65 void EmitJumpIfNotSmi(Register reg, NearLabel* target) { | 65 void EmitJumpIfNotSmi(Register reg, |
| 66 Label* target, |
| 67 Label::Distance near = Label::kFar) { |
66 __ test(reg, Immediate(kSmiTagMask)); | 68 __ test(reg, Immediate(kSmiTagMask)); |
67 EmitJump(not_carry, target); // Always taken before patched. | 69 EmitJump(not_carry, target, near); // Always taken before patched. |
68 } | 70 } |
69 | 71 |
70 void EmitJumpIfSmi(Register reg, NearLabel* target) { | 72 void EmitJumpIfSmi(Register reg, |
| 73 Label* target, |
| 74 Label::Distance near = Label::kFar) { |
71 __ test(reg, Immediate(kSmiTagMask)); | 75 __ test(reg, Immediate(kSmiTagMask)); |
72 EmitJump(carry, target); // Never taken before patched. | 76 EmitJump(carry, target, near); // Never taken before patched. |
73 } | 77 } |
74 | 78 |
75 void EmitPatchInfo() { | 79 void EmitPatchInfo() { |
76 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); | 80 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); |
77 ASSERT(is_int8(delta_to_patch_site)); | 81 ASSERT(is_int8(delta_to_patch_site)); |
78 __ test(eax, Immediate(delta_to_patch_site)); | 82 __ test(eax, Immediate(delta_to_patch_site)); |
79 #ifdef DEBUG | 83 #ifdef DEBUG |
80 info_emitted_ = true; | 84 info_emitted_ = true; |
81 #endif | 85 #endif |
82 } | 86 } |
83 | 87 |
84 bool is_bound() const { return patch_site_.is_bound(); } | 88 bool is_bound() const { return patch_site_.is_bound(); } |
85 | 89 |
86 private: | 90 private: |
87 // jc will be patched with jz, jnc will become jnz. | 91 // jc will be patched with jz, jnc will become jnz. |
88 void EmitJump(Condition cc, NearLabel* target) { | 92 void EmitJump(Condition cc, Label* target, Label::Distance near) { |
89 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 93 ASSERT(!patch_site_.is_bound() && !info_emitted_); |
90 ASSERT(cc == carry || cc == not_carry); | 94 ASSERT(cc == carry || cc == not_carry); |
91 __ bind(&patch_site_); | 95 __ bind(&patch_site_); |
92 __ j(cc, target); | 96 __ j(cc, target, near); |
93 } | 97 } |
94 | 98 |
95 MacroAssembler* masm_; | 99 MacroAssembler* masm_; |
96 Label patch_site_; | 100 Label patch_site_; |
97 #ifdef DEBUG | 101 #ifdef DEBUG |
98 bool info_emitted_; | 102 bool info_emitted_; |
99 #endif | 103 #endif |
100 }; | 104 }; |
101 | 105 |
102 | 106 |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 next_test.Unuse(); | 795 next_test.Unuse(); |
792 | 796 |
793 // Compile the label expression. | 797 // Compile the label expression. |
794 VisitForAccumulatorValue(clause->label()); | 798 VisitForAccumulatorValue(clause->label()); |
795 | 799 |
796 // Perform the comparison as if via '==='. | 800 // Perform the comparison as if via '==='. |
797 __ mov(edx, Operand(esp, 0)); // Switch value. | 801 __ mov(edx, Operand(esp, 0)); // Switch value. |
798 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); | 802 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); |
799 JumpPatchSite patch_site(masm_); | 803 JumpPatchSite patch_site(masm_); |
800 if (inline_smi_code) { | 804 if (inline_smi_code) { |
801 NearLabel slow_case; | 805 Label slow_case; |
802 __ mov(ecx, edx); | 806 __ mov(ecx, edx); |
803 __ or_(ecx, Operand(eax)); | 807 __ or_(ecx, Operand(eax)); |
804 patch_site.EmitJumpIfNotSmi(ecx, &slow_case); | 808 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
805 | 809 |
806 __ cmp(edx, Operand(eax)); | 810 __ cmp(edx, Operand(eax)); |
807 __ j(not_equal, &next_test); | 811 __ j(not_equal, &next_test); |
808 __ Drop(1); // Switch value is no longer needed. | 812 __ Drop(1); // Switch value is no longer needed. |
809 __ jmp(clause->body_target()); | 813 __ jmp(clause->body_target()); |
810 __ bind(&slow_case); | 814 __ bind(&slow_case); |
811 } | 815 } |
812 | 816 |
813 // Record position before stub call for type feedback. | 817 // Record position before stub call for type feedback. |
814 SetSourcePosition(clause->position()); | 818 SetSourcePosition(clause->position()); |
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 } | 1654 } |
1651 | 1655 |
1652 | 1656 |
1653 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1657 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1654 Token::Value op, | 1658 Token::Value op, |
1655 OverwriteMode mode, | 1659 OverwriteMode mode, |
1656 Expression* left, | 1660 Expression* left, |
1657 Expression* right) { | 1661 Expression* right) { |
1658 // Do combined smi check of the operands. Left operand is on the | 1662 // Do combined smi check of the operands. Left operand is on the |
1659 // stack. Right operand is in eax. | 1663 // stack. Right operand is in eax. |
1660 NearLabel smi_case; | 1664 Label smi_case, done, stub_call; |
1661 Label done, stub_call; | |
1662 __ pop(edx); | 1665 __ pop(edx); |
1663 __ mov(ecx, eax); | 1666 __ mov(ecx, eax); |
1664 __ or_(eax, Operand(edx)); | 1667 __ or_(eax, Operand(edx)); |
1665 JumpPatchSite patch_site(masm_); | 1668 JumpPatchSite patch_site(masm_); |
1666 patch_site.EmitJumpIfSmi(eax, &smi_case); | 1669 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
1667 | 1670 |
1668 __ bind(&stub_call); | 1671 __ bind(&stub_call); |
1669 __ mov(eax, ecx); | 1672 __ mov(eax, ecx); |
1670 TypeRecordingBinaryOpStub stub(op, mode); | 1673 TypeRecordingBinaryOpStub stub(op, mode); |
1671 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); | 1674 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); |
1672 __ jmp(&done, Label::kNear); | 1675 __ jmp(&done, Label::kNear); |
1673 | 1676 |
1674 // Smi case. | 1677 // Smi case. |
1675 __ bind(&smi_case); | 1678 __ bind(&smi_case); |
1676 __ mov(eax, edx); // Copy left operand in case of a stub call. | 1679 __ mov(eax, edx); // Copy left operand in case of a stub call. |
(...skipping 2176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3853 __ mov(Operand(esp, kPointerSize), eax); | 3856 __ mov(Operand(esp, kPointerSize), eax); |
3854 break; | 3857 break; |
3855 case KEYED_PROPERTY: | 3858 case KEYED_PROPERTY: |
3856 __ mov(Operand(esp, 2 * kPointerSize), eax); | 3859 __ mov(Operand(esp, 2 * kPointerSize), eax); |
3857 break; | 3860 break; |
3858 } | 3861 } |
3859 } | 3862 } |
3860 } | 3863 } |
3861 | 3864 |
3862 // Inline smi case if we are in a loop. | 3865 // Inline smi case if we are in a loop. |
3863 NearLabel done; | 3866 Label done, stub_call; |
3864 Label stub_call; | |
3865 JumpPatchSite patch_site(masm_); | 3867 JumpPatchSite patch_site(masm_); |
3866 | 3868 |
3867 if (ShouldInlineSmiCase(expr->op())) { | 3869 if (ShouldInlineSmiCase(expr->op())) { |
3868 if (expr->op() == Token::INC) { | 3870 if (expr->op() == Token::INC) { |
3869 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3871 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
3870 } else { | 3872 } else { |
3871 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3873 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
3872 } | 3874 } |
3873 __ j(overflow, &stub_call, Label::kNear); | 3875 __ j(overflow, &stub_call, Label::kNear); |
3874 // We could eliminate this smi check if we split the code at | 3876 // We could eliminate this smi check if we split the code at |
3875 // the first smi check before calling ToNumber. | 3877 // the first smi check before calling ToNumber. |
3876 patch_site.EmitJumpIfSmi(eax, &done); | 3878 patch_site.EmitJumpIfSmi(eax, &done, Label::kNear); |
3877 | 3879 |
3878 __ bind(&stub_call); | 3880 __ bind(&stub_call); |
3879 // Call stub. Undo operation first. | 3881 // Call stub. Undo operation first. |
3880 if (expr->op() == Token::INC) { | 3882 if (expr->op() == Token::INC) { |
3881 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3883 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
3882 } else { | 3884 } else { |
3883 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3885 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
3884 } | 3886 } |
3885 } | 3887 } |
3886 | 3888 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4149 break; | 4151 break; |
4150 case Token::IN: | 4152 case Token::IN: |
4151 case Token::INSTANCEOF: | 4153 case Token::INSTANCEOF: |
4152 default: | 4154 default: |
4153 UNREACHABLE(); | 4155 UNREACHABLE(); |
4154 } | 4156 } |
4155 | 4157 |
4156 bool inline_smi_code = ShouldInlineSmiCase(op); | 4158 bool inline_smi_code = ShouldInlineSmiCase(op); |
4157 JumpPatchSite patch_site(masm_); | 4159 JumpPatchSite patch_site(masm_); |
4158 if (inline_smi_code) { | 4160 if (inline_smi_code) { |
4159 NearLabel slow_case; | 4161 Label slow_case; |
4160 __ mov(ecx, Operand(edx)); | 4162 __ mov(ecx, Operand(edx)); |
4161 __ or_(ecx, Operand(eax)); | 4163 __ or_(ecx, Operand(eax)); |
4162 patch_site.EmitJumpIfNotSmi(ecx, &slow_case); | 4164 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
4163 __ cmp(edx, Operand(eax)); | 4165 __ cmp(edx, Operand(eax)); |
4164 Split(cc, if_true, if_false, NULL); | 4166 Split(cc, if_true, if_false, NULL); |
4165 __ bind(&slow_case); | 4167 __ bind(&slow_case); |
4166 } | 4168 } |
4167 | 4169 |
4168 // Record position and call the compare IC. | 4170 // Record position and call the compare IC. |
4169 SetSourcePosition(expr->position()); | 4171 SetSourcePosition(expr->position()); |
4170 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4172 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4171 EmitCallIC(ic, &patch_site, expr->id()); | 4173 EmitCallIC(ic, &patch_site, expr->id()); |
4172 | 4174 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4320 // And return. | 4322 // And return. |
4321 __ ret(0); | 4323 __ ret(0); |
4322 } | 4324 } |
4323 | 4325 |
4324 | 4326 |
4325 #undef __ | 4327 #undef __ |
4326 | 4328 |
4327 } } // namespace v8::internal | 4329 } } // namespace v8::internal |
4328 | 4330 |
4329 #endif // V8_TARGET_ARCH_IA32 | 4331 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |