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

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

Issue 660072: Added fast support for Math.pow. This simply calculates the result using the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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/ia32/codegen-ia32.h ('k') | src/math.js » ('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 5259 matching lines...) Expand 10 before | Expand all | Expand 10 after
5270 Load(args->at(0)); 5270 Load(args->at(0));
5271 Result value = frame_->Pop(); 5271 Result value = frame_->Pop();
5272 value.ToRegister(); 5272 value.ToRegister();
5273 ASSERT(value.is_valid()); 5273 ASSERT(value.is_valid());
5274 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000)); 5274 __ test(value.reg(), Immediate(kSmiTagMask | 0x80000000));
5275 value.Unuse(); 5275 value.Unuse();
5276 destination()->Split(zero); 5276 destination()->Split(zero);
5277 } 5277 }
5278 5278
5279 5279
5280 // Generates the Math.pow method - only handles special cases and branches to
5281 // the runtime system if not. Uses eax to store result and as temporary reg.
5282 void CodeGenerator::GeneratePow(ZoneList<Expression*>* args) {
5283 ASSERT(args->length() == 2);
5284 if (CpuFeatures::IsSupported(SSE2)) {
5285 CpuFeatures::Scope use_sse2(SSE2);
5286 Load(args->at(0));
5287 Load(args->at(1));
5288 Label go_runtime;
5289 Label return_preg;
5290 Result p = allocator()->Allocate(eax);
5291 Result y = frame_->Pop();
5292 Result x= frame_->Pop();
5293 if (p.is_valid() && p.reg().is(eax)) {
5294 x.ToRegister();
5295 y.ToRegister();
5296 frame_->Spill(x.reg());
5297 frame_->Spill(y.reg());
5298 ASSERT(x.is_valid());
5299 ASSERT(y.is_valid());
5300
5301 Label y_nonsmi;
5302 Label x_is_double;
5303 // If y is a heap number go to that specific case.
5304 __ test(y.reg(), Immediate(kSmiTagMask));
5305 __ j(not_zero, &y_nonsmi);
5306 __ test(x.reg(), Immediate(kSmiTagMask));
5307 __ j(not_zero, &x_is_double);
5308
5309 // Bot numbers are smis.
5310 Label powi;
5311 __ SmiUntag(x.reg());
5312 __ cvtsi2sd(xmm0, Operand(x.reg()));
5313 __ jmp(&powi);
5314 // Y is smi and x is a double.
5315 __ bind(&x_is_double);
5316 __ cmp(FieldOperand(x.reg(), HeapObject::kMapOffset),
5317 Factory::heap_number_map());
5318 __ j(not_equal, &go_runtime);
5319 __ movdbl(xmm0, FieldOperand(x.reg(), HeapNumber::kValueOffset));
5320
5321 __ bind(&powi);
5322 __ SmiUntag(y.reg());
5323
5324 // Save y in x as we need to check if y is negative later.
5325 __ mov(x.reg(), y.reg());
5326 // Save 1 in xmm3 - we need this several times later on
5327 __ mov(p.reg(), Immediate(1));
5328 __ cvtsi2sd(xmm3, Operand(p.reg()));
5329
5330 // Get absolute value of y.
5331 Label no_neg;
5332 __ cmp(y.reg(), 0);
5333 __ j(greater_equal, &no_neg);
5334 __ neg(y.reg());
5335 __ bind(&no_neg);
5336
5337 // Optimized version of pow if y is an integer.
5338 // Load xmm1 with 1.
5339 __ movsd(xmm1, xmm3);
5340 Label while_true;
5341 Label no_multiply;
5342 Label powi_done;
5343 Label allocate_and_return;
5344 __ bind(&while_true);
5345 __ test(y.reg(), Immediate(1));
Lasse Reichstein 2010/02/26 09:06:20 If you shr(y.reg(),1) here, then the bit that was
Rico 2010/03/04 06:39:29 Done.
5346 __ j(zero, &no_multiply);
5347 __ mulsd(xmm1, xmm0);
5348 __ bind(&no_multiply);
5349 __ shr(y.reg(), 1);
5350 __ test(y.reg(), Operand(y.reg()));
5351 __ j(zero, &powi_done);
Lasse Reichstein 2010/02/26 09:06:20 Just do: mulsd(xmm0, xmm0); j(not_zero, &while_t
Rico 2010/03/04 06:39:29 Done.
5352 __ mulsd(xmm0, xmm0);
5353 __ jmp(&while_true);
5354
5355 __ bind(&powi_done);
5356 // x has the original value of y - if y is negative return 1/result.
5357 __ test(x.reg(), Operand(x.reg()));
5358 __ j(positive, &allocate_and_return);
5359 // Special case if xmm1 has reached infinity
5360 __ mov(p.reg(), Immediate(0x7FF00000));
Lasse Reichstein 2010/02/26 09:06:20 I don't think this is single-precission infinity.
Rico 2010/03/04 06:39:29 As discussed offline this will always branch to ru
5361 __ movd(xmm0, Operand(p.reg()));
5362 __ cvtss2sd(xmm0, xmm0);
5363 __ comisd(xmm0, xmm1);
Lasse Reichstein 2010/02/26 09:06:20 Use ucomisd instead of comisd.
Rico 2010/03/04 06:39:29 Done - added ucomisd to assembler-ia32
5364 __ j(equal, &go_runtime);
5365 __ divsd(xmm3, xmm1);
5366 __ movsd(xmm1, xmm3);
5367 __ jmp(&allocate_and_return);
5368
5369 // y (or both) is a double - no matter what we should now work
5370 // on doubles.
5371 __ bind(&y_nonsmi);
5372 __ cmp(FieldOperand(y.reg(), HeapObject::kMapOffset),
5373 Factory::heap_number_map());
5374 __ j(not_equal, &go_runtime);
5375 // Test if y is nan.
5376 __ comisd(xmm1, xmm1);
Lasse Reichstein 2010/02/26 09:06:20 ucomisd
Rico 2010/03/04 06:39:29 Done.
5377 __ j(parity_even, &go_runtime);
5378
5379 // Y must be a double.
5380 __ movdbl(xmm1, FieldOperand(y.reg(), HeapNumber::kValueOffset));
5381
5382 Label x_not_smi;
5383 Label handle_special_cases;
5384 __ test(x.reg(), Immediate(kSmiTagMask));
5385 __ j(not_zero, &x_not_smi);
5386 __ SmiUntag(x.reg());
5387 __ cvtsi2sd(xmm0, Operand(x.reg()));
5388 __ jmp(&handle_special_cases);
5389 __ bind(&x_not_smi);
5390 __ cmp(FieldOperand(x.reg(), HeapObject::kMapOffset),
5391 Factory::heap_number_map());
5392 __ j(not_equal, &go_runtime);
5393 __ mov(p.reg(), FieldOperand(x.reg(), HeapNumber::kExponentOffset));
5394 __ and_(p.reg(), HeapNumber::kExponentMask);
5395 __ cmp(Operand(p.reg()), Immediate(HeapNumber::kExponentMask));
Lasse Reichstein 2010/02/26 09:06:20 Add comment here saying something like "p is NaN o
Rico 2010/03/04 06:39:29 Done.
5396 __ j(greater_equal, &go_runtime);
5397 __ movdbl(xmm0, FieldOperand(x.reg(), HeapNumber::kValueOffset));
5398
5399 // x is in xmm0 and y is in xmm1.
5400 __ bind(&handle_special_cases);
5401
5402 Label not_minus_half;
5403 // Test for -0.5.
5404 // Load xmm2 with -0.5.
5405 __ mov(p.reg(), Immediate(0xBF000000));
5406 __ movd(xmm2, Operand(p.reg()));
5407 __ cvtss2sd(xmm2, xmm2);
5408 // xmm2 now has -0.5.
5409 __ comisd(xmm2, xmm1);
Lasse Reichstein 2010/02/26 09:06:20 ucomisd
Rico 2010/03/04 06:39:29 Done.
5410 __ j(not_equal, &not_minus_half);
5411
5412 // Calculates reciprocal of square root.
5413 __ sqrt(xmm0, xmm0);
Lasse Reichstein 2010/02/26 09:06:20 Why isn't sqrt called sqrtsd?
Rico 2010/03/04 06:39:29 Changed name and moved down to sse2 instructions.
5414 __ divsd(xmm3, xmm0);
5415 __ movsd(xmm1, xmm3);
Lasse Reichstein 2010/02/26 09:06:20 Move sqrt to the end (i.e., sqrt(xmm1,xmm1)) since
Rico 2010/03/04 06:39:29 Done.
5416 __ jmp(&allocate_and_return);
5417
5418 // Test for 0.5.
5419 __ bind(&not_minus_half);
5420 // Load xmm2 with 0.5.
5421 __ mov(p.reg(), Immediate(0x3F000000));
Lasse Reichstein 2010/02/26 09:06:20 You have -0.5 in xmm2 already, and 1.0 in xmm3, so
Rico 2010/03/04 06:39:29 Done.
5422 __ movd(xmm2, Operand(p.reg()));
5423 __ cvtss2sd(xmm2, xmm2);
5424 // xmm2 now has 0.5.
5425 __ comisd(xmm2, xmm1);
Lasse Reichstein 2010/02/26 09:06:20 ucomisd
Rico 2010/03/04 06:39:29 Done.
5426 __ j(not_equal, &go_runtime);
5427 // Calculates square root.
5428 __ sqrt(xmm0, xmm0);
Lasse Reichstein 2010/02/26 09:06:20 do movsd(xmm1, xmm0); sqrt(xmm1, xmm1); instead
Rico 2010/03/04 06:39:29 Done.
5429 __ movsd(xmm1, xmm0);
5430
5431
5432 __ bind(&allocate_and_return);
5433 __ AllocateHeapNumber(p.reg(), y.reg(), x.reg(), &go_runtime);
5434 __ movdbl(FieldOperand(p.reg(), HeapNumber::kValueOffset), xmm1);
5435 __ jmp(&return_preg);
5436 }
5437 __ bind(&go_runtime);
5438 x.Unuse();
5439 y.Unuse();
5440 p.Unuse();
5441 Load(args->at(0));
5442 Load(args->at(1));
5443 frame_->CallRuntime(Runtime::kMath_pow_cfunction, 2);
5444
5445 // Since we store the result in p.reg() which is eax - return this value.
5446 // If we called runtime the result is also in eax.
5447 __ bind(&return_preg);
5448 frame_->Push(eax);
5449 } else { // Simply call runtime.
5450 Load(args->at(0));
5451 Load(args->at(1));
5452 Result res = frame_->CallRuntime(Runtime::kMath_pow, 2);
5453 frame_->Push(&res);
5454 }
5455 }
5456
5457
5280 // This generates code that performs a charCodeAt() call or returns 5458 // This generates code that performs a charCodeAt() call or returns
5281 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 5459 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
5282 // It can handle flat, 8 and 16 bit characters and cons strings where the 5460 // It can handle flat, 8 and 16 bit characters and cons strings where the
5283 // answer is found in the left hand branch of the cons. The slow case will 5461 // answer is found in the left hand branch of the cons. The slow case will
5284 // flatten the string, which will ensure that the answer is in the left hand 5462 // flatten the string, which will ensure that the answer is in the left hand
5285 // side the next time around. 5463 // side the next time around.
5286 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 5464 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
5287 Comment(masm_, "[ GenerateFastCharCodeAt"); 5465 Comment(masm_, "[ GenerateFastCharCodeAt");
5288 ASSERT(args->length() == 2); 5466 ASSERT(args->length() == 2);
5289 5467
(...skipping 5725 matching lines...) Expand 10 before | Expand all | Expand 10 after
11015 11193
11016 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 11194 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
11017 // tagged as a small integer. 11195 // tagged as a small integer.
11018 __ bind(&runtime); 11196 __ bind(&runtime);
11019 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 11197 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
11020 } 11198 }
11021 11199
11022 #undef __ 11200 #undef __
11023 11201
11024 } } // namespace v8::internal 11202 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/math.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698