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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 void EmitJumpIfSmi(Register reg, Label* target) { | 94 void EmitJumpIfSmi(Register reg, Label* target) { |
95 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 95 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
96 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 96 ASSERT(!patch_site_.is_bound() && !info_emitted_); |
97 __ bind(&patch_site_); | 97 __ bind(&patch_site_); |
98 __ andi(at, reg, 0); | 98 __ andi(at, reg, 0); |
99 // Never taken before patched. | 99 // Never taken before patched. |
100 __ Branch(target, ne, at, Operand(zero_reg)); | 100 __ Branch(target, ne, at, Operand(zero_reg)); |
101 } | 101 } |
102 | 102 |
103 void EmitPatchInfo() { | 103 void EmitPatchInfo() { |
104 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); | 104 if (patch_site_.is_bound()) { |
105 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); | 105 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); |
106 __ andi(at, reg, delta_to_patch_site % kImm16Mask); | 106 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); |
| 107 __ andi(at, reg, delta_to_patch_site % kImm16Mask); |
107 #ifdef DEBUG | 108 #ifdef DEBUG |
108 info_emitted_ = true; | 109 info_emitted_ = true; |
109 #endif | 110 #endif |
| 111 } else { |
| 112 __ nop(); // Signals no inlined code. |
| 113 } |
110 } | 114 } |
111 | 115 |
112 bool is_bound() const { return patch_site_.is_bound(); } | |
113 | |
114 private: | 116 private: |
115 MacroAssembler* masm_; | 117 MacroAssembler* masm_; |
116 Label patch_site_; | 118 Label patch_site_; |
117 #ifdef DEBUG | 119 #ifdef DEBUG |
118 bool info_emitted_; | 120 bool info_emitted_; |
119 #endif | 121 #endif |
120 }; | 122 }; |
121 | 123 |
122 | 124 |
123 // Generate code for a JS function. On entry to the function the receiver | 125 // Generate code for a JS function. On entry to the function the receiver |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 __ Branch(&next_test, ne, a1, Operand(a0)); | 860 __ Branch(&next_test, ne, a1, Operand(a0)); |
859 __ Drop(1); // Switch value is no longer needed. | 861 __ Drop(1); // Switch value is no longer needed. |
860 __ Branch(clause->body_target()); | 862 __ Branch(clause->body_target()); |
861 | 863 |
862 __ bind(&slow_case); | 864 __ bind(&slow_case); |
863 } | 865 } |
864 | 866 |
865 // Record position before stub call for type feedback. | 867 // Record position before stub call for type feedback. |
866 SetSourcePosition(clause->position()); | 868 SetSourcePosition(clause->position()); |
867 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 869 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
868 EmitCallIC(ic, &patch_site, clause->CompareId()); | 870 EmitCallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
| 871 patch_site.EmitPatchInfo(); |
869 | 872 |
870 __ Branch(&next_test, ne, v0, Operand(zero_reg)); | 873 __ Branch(&next_test, ne, v0, Operand(zero_reg)); |
871 __ Drop(1); // Switch value is no longer needed. | 874 __ Drop(1); // Switch value is no longer needed. |
872 __ Branch(clause->body_target()); | 875 __ Branch(clause->body_target()); |
873 } | 876 } |
874 | 877 |
875 // Discard the test value and jump to the default if present, otherwise to | 878 // Discard the test value and jump to the default if present, otherwise to |
876 // the end of the statement. | 879 // the end of the statement. |
877 __ bind(&next_test); | 880 __ bind(&next_test); |
878 __ Drop(1); // Switch value is no longer needed. | 881 __ Drop(1); // Switch value is no longer needed. |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 __ mov(a0, result_register()); | 1689 __ mov(a0, result_register()); |
1687 | 1690 |
1688 // Perform combined smi check on both operands. | 1691 // Perform combined smi check on both operands. |
1689 __ Or(scratch1, left, Operand(right)); | 1692 __ Or(scratch1, left, Operand(right)); |
1690 STATIC_ASSERT(kSmiTag == 0); | 1693 STATIC_ASSERT(kSmiTag == 0); |
1691 JumpPatchSite patch_site(masm_); | 1694 JumpPatchSite patch_site(masm_); |
1692 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1695 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1693 | 1696 |
1694 __ bind(&stub_call); | 1697 __ bind(&stub_call); |
1695 BinaryOpStub stub(op, mode); | 1698 BinaryOpStub stub(op, mode); |
1696 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); | 1699 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1700 patch_site.EmitPatchInfo(); |
1697 __ jmp(&done); | 1701 __ jmp(&done); |
1698 | 1702 |
1699 __ bind(&smi_case); | 1703 __ bind(&smi_case); |
1700 // Smi case. This code works the same way as the smi-smi case in the type | 1704 // Smi case. This code works the same way as the smi-smi case in the type |
1701 // recording binary operation stub, see | 1705 // recording binary operation stub, see |
1702 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1706 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
1703 switch (op) { | 1707 switch (op) { |
1704 case Token::SAR: | 1708 case Token::SAR: |
1705 __ Branch(&stub_call); | 1709 __ Branch(&stub_call); |
1706 __ GetLeastBitsFromSmi(scratch1, right, 5); | 1710 __ GetLeastBitsFromSmi(scratch1, right, 5); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 context()->Plug(v0); | 1771 context()->Plug(v0); |
1768 } | 1772 } |
1769 | 1773 |
1770 | 1774 |
1771 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1775 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
1772 Token::Value op, | 1776 Token::Value op, |
1773 OverwriteMode mode) { | 1777 OverwriteMode mode) { |
1774 __ mov(a0, result_register()); | 1778 __ mov(a0, result_register()); |
1775 __ pop(a1); | 1779 __ pop(a1); |
1776 BinaryOpStub stub(op, mode); | 1780 BinaryOpStub stub(op, mode); |
1777 EmitCallIC(stub.GetCode(), NULL, expr->id()); | 1781 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1782 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1783 patch_site.EmitPatchInfo(); |
1778 context()->Plug(v0); | 1784 context()->Plug(v0); |
1779 } | 1785 } |
1780 | 1786 |
1781 | 1787 |
1782 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1788 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1783 // Invalid left-hand sides are rewritten to have a 'throw | 1789 // Invalid left-hand sides are rewritten to have a 'throw |
1784 // ReferenceError' on the left-hand side. | 1790 // ReferenceError' on the left-hand side. |
1785 if (!expr->IsValidLeftHandSide()) { | 1791 if (!expr->IsValidLeftHandSide()) { |
1786 VisitForEffect(expr); | 1792 VisitForEffect(expr); |
1787 return; | 1793 return; |
(...skipping 2087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3875 // We could eliminate this smi check if we split the code at | 3881 // We could eliminate this smi check if we split the code at |
3876 // the first smi check before calling ToNumber. | 3882 // the first smi check before calling ToNumber. |
3877 patch_site.EmitJumpIfSmi(v0, &done); | 3883 patch_site.EmitJumpIfSmi(v0, &done); |
3878 __ bind(&stub_call); | 3884 __ bind(&stub_call); |
3879 } | 3885 } |
3880 | 3886 |
3881 // Record position before stub call. | 3887 // Record position before stub call. |
3882 SetSourcePosition(expr->position()); | 3888 SetSourcePosition(expr->position()); |
3883 | 3889 |
3884 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 3890 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
3885 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); | 3891 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
| 3892 patch_site.EmitPatchInfo(); |
3886 __ bind(&done); | 3893 __ bind(&done); |
3887 | 3894 |
3888 // Store the value returned in v0. | 3895 // Store the value returned in v0. |
3889 switch (assign_type) { | 3896 switch (assign_type) { |
3890 case VARIABLE: | 3897 case VARIABLE: |
3891 if (expr->is_postfix()) { | 3898 if (expr->is_postfix()) { |
3892 { EffectContext context(this); | 3899 { EffectContext context(this); |
3893 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3900 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3894 Token::ASSIGN); | 3901 Token::ASSIGN); |
3895 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3902 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4146 if (inline_smi_code) { | 4153 if (inline_smi_code) { |
4147 Label slow_case; | 4154 Label slow_case; |
4148 __ Or(a2, a0, Operand(a1)); | 4155 __ Or(a2, a0, Operand(a1)); |
4149 patch_site.EmitJumpIfNotSmi(a2, &slow_case); | 4156 patch_site.EmitJumpIfNotSmi(a2, &slow_case); |
4150 Split(cc, a1, Operand(a0), if_true, if_false, NULL); | 4157 Split(cc, a1, Operand(a0), if_true, if_false, NULL); |
4151 __ bind(&slow_case); | 4158 __ bind(&slow_case); |
4152 } | 4159 } |
4153 // Record position and call the compare IC. | 4160 // Record position and call the compare IC. |
4154 SetSourcePosition(expr->position()); | 4161 SetSourcePosition(expr->position()); |
4155 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4162 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4156 EmitCallIC(ic, &patch_site, expr->id()); | 4163 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 4164 patch_site.EmitPatchInfo(); |
4157 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4165 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4158 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4166 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); |
4159 } | 4167 } |
4160 } | 4168 } |
4161 | 4169 |
4162 // Convert the result of the comparison into one expected for this | 4170 // Convert the result of the comparison into one expected for this |
4163 // expression's context. | 4171 // expression's context. |
4164 context()->Plug(if_true, if_false); | 4172 context()->Plug(if_true, if_false); |
4165 } | 4173 } |
4166 | 4174 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4210 Register FullCodeGenerator::context_register() { | 4218 Register FullCodeGenerator::context_register() { |
4211 return cp; | 4219 return cp; |
4212 } | 4220 } |
4213 | 4221 |
4214 | 4222 |
4215 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4223 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, |
4216 RelocInfo::Mode mode, | 4224 RelocInfo::Mode mode, |
4217 unsigned ast_id) { | 4225 unsigned ast_id) { |
4218 ASSERT(mode == RelocInfo::CODE_TARGET || | 4226 ASSERT(mode == RelocInfo::CODE_TARGET || |
4219 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4227 mode == RelocInfo::CODE_TARGET_CONTEXT); |
4220 Counters* counters = isolate()->counters(); | |
4221 switch (ic->kind()) { | |
4222 case Code::LOAD_IC: | |
4223 __ IncrementCounter(counters->named_load_full(), 1, a1, a2); | |
4224 break; | |
4225 case Code::KEYED_LOAD_IC: | |
4226 __ IncrementCounter(counters->keyed_load_full(), 1, a1, a2); | |
4227 break; | |
4228 case Code::STORE_IC: | |
4229 __ IncrementCounter(counters->named_store_full(), 1, a1, a2); | |
4230 break; | |
4231 case Code::KEYED_STORE_IC: | |
4232 __ IncrementCounter(counters->keyed_store_full(), 1, a1, a2); | |
4233 default: | |
4234 break; | |
4235 } | |
4236 if (ast_id == kNoASTId || mode == RelocInfo::CODE_TARGET_CONTEXT) { | 4228 if (ast_id == kNoASTId || mode == RelocInfo::CODE_TARGET_CONTEXT) { |
4237 __ Call(ic, mode); | 4229 __ Call(ic, mode); |
4238 } else { | 4230 } else { |
4239 ASSERT(mode == RelocInfo::CODE_TARGET); | 4231 ASSERT(mode == RelocInfo::CODE_TARGET); |
4240 mode = RelocInfo::CODE_TARGET_WITH_ID; | 4232 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); |
4241 __ CallWithAstId(ic, mode, ast_id); | |
4242 } | 4233 } |
4243 } | 4234 } |
4244 | 4235 |
4245 | 4236 |
4246 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | |
4247 JumpPatchSite* patch_site, | |
4248 unsigned ast_id) { | |
4249 Counters* counters = isolate()->counters(); | |
4250 switch (ic->kind()) { | |
4251 case Code::LOAD_IC: | |
4252 __ IncrementCounter(counters->named_load_full(), 1, a1, a2); | |
4253 break; | |
4254 case Code::KEYED_LOAD_IC: | |
4255 __ IncrementCounter(counters->keyed_load_full(), 1, a1, a2); | |
4256 break; | |
4257 case Code::STORE_IC: | |
4258 __ IncrementCounter(counters->named_store_full(), 1, a1, a2); | |
4259 break; | |
4260 case Code::KEYED_STORE_IC: | |
4261 __ IncrementCounter(counters->keyed_store_full(), 1, a1, a2); | |
4262 default: | |
4263 break; | |
4264 } | |
4265 | |
4266 if (ast_id == kNoASTId) { | |
4267 __ Call(ic, RelocInfo::CODE_TARGET); | |
4268 } else { | |
4269 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); | |
4270 } | |
4271 if (patch_site != NULL && patch_site->is_bound()) { | |
4272 patch_site->EmitPatchInfo(); | |
4273 } else { | |
4274 __ nop(); // Signals no inlined code. | |
4275 } | |
4276 } | |
4277 | |
4278 | |
4279 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4237 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4280 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4238 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
4281 __ sw(value, MemOperand(fp, frame_offset)); | 4239 __ sw(value, MemOperand(fp, frame_offset)); |
4282 } | 4240 } |
4283 | 4241 |
4284 | 4242 |
4285 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4243 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
4286 __ lw(dst, ContextOperand(cp, context_index)); | 4244 __ lw(dst, ContextOperand(cp, context_index)); |
4287 } | 4245 } |
4288 | 4246 |
(...skipping 25 matching lines...) Expand all Loading... |
4314 __ Addu(at, a1, Operand(masm_->CodeObject())); | 4272 __ Addu(at, a1, Operand(masm_->CodeObject())); |
4315 __ Jump(at); | 4273 __ Jump(at); |
4316 } | 4274 } |
4317 | 4275 |
4318 | 4276 |
4319 #undef __ | 4277 #undef __ |
4320 | 4278 |
4321 } } // namespace v8::internal | 4279 } } // namespace v8::internal |
4322 | 4280 |
4323 #endif // V8_TARGET_ARCH_MIPS | 4281 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |