Chromium Code Reviews| 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 5259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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, ¬_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(¬_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 Loading... | |
| 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 |
| OLD | NEW |