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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 // When initially emitting this ensure that a jump is never generated to skip | 85 // When initially emitting this ensure that a jump is never generated to skip |
| 86 // the inlined smi code. | 86 // the inlined smi code. |
| 87 void EmitJumpIfSmi(Register reg, Label* target) { | 87 void EmitJumpIfSmi(Register reg, Label* target) { |
| 88 ASSERT(!patch_site_.is_bound() && !info_emitted_); | 88 ASSERT(!patch_site_.is_bound() && !info_emitted_); |
| 89 __ bind(&patch_site_); | 89 __ bind(&patch_site_); |
| 90 __ cmp(reg, Operand(reg)); | 90 __ cmp(reg, Operand(reg)); |
| 91 __ b(ne, target); // Never taken before patched. | 91 __ b(ne, target); // Never taken before patched. |
| 92 } | 92 } |
| 93 | 93 |
| 94 void EmitPatchInfo() { | 94 void EmitPatchInfo() { |
| 95 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); | 95 if (patch_site_.is_bound()) { |
| 96 Register reg; | 96 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); |
| 97 reg.set_code(delta_to_patch_site / kOff12Mask); | 97 Register reg; |
| 98 __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); | 98 reg.set_code(delta_to_patch_site / kOff12Mask); |
| 99 __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); | |
| 99 #ifdef DEBUG | 100 #ifdef DEBUG |
| 100 info_emitted_ = true; | 101 info_emitted_ = true; |
| 101 #endif | 102 #endif |
| 103 } else { | |
| 104 __ nop(); // Signals no inlined code. | |
| 105 } | |
| 102 } | 106 } |
| 103 | 107 |
| 104 bool is_bound() const { return patch_site_.is_bound(); } | |
| 105 | |
| 106 private: | 108 private: |
| 107 MacroAssembler* masm_; | 109 MacroAssembler* masm_; |
| 108 Label patch_site_; | 110 Label patch_site_; |
| 109 #ifdef DEBUG | 111 #ifdef DEBUG |
| 110 bool info_emitted_; | 112 bool info_emitted_; |
| 111 #endif | 113 #endif |
| 112 }; | 114 }; |
| 113 | 115 |
| 114 | 116 |
| 115 // Generate code for a JS function. On entry to the function the receiver | 117 // Generate code for a JS function. On entry to the function the receiver |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 __ cmp(r1, r0); | 855 __ cmp(r1, r0); |
| 854 __ b(ne, &next_test); | 856 __ b(ne, &next_test); |
| 855 __ Drop(1); // Switch value is no longer needed. | 857 __ Drop(1); // Switch value is no longer needed. |
| 856 __ b(clause->body_target()); | 858 __ b(clause->body_target()); |
| 857 __ bind(&slow_case); | 859 __ bind(&slow_case); |
| 858 } | 860 } |
| 859 | 861 |
| 860 // Record position before stub call for type feedback. | 862 // Record position before stub call for type feedback. |
| 861 SetSourcePosition(clause->position()); | 863 SetSourcePosition(clause->position()); |
| 862 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 864 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
| 863 EmitCallIC(ic, &patch_site, clause->CompareId()); | 865 EmitCallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
|
fschneider
2011/06/29 13:00:39
I'd still prefer statically helping to never forge
Sven Panne
2011/06/29 13:16:43
After some semi-religious offline discussions invo
| |
| 866 patch_site.EmitPatchInfo(); | |
| 864 | 867 |
| 865 __ cmp(r0, Operand(0)); | 868 __ cmp(r0, Operand(0)); |
| 866 __ b(ne, &next_test); | 869 __ b(ne, &next_test); |
| 867 __ Drop(1); // Switch value is no longer needed. | 870 __ Drop(1); // Switch value is no longer needed. |
| 868 __ b(clause->body_target()); | 871 __ b(clause->body_target()); |
| 869 } | 872 } |
| 870 | 873 |
| 871 // Discard the test value and jump to the default if present, otherwise to | 874 // Discard the test value and jump to the default if present, otherwise to |
| 872 // the end of the statement. | 875 // the end of the statement. |
| 873 __ bind(&next_test); | 876 __ bind(&next_test); |
| (...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1682 __ pop(left); | 1685 __ pop(left); |
| 1683 | 1686 |
| 1684 // Perform combined smi check on both operands. | 1687 // Perform combined smi check on both operands. |
| 1685 __ orr(scratch1, left, Operand(right)); | 1688 __ orr(scratch1, left, Operand(right)); |
| 1686 STATIC_ASSERT(kSmiTag == 0); | 1689 STATIC_ASSERT(kSmiTag == 0); |
| 1687 JumpPatchSite patch_site(masm_); | 1690 JumpPatchSite patch_site(masm_); |
| 1688 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1691 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
| 1689 | 1692 |
| 1690 __ bind(&stub_call); | 1693 __ bind(&stub_call); |
| 1691 BinaryOpStub stub(op, mode); | 1694 BinaryOpStub stub(op, mode); |
| 1692 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); | 1695 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
| 1696 patch_site.EmitPatchInfo(); | |
| 1693 __ jmp(&done); | 1697 __ jmp(&done); |
| 1694 | 1698 |
| 1695 __ bind(&smi_case); | 1699 __ bind(&smi_case); |
| 1696 // Smi case. This code works the same way as the smi-smi case in the type | 1700 // Smi case. This code works the same way as the smi-smi case in the type |
| 1697 // recording binary operation stub, see | 1701 // recording binary operation stub, see |
| 1698 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1702 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
| 1699 switch (op) { | 1703 switch (op) { |
| 1700 case Token::SAR: | 1704 case Token::SAR: |
| 1701 __ b(&stub_call); | 1705 __ b(&stub_call); |
| 1702 __ GetLeastBitsFromSmi(scratch1, right, 5); | 1706 __ GetLeastBitsFromSmi(scratch1, right, 5); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1763 __ bind(&done); | 1767 __ bind(&done); |
| 1764 context()->Plug(r0); | 1768 context()->Plug(r0); |
| 1765 } | 1769 } |
| 1766 | 1770 |
| 1767 | 1771 |
| 1768 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1772 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1769 Token::Value op, | 1773 Token::Value op, |
| 1770 OverwriteMode mode) { | 1774 OverwriteMode mode) { |
| 1771 __ pop(r1); | 1775 __ pop(r1); |
| 1772 BinaryOpStub stub(op, mode); | 1776 BinaryOpStub stub(op, mode); |
| 1773 EmitCallIC(stub.GetCode(), NULL, expr->id()); | 1777 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
| 1778 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | |
| 1779 patch_site.EmitPatchInfo(); | |
| 1774 context()->Plug(r0); | 1780 context()->Plug(r0); |
| 1775 } | 1781 } |
| 1776 | 1782 |
| 1777 | 1783 |
| 1778 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1784 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
| 1779 // Invalid left-hand sides are rewritten to have a 'throw | 1785 // Invalid left-hand sides are rewritten to have a 'throw |
| 1780 // ReferenceError' on the left-hand side. | 1786 // ReferenceError' on the left-hand side. |
| 1781 if (!expr->IsValidLeftHandSide()) { | 1787 if (!expr->IsValidLeftHandSide()) { |
| 1782 VisitForEffect(expr); | 1788 VisitForEffect(expr); |
| 1783 return; | 1789 return; |
| (...skipping 2062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3846 __ bind(&stub_call); | 3852 __ bind(&stub_call); |
| 3847 // Call stub. Undo operation first. | 3853 // Call stub. Undo operation first. |
| 3848 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 3854 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
| 3849 } | 3855 } |
| 3850 __ mov(r1, Operand(Smi::FromInt(count_value))); | 3856 __ mov(r1, Operand(Smi::FromInt(count_value))); |
| 3851 | 3857 |
| 3852 // Record position before stub call. | 3858 // Record position before stub call. |
| 3853 SetSourcePosition(expr->position()); | 3859 SetSourcePosition(expr->position()); |
| 3854 | 3860 |
| 3855 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 3861 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
| 3856 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); | 3862 EmitCallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
| 3863 patch_site.EmitPatchInfo(); | |
| 3857 __ bind(&done); | 3864 __ bind(&done); |
| 3858 | 3865 |
| 3859 // Store the value returned in r0. | 3866 // Store the value returned in r0. |
| 3860 switch (assign_type) { | 3867 switch (assign_type) { |
| 3861 case VARIABLE: | 3868 case VARIABLE: |
| 3862 if (expr->is_postfix()) { | 3869 if (expr->is_postfix()) { |
| 3863 { EffectContext context(this); | 3870 { EffectContext context(this); |
| 3864 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3871 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3865 Token::ASSIGN); | 3872 Token::ASSIGN); |
| 3866 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3873 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4119 __ orr(r2, r0, Operand(r1)); | 4126 __ orr(r2, r0, Operand(r1)); |
| 4120 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4127 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
| 4121 __ cmp(r1, r0); | 4128 __ cmp(r1, r0); |
| 4122 Split(cond, if_true, if_false, NULL); | 4129 Split(cond, if_true, if_false, NULL); |
| 4123 __ bind(&slow_case); | 4130 __ bind(&slow_case); |
| 4124 } | 4131 } |
| 4125 | 4132 |
| 4126 // Record position and call the compare IC. | 4133 // Record position and call the compare IC. |
| 4127 SetSourcePosition(expr->position()); | 4134 SetSourcePosition(expr->position()); |
| 4128 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4135 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 4129 EmitCallIC(ic, &patch_site, expr->id()); | 4136 EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
| 4137 patch_site.EmitPatchInfo(); | |
| 4130 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4138 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
| 4131 __ cmp(r0, Operand(0)); | 4139 __ cmp(r0, Operand(0)); |
| 4132 Split(cond, if_true, if_false, fall_through); | 4140 Split(cond, if_true, if_false, fall_through); |
| 4133 } | 4141 } |
| 4134 } | 4142 } |
| 4135 | 4143 |
| 4136 // Convert the result of the comparison into one expected for this | 4144 // Convert the result of the comparison into one expected for this |
| 4137 // expression's context. | 4145 // expression's context. |
| 4138 context()->Plug(if_true, if_false); | 4146 context()->Plug(if_true, if_false); |
| 4139 } | 4147 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4185 Register FullCodeGenerator::context_register() { | 4193 Register FullCodeGenerator::context_register() { |
| 4186 return cp; | 4194 return cp; |
| 4187 } | 4195 } |
| 4188 | 4196 |
| 4189 | 4197 |
| 4190 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4198 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, |
| 4191 RelocInfo::Mode mode, | 4199 RelocInfo::Mode mode, |
| 4192 unsigned ast_id) { | 4200 unsigned ast_id) { |
| 4193 ASSERT(mode == RelocInfo::CODE_TARGET || | 4201 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 4194 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4202 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 4195 Counters* counters = isolate()->counters(); | 4203 if (StatsCounter* counter = ic->Counter(isolate())) { |
|
fschneider
2011/06/29 13:00:39
Do we really need those counters at all? We don't
Sven Panne
2011/06/29 13:16:43
OK, I'll nuke those 4 counters then.
| |
| 4196 switch (ic->kind()) { | 4204 __ IncrementCounter(counter, 1, r1, r2); |
| 4197 case Code::LOAD_IC: | |
| 4198 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | |
| 4199 break; | |
| 4200 case Code::KEYED_LOAD_IC: | |
| 4201 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | |
| 4202 break; | |
| 4203 case Code::STORE_IC: | |
| 4204 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | |
| 4205 break; | |
| 4206 case Code::KEYED_STORE_IC: | |
| 4207 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | |
| 4208 default: | |
| 4209 break; | |
| 4210 } | 4205 } |
| 4211 if (ast_id == kNoASTId || mode == RelocInfo::CODE_TARGET_CONTEXT) { | 4206 if (ast_id == kNoASTId || mode == RelocInfo::CODE_TARGET_CONTEXT) { |
| 4212 __ Call(ic, mode); | 4207 __ Call(ic, mode); |
| 4213 } else { | 4208 } else { |
| 4214 ASSERT(mode == RelocInfo::CODE_TARGET); | 4209 ASSERT(mode == RelocInfo::CODE_TARGET); |
| 4215 mode = RelocInfo::CODE_TARGET_WITH_ID; | 4210 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); |
| 4216 __ CallWithAstId(ic, mode, ast_id); | |
| 4217 } | 4211 } |
| 4218 } | 4212 } |
| 4219 | 4213 |
| 4220 | 4214 |
| 4221 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | |
| 4222 JumpPatchSite* patch_site, | |
| 4223 unsigned ast_id) { | |
| 4224 Counters* counters = isolate()->counters(); | |
| 4225 switch (ic->kind()) { | |
| 4226 case Code::LOAD_IC: | |
| 4227 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | |
| 4228 break; | |
| 4229 case Code::KEYED_LOAD_IC: | |
| 4230 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | |
| 4231 break; | |
| 4232 case Code::STORE_IC: | |
| 4233 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | |
| 4234 break; | |
| 4235 case Code::KEYED_STORE_IC: | |
| 4236 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | |
| 4237 default: | |
| 4238 break; | |
| 4239 } | |
| 4240 | |
| 4241 if (ast_id == kNoASTId) { | |
| 4242 __ Call(ic, RelocInfo::CODE_TARGET); | |
| 4243 } else { | |
| 4244 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); | |
| 4245 } | |
| 4246 if (patch_site != NULL && patch_site->is_bound()) { | |
| 4247 patch_site->EmitPatchInfo(); | |
| 4248 } else { | |
| 4249 __ nop(); // Signals no inlined code. | |
| 4250 } | |
| 4251 } | |
| 4252 | |
| 4253 | |
| 4254 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4215 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 4255 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4216 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 4256 __ str(value, MemOperand(fp, frame_offset)); | 4217 __ str(value, MemOperand(fp, frame_offset)); |
| 4257 } | 4218 } |
| 4258 | 4219 |
| 4259 | 4220 |
| 4260 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4221 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 4261 __ ldr(dst, ContextOperand(cp, context_index)); | 4222 __ ldr(dst, ContextOperand(cp, context_index)); |
| 4262 } | 4223 } |
| 4263 | 4224 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4308 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4269 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 4309 __ add(pc, r1, Operand(masm_->CodeObject())); | 4270 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 4310 } | 4271 } |
| 4311 | 4272 |
| 4312 | 4273 |
| 4313 #undef __ | 4274 #undef __ |
| 4314 | 4275 |
| 4315 } } // namespace v8::internal | 4276 } } // namespace v8::internal |
| 4316 | 4277 |
| 4317 #endif // V8_TARGET_ARCH_ARM | 4278 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |