OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 if (!final_result_reg.is(result_reg)) { | 772 if (!final_result_reg.is(result_reg)) { |
773 ASSERT(final_result_reg.is(ecx)); | 773 ASSERT(final_result_reg.is(ecx)); |
774 __ mov(final_result_reg, result_reg); | 774 __ mov(final_result_reg, result_reg); |
775 } | 775 } |
776 __ pop(save_reg); | 776 __ pop(save_reg); |
777 __ pop(scratch1); | 777 __ pop(scratch1); |
778 __ ret(0); | 778 __ ret(0); |
779 } | 779 } |
780 | 780 |
781 | 781 |
782 // Uses SSE2 to convert the heap number in |source| to an integer. Jumps to | |
783 // |conversion_failure| if the heap number did not contain an int32 value. | |
784 // Result is in ecx. Trashes ebx, xmm0, and xmm1. | |
785 static void ConvertHeapNumberToInt32(MacroAssembler* masm, | |
786 Register source, | |
787 Label* conversion_failure) { | |
788 __ movdbl(xmm0, FieldOperand(source, HeapNumber::kValueOffset)); | |
789 FloatingPointHelper::CheckSSE2OperandIsInt32( | |
790 masm, conversion_failure, xmm0, ecx, ebx, xmm1); | |
791 } | |
792 | |
793 | |
794 void BinaryOpStub::Initialize() { | 782 void BinaryOpStub::Initialize() { |
795 platform_specific_bit_ = CpuFeatures::IsSupported(SSE3); | 783 platform_specific_bit_ = CpuFeatures::IsSupported(SSE3); |
796 } | 784 } |
797 | 785 |
798 | 786 |
799 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | 787 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { |
800 __ pop(ecx); // Save return address. | 788 __ pop(ecx); // Save return address. |
801 __ push(edx); | 789 __ push(edx); |
802 __ push(eax); | 790 __ push(eax); |
803 // Left and right arguments are now on top. | 791 // Left and right arguments are now on top. |
(...skipping 1580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2384 __ cmp(edx, factory->undefined_value()); | 2372 __ cmp(edx, factory->undefined_value()); |
2385 __ j(not_equal, conversion_failure); | 2373 __ j(not_equal, conversion_failure); |
2386 __ mov(edx, Immediate(0)); | 2374 __ mov(edx, Immediate(0)); |
2387 __ jmp(&load_arg2); | 2375 __ jmp(&load_arg2); |
2388 | 2376 |
2389 __ bind(&arg1_is_object); | 2377 __ bind(&arg1_is_object); |
2390 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2378 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
2391 __ cmp(ebx, factory->heap_number_map()); | 2379 __ cmp(ebx, factory->heap_number_map()); |
2392 __ j(not_equal, &check_undefined_arg1); | 2380 __ j(not_equal, &check_undefined_arg1); |
2393 | 2381 |
2394 // Get the untagged integer version of the edx heap number in ecx. | 2382 __ TruncateHeapNumberToI(edx, edx); |
2395 if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | |
2396 CpuFeatureScope use_sse2(masm, SSE2); | |
2397 ConvertHeapNumberToInt32(masm, edx, conversion_failure); | |
2398 } else { | |
2399 DoubleToIStub stub(edx, ecx, HeapNumber::kValueOffset - kHeapObjectTag, | |
2400 true); | |
2401 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
2402 } | |
2403 __ mov(edx, ecx); | |
2404 | 2383 |
2405 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2384 // Here edx has the untagged integer, eax has a Smi or a heap number. |
2406 __ bind(&load_arg2); | 2385 __ bind(&load_arg2); |
2407 | 2386 |
2408 // Test if arg2 is a Smi. | 2387 // Test if arg2 is a Smi. |
2409 if (right_type == BinaryOpIC::SMI) { | 2388 if (right_type == BinaryOpIC::SMI) { |
2410 __ JumpIfNotSmi(eax, conversion_failure); | 2389 __ JumpIfNotSmi(eax, conversion_failure); |
2411 } else { | 2390 } else { |
2412 __ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); | 2391 __ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); |
2413 } | 2392 } |
2414 | 2393 |
2415 __ SmiUntag(eax); | 2394 __ SmiUntag(eax); |
2416 __ mov(ecx, eax); | 2395 __ mov(ecx, eax); |
2417 __ jmp(&done); | 2396 __ jmp(&done); |
2418 | 2397 |
2419 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2398 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
2420 __ bind(&check_undefined_arg2); | 2399 __ bind(&check_undefined_arg2); |
2421 __ cmp(eax, factory->undefined_value()); | 2400 __ cmp(eax, factory->undefined_value()); |
2422 __ j(not_equal, conversion_failure); | 2401 __ j(not_equal, conversion_failure); |
2423 __ mov(ecx, Immediate(0)); | 2402 __ mov(ecx, Immediate(0)); |
2424 __ jmp(&done); | 2403 __ jmp(&done); |
2425 | 2404 |
2426 __ bind(&arg2_is_object); | 2405 __ bind(&arg2_is_object); |
2427 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2406 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2428 __ cmp(ebx, factory->heap_number_map()); | 2407 __ cmp(ebx, factory->heap_number_map()); |
2429 __ j(not_equal, &check_undefined_arg2); | 2408 __ j(not_equal, &check_undefined_arg2); |
2430 // Get the untagged integer version of the eax heap number in ecx. | 2409 // Get the untagged integer version of the eax heap number in ecx. |
2431 | 2410 |
2432 if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) { | 2411 __ TruncateHeapNumberToI(ecx, eax); |
2433 CpuFeatureScope use_sse2(masm, SSE2); | |
2434 ConvertHeapNumberToInt32(masm, eax, conversion_failure); | |
2435 } else { | |
2436 DoubleToIStub stub(eax, ecx, HeapNumber::kValueOffset - kHeapObjectTag, | |
2437 true); | |
2438 __ call(stub.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
2439 } | |
2440 | 2412 |
2441 __ bind(&done); | 2413 __ bind(&done); |
2442 __ mov(eax, edx); | 2414 __ mov(eax, edx); |
2443 } | 2415 } |
2444 | 2416 |
2445 | 2417 |
2446 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2418 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
2447 Register number) { | 2419 Register number) { |
2448 Label load_smi, done; | 2420 Label load_smi, done; |
2449 | 2421 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2683 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 2655 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
2684 __ SmiUntag(exponent); | 2656 __ SmiUntag(exponent); |
2685 __ jmp(&int_exponent); | 2657 __ jmp(&int_exponent); |
2686 | 2658 |
2687 __ bind(&exponent_not_smi); | 2659 __ bind(&exponent_not_smi); |
2688 __ movdbl(double_exponent, | 2660 __ movdbl(double_exponent, |
2689 FieldOperand(exponent, HeapNumber::kValueOffset)); | 2661 FieldOperand(exponent, HeapNumber::kValueOffset)); |
2690 } | 2662 } |
2691 | 2663 |
2692 if (exponent_type_ != INTEGER) { | 2664 if (exponent_type_ != INTEGER) { |
2693 Label fast_power; | 2665 Label fast_power, try_arithmetic_simplification; |
2694 // Detect integer exponents stored as double. | 2666 __ DoubleToI(exponent, double_exponent, double_scratch, |
| 2667 TREAT_MINUS_ZERO_AS_ZERO, &try_arithmetic_simplification); |
| 2668 __ jmp(&int_exponent); |
| 2669 |
| 2670 __ bind(&try_arithmetic_simplification); |
| 2671 // Skip to runtime if possibly NaN (indicated by the indefinite integer). |
2695 __ cvttsd2si(exponent, Operand(double_exponent)); | 2672 __ cvttsd2si(exponent, Operand(double_exponent)); |
2696 // Skip to runtime if possibly NaN (indicated by the indefinite integer). | |
2697 __ cmp(exponent, Immediate(0x80000000u)); | 2673 __ cmp(exponent, Immediate(0x80000000u)); |
2698 __ j(equal, &call_runtime); | 2674 __ j(equal, &call_runtime); |
2699 __ cvtsi2sd(double_scratch, exponent); | |
2700 // Already ruled out NaNs for exponent. | |
2701 __ ucomisd(double_exponent, double_scratch); | |
2702 __ j(equal, &int_exponent); | |
2703 | 2675 |
2704 if (exponent_type_ == ON_STACK) { | 2676 if (exponent_type_ == ON_STACK) { |
2705 // Detect square root case. Crankshaft detects constant +/-0.5 at | 2677 // Detect square root case. Crankshaft detects constant +/-0.5 at |
2706 // compile time and uses DoMathPowHalf instead. We then skip this check | 2678 // compile time and uses DoMathPowHalf instead. We then skip this check |
2707 // for non-constant cases of +/-0.5 as these hardly occur. | 2679 // for non-constant cases of +/-0.5 as these hardly occur. |
2708 Label continue_sqrt, continue_rsqrt, not_plus_half; | 2680 Label continue_sqrt, continue_rsqrt, not_plus_half; |
2709 // Test for 0.5. | 2681 // Test for 0.5. |
2710 // Load double_scratch with 0.5. | 2682 // Load double_scratch with 0.5. |
2711 __ mov(scratch, Immediate(0x3F000000u)); | 2683 __ mov(scratch, Immediate(0x3F000000u)); |
2712 __ movd(double_scratch, scratch); | 2684 __ movd(double_scratch, scratch); |
(...skipping 5001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7714 __ bind(&fast_elements_case); | 7686 __ bind(&fast_elements_case); |
7715 GenerateCase(masm, FAST_ELEMENTS); | 7687 GenerateCase(masm, FAST_ELEMENTS); |
7716 } | 7688 } |
7717 | 7689 |
7718 | 7690 |
7719 #undef __ | 7691 #undef __ |
7720 | 7692 |
7721 } } // namespace v8::internal | 7693 } } // namespace v8::internal |
7722 | 7694 |
7723 #endif // V8_TARGET_ARCH_IA32 | 7695 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |