Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 1774010: Port inline version of Math.sqrt and Math.pow from ia32 to x64. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/disasm-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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, &not_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(&not_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
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
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/disasm-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698