OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 4022 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4033 Load(args->at(0)); | 4033 Load(args->at(0)); |
4034 Result value = frame_->Pop(); | 4034 Result value = frame_->Pop(); |
4035 value.ToRegister(); | 4035 value.ToRegister(); |
4036 ASSERT(value.is_valid()); | 4036 ASSERT(value.is_valid()); |
4037 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); | 4037 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); |
4038 value.Unuse(); | 4038 value.Unuse(); |
4039 destination()->Split(positive_smi); | 4039 destination()->Split(positive_smi); |
4040 } | 4040 } |
4041 | 4041 |
4042 | 4042 |
4043 // Generates the Math.pow method - currently just calls runtime. | 4043 // Generates the Math.pow method. Only handles special cases and |
| 4044 // branches to the runtime system for everything else. Please note |
| 4045 // that this function assumes that the callsite has executed ToNumber |
| 4046 // on both arguments. |
4044 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | 4047 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
4045 ASSERT(args->length() == 2); | 4048 ASSERT(args->length() == 2); |
4046 Load(args->at(0)); | 4049 Load(args->at(0)); |
4047 Load(args->at(1)); | 4050 Load(args->at(1)); |
4048 Result res = frame_->CallRuntime(Runtime::kMath_pow, 2); | 4051 |
4049 frame_->Push(&res); | 4052 Label allocate_return; |
| 4053 // Load the two operands while leaving the values on the frame. |
| 4054 frame()->Dup(); |
| 4055 Result exponent = frame()->Pop(); |
| 4056 exponent.ToRegister(); |
| 4057 frame()->Spill(exponent.reg()); |
| 4058 frame()->PushElementAt(1); |
| 4059 Result base = frame()->Pop(); |
| 4060 base.ToRegister(); |
| 4061 frame()->Spill(base.reg()); |
| 4062 |
| 4063 Result answer = allocator()->Allocate(); |
| 4064 ASSERT(answer.is_valid()); |
| 4065 ASSERT(!exponent.reg().is(base.reg())); |
| 4066 JumpTarget call_runtime; |
| 4067 |
| 4068 // Save 1 in xmm3 - we need this several times later on. |
| 4069 __ movl(answer.reg(), Immediate(1)); |
| 4070 __ cvtlsi2sd(xmm3, answer.reg()); |
| 4071 |
| 4072 Label exponent_nonsmi; |
| 4073 Label base_nonsmi; |
| 4074 // If the exponent is a heap number go to that specific case. |
| 4075 __ JumpIfNotSmi(exponent.reg(), &exponent_nonsmi); |
| 4076 __ JumpIfNotSmi(base.reg(), &base_nonsmi); |
| 4077 |
| 4078 // Optimized version when y is an integer. |
| 4079 Label powi; |
| 4080 __ SmiToInteger32(base.reg(), base.reg()); |
| 4081 __ cvtlsi2sd(xmm0, base.reg()); |
| 4082 __ jmp(&powi); |
| 4083 // exponent is smi and base is a heapnumber. |
| 4084 __ bind(&base_nonsmi); |
| 4085 __ CompareRoot(FieldOperand(base.reg(), HeapObject::kMapOffset), |
| 4086 Heap::kHeapNumberMapRootIndex); |
| 4087 call_runtime.Branch(not_equal); |
| 4088 |
| 4089 __ movsd(xmm0, FieldOperand(base.reg(), HeapNumber::kValueOffset)); |
| 4090 |
| 4091 // Optimized version of pow if y is an integer. |
| 4092 __ bind(&powi); |
| 4093 __ SmiToInteger32(exponent.reg(), exponent.reg()); |
| 4094 |
| 4095 // Save exponent in base as we need to check if exponent is negative later. |
| 4096 // We know that base and exponent are in different registers. |
| 4097 __ movl(base.reg(), exponent.reg()); |
| 4098 |
| 4099 // Get absolute value of exponent. |
| 4100 Label no_neg; |
| 4101 __ cmpl(exponent.reg(), Immediate(0)); |
| 4102 __ j(greater_equal, &no_neg); |
| 4103 __ negl(exponent.reg()); |
| 4104 __ bind(&no_neg); |
| 4105 |
| 4106 // Load xmm1 with 1. |
| 4107 __ movsd(xmm1, xmm3); |
| 4108 Label while_true; |
| 4109 Label no_multiply; |
| 4110 |
| 4111 __ bind(&while_true); |
| 4112 __ shrl(exponent.reg(), Immediate(1)); |
| 4113 __ j(not_carry, &no_multiply); |
| 4114 __ mulsd(xmm1, xmm0); |
| 4115 __ bind(&no_multiply); |
| 4116 __ testl(exponent.reg(), exponent.reg()); |
| 4117 __ mulsd(xmm0, xmm0); |
| 4118 __ j(not_zero, &while_true); |
| 4119 |
| 4120 // x has the original value of y - if y is negative return 1/result. |
| 4121 __ testl(base.reg(), base.reg()); |
| 4122 __ j(positive, &allocate_return); |
| 4123 // Special case if xmm1 has reached infinity. |
| 4124 __ movl(answer.reg(), Immediate(0x7FB00000)); |
| 4125 __ movd(xmm0, answer.reg()); |
| 4126 __ cvtss2sd(xmm0, xmm0); |
| 4127 __ ucomisd(xmm0, xmm1); |
| 4128 call_runtime.Branch(equal); |
| 4129 __ divsd(xmm3, xmm1); |
| 4130 __ movsd(xmm1, xmm3); |
| 4131 __ jmp(&allocate_return); |
| 4132 |
| 4133 // exponent (or both) is a heapnumber - no matter what we should now work |
| 4134 // on doubles. |
| 4135 __ bind(&exponent_nonsmi); |
| 4136 __ CompareRoot(FieldOperand(exponent.reg(), HeapObject::kMapOffset), |
| 4137 Heap::kHeapNumberMapRootIndex); |
| 4138 call_runtime.Branch(not_equal); |
| 4139 __ movsd(xmm1, FieldOperand(exponent.reg(), HeapNumber::kValueOffset)); |
| 4140 // Test if exponent is nan. |
| 4141 __ ucomisd(xmm1, xmm1); |
| 4142 call_runtime.Branch(parity_even); |
| 4143 |
| 4144 Label base_not_smi; |
| 4145 Label handle_special_cases; |
| 4146 __ testl(base.reg(), Immediate(kSmiTagMask)); |
| 4147 __ j(not_zero, &base_not_smi); |
| 4148 __ SmiToInteger32(base.reg(), base.reg()); |
| 4149 __ cvtlsi2sd(xmm0, base.reg()); |
| 4150 __ jmp(&handle_special_cases); |
| 4151 __ bind(&base_not_smi); |
| 4152 __ CompareRoot(FieldOperand(base.reg(), HeapObject::kMapOffset), |
| 4153 Heap::kHeapNumberMapRootIndex); |
| 4154 call_runtime.Branch(not_equal); |
| 4155 __ movl(answer.reg(), FieldOperand(base.reg(), HeapNumber::kExponentOffset)); |
| 4156 __ andl(answer.reg(), Immediate(HeapNumber::kExponentMask)); |
| 4157 __ cmpl(answer.reg(), Immediate(HeapNumber::kExponentMask)); |
| 4158 // base is NaN or +/-Infinity |
| 4159 call_runtime.Branch(greater_equal); |
| 4160 __ movsd(xmm0, FieldOperand(base.reg(), HeapNumber::kValueOffset)); |
| 4161 |
| 4162 // base is in xmm0 and exponent is in xmm1. |
| 4163 __ bind(&handle_special_cases); |
| 4164 Label not_minus_half; |
| 4165 // Test for -0.5. |
| 4166 // Load xmm2 with -0.5. |
| 4167 __ movl(answer.reg(), Immediate(0xBF000000)); |
| 4168 __ movd(xmm2, answer.reg()); |
| 4169 __ cvtss2sd(xmm2, xmm2); |
| 4170 // xmm2 now has -0.5. |
| 4171 __ ucomisd(xmm2, xmm1); |
| 4172 __ j(not_equal, ¬_minus_half); |
| 4173 |
| 4174 // Calculates reciprocal of square root. |
| 4175 // Note that 1/sqrt(x) = sqrt(1/x)) |
| 4176 __ divsd(xmm3, xmm0); |
| 4177 __ movsd(xmm1, xmm3); |
| 4178 __ sqrtsd(xmm1, xmm1); |
| 4179 __ jmp(&allocate_return); |
| 4180 |
| 4181 // Test for 0.5. |
| 4182 __ bind(¬_minus_half); |
| 4183 // Load xmm2 with 0.5. |
| 4184 // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3. |
| 4185 __ addsd(xmm2, xmm3); |
| 4186 // xmm2 now has 0.5. |
| 4187 __ comisd(xmm2, xmm1); |
| 4188 call_runtime.Branch(not_equal); |
| 4189 |
| 4190 // Calculates square root. |
| 4191 __ movsd(xmm1, xmm0); |
| 4192 __ sqrtsd(xmm1, xmm1); |
| 4193 |
| 4194 JumpTarget done; |
| 4195 Label failure, success; |
| 4196 __ bind(&allocate_return); |
| 4197 // Make a copy of the frame to enable us to handle allocation |
| 4198 // failure after the JumpTarget jump. |
| 4199 VirtualFrame* clone = new VirtualFrame(frame()); |
| 4200 __ AllocateHeapNumber(answer.reg(), exponent.reg(), &failure); |
| 4201 __ movsd(FieldOperand(answer.reg(), HeapNumber::kValueOffset), xmm1); |
| 4202 // Remove the two original values from the frame - we only need those |
| 4203 // in the case where we branch to runtime. |
| 4204 frame()->Drop(2); |
| 4205 exponent.Unuse(); |
| 4206 base.Unuse(); |
| 4207 done.Jump(&answer); |
| 4208 // Use the copy of the original frame as our current frame. |
| 4209 RegisterFile empty_regs; |
| 4210 SetFrame(clone, &empty_regs); |
| 4211 // If we experience an allocation failure we branch to runtime. |
| 4212 __ bind(&failure); |
| 4213 call_runtime.Bind(); |
| 4214 answer = frame()->CallRuntime(Runtime::kMath_pow_cfunction, 2); |
| 4215 |
| 4216 done.Bind(&answer); |
| 4217 frame()->Push(&answer); |
4050 } | 4218 } |
4051 | 4219 |
4052 | 4220 |
4053 // Generates the Math.sqrt method - currently just calls runtime. | 4221 // Generates the Math.sqrt method. Please note - this function assumes that |
| 4222 // the callsite has executed ToNumber on the argument. |
4054 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | 4223 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
4055 ASSERT(args->length() == 1); | 4224 ASSERT(args->length() == 1); |
4056 Load(args->at(0)); | 4225 Load(args->at(0)); |
4057 Result res = frame_->CallRuntime(Runtime::kMath_sqrt, 1); | 4226 |
4058 frame_->Push(&res); | 4227 // Leave original value on the frame if we need to call runtime. |
| 4228 frame()->Dup(); |
| 4229 Result result = frame()->Pop(); |
| 4230 result.ToRegister(); |
| 4231 frame()->Spill(result.reg()); |
| 4232 Label runtime; |
| 4233 Label non_smi; |
| 4234 Label load_done; |
| 4235 JumpTarget end; |
| 4236 |
| 4237 __ JumpIfNotSmi(result.reg(), &non_smi); |
| 4238 __ SmiToInteger32(result.reg(), result.reg()); |
| 4239 __ cvtlsi2sd(xmm0, result.reg()); |
| 4240 __ jmp(&load_done); |
| 4241 __ bind(&non_smi); |
| 4242 __ CompareRoot(FieldOperand(result.reg(), HeapObject::kMapOffset), |
| 4243 Heap::kHeapNumberMapRootIndex); |
| 4244 __ j(not_equal, &runtime); |
| 4245 __ movsd(xmm0, FieldOperand(result.reg(), HeapNumber::kValueOffset)); |
| 4246 |
| 4247 __ bind(&load_done); |
| 4248 __ sqrtsd(xmm0, xmm0); |
| 4249 // A copy of the virtual frame to allow us to go to runtime after the |
| 4250 // JumpTarget jump. |
| 4251 Result scratch = allocator()->Allocate(); |
| 4252 VirtualFrame* clone = new VirtualFrame(frame()); |
| 4253 __ AllocateHeapNumber(result.reg(), scratch.reg(), &runtime); |
| 4254 |
| 4255 __ movsd(FieldOperand(result.reg(), HeapNumber::kValueOffset), xmm0); |
| 4256 frame()->Drop(1); |
| 4257 scratch.Unuse(); |
| 4258 end.Jump(&result); |
| 4259 // We only branch to runtime if we have an allocation error. |
| 4260 // Use the copy of the original frame as our current frame. |
| 4261 RegisterFile empty_regs; |
| 4262 SetFrame(clone, &empty_regs); |
| 4263 __ bind(&runtime); |
| 4264 result = frame()->CallRuntime(Runtime::kMath_sqrt, 1); |
| 4265 |
| 4266 end.Bind(&result); |
| 4267 frame()->Push(&result); |
4059 } | 4268 } |
4060 | 4269 |
4061 | 4270 |
4062 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 4271 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
4063 ASSERT(args->length() == 1); | 4272 ASSERT(args->length() == 1); |
4064 Load(args->at(0)); | 4273 Load(args->at(0)); |
4065 Result value = frame_->Pop(); | 4274 Result value = frame_->Pop(); |
4066 value.ToRegister(); | 4275 value.ToRegister(); |
4067 ASSERT(value.is_valid()); | 4276 ASSERT(value.is_valid()); |
4068 Condition is_smi = masm_->CheckSmi(value.reg()); | 4277 Condition is_smi = masm_->CheckSmi(value.reg()); |
(...skipping 6410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10479 // Call the function from C++. | 10688 // Call the function from C++. |
10480 return FUNCTION_CAST<ModuloFunction>(buffer); | 10689 return FUNCTION_CAST<ModuloFunction>(buffer); |
10481 } | 10690 } |
10482 | 10691 |
10483 #endif | 10692 #endif |
10484 | 10693 |
10485 | 10694 |
10486 #undef __ | 10695 #undef __ |
10487 | 10696 |
10488 } } // namespace v8::internal | 10697 } } // namespace v8::internal |
OLD | NEW |