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

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

Issue 1279001: Revert "Inline floating point compare" (Closed)
Patch Set: Created 10 years, 9 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
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/jump-target.h » ('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 893 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 enum ArgLocation { 904 enum ArgLocation {
905 ARGS_ON_STACK, 905 ARGS_ON_STACK,
906 ARGS_IN_REGISTERS 906 ARGS_IN_REGISTERS
907 }; 907 };
908 908
909 // Code pattern for loading a floating point value. Input value must 909 // Code pattern for loading a floating point value. Input value must
910 // be either a smi or a heap number object (fp value). Requirements: 910 // be either a smi or a heap number object (fp value). Requirements:
911 // operand in register number. Returns operand as floating point number 911 // operand in register number. Returns operand as floating point number
912 // on FPU stack. 912 // on FPU stack.
913 static void LoadFloatOperand(MacroAssembler* masm, Register number); 913 static void LoadFloatOperand(MacroAssembler* masm, Register number);
914
915 // Code pattern for loading floating point values. Input values must 914 // Code pattern for loading floating point values. Input values must
916 // be either smi or heap number objects (fp values). Requirements: 915 // be either smi or heap number objects (fp values). Requirements:
917 // operand_1 on TOS+1 or in edx, operand_2 on TOS+2 or in eax. 916 // operand_1 on TOS+1 or in edx, operand_2 on TOS+2 or in eax.
918 // Returns operands as floating point numbers on FPU stack. 917 // Returns operands as floating point numbers on FPU stack.
919 static void LoadFloatOperands(MacroAssembler* masm, 918 static void LoadFloatOperands(MacroAssembler* masm,
920 Register scratch, 919 Register scratch,
921 ArgLocation arg_location = ARGS_ON_STACK); 920 ArgLocation arg_location = ARGS_ON_STACK);
922 921
923 // Similar to LoadFloatOperand but assumes that both operands are smis. 922 // Similar to LoadFloatOperand but assumes that both operands are smis.
924 // Expects operands in edx, eax. 923 // Expects operands in edx, eax.
925 static void LoadFloatSmis(MacroAssembler* masm, Register scratch); 924 static void LoadFloatSmis(MacroAssembler* masm, Register scratch);
926 925
927 // Test if operands are smi or number objects (fp). Requirements: 926 // Test if operands are smi or number objects (fp). Requirements:
928 // operand_1 in eax, operand_2 in edx; falls through on float 927 // operand_1 in eax, operand_2 in edx; falls through on float
929 // operands, jumps to the non_float label otherwise. 928 // operands, jumps to the non_float label otherwise.
930 static void CheckFloatOperands(MacroAssembler* masm, 929 static void CheckFloatOperands(MacroAssembler* masm,
931 Label* non_float, 930 Label* non_float,
932 Register scratch); 931 Register scratch);
933
934 // Takes the operands in edx and eax and loads them as integers in eax 932 // Takes the operands in edx and eax and loads them as integers in eax
935 // and ecx. 933 // and ecx.
936 static void LoadAsIntegers(MacroAssembler* masm, 934 static void LoadAsIntegers(MacroAssembler* masm,
937 NumberInfo number_info, 935 NumberInfo number_info,
938 bool use_sse3, 936 bool use_sse3,
939 Label* operand_conversion_failure); 937 Label* operand_conversion_failure);
940 static void LoadNumbersAsIntegers(MacroAssembler* masm, 938 static void LoadNumbersAsIntegers(MacroAssembler* masm,
941 NumberInfo number_info, 939 NumberInfo number_info,
942 bool use_sse3, 940 bool use_sse3,
943 Label* operand_conversion_failure); 941 Label* operand_conversion_failure);
944 static void LoadUnknownsAsIntegers(MacroAssembler* masm, 942 static void LoadUnknownsAsIntegers(MacroAssembler* masm,
945 bool use_sse3, 943 bool use_sse3,
946 Label* operand_conversion_failure); 944 Label* operand_conversion_failure);
947 945
948 // Test if operands are smis or heap numbers and load them 946 // Test if operands are smis or heap numbers and load them
949 // into xmm0 and xmm1 if they are. Operands are in edx and eax. 947 // into xmm0 and xmm1 if they are. Operands are in edx and eax.
950 // Leaves operands unchanged. 948 // Leaves operands unchanged.
951 static void LoadSSE2Operands(MacroAssembler* masm); 949 static void LoadSSE2Operands(MacroAssembler* masm);
952
953 // Test if operands are numbers (smi or HeapNumber objects), and load 950 // Test if operands are numbers (smi or HeapNumber objects), and load
954 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if 951 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
955 // either operand is not a number. Operands are in edx and eax. 952 // either operand is not a number. Operands are in edx and eax.
956 // Leaves operands unchanged. 953 // Leaves operands unchanged.
957 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); 954 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers);
958 955
959 // Similar to LoadSSE2Operands but assumes that both operands are smis. 956 // Similar to LoadSSE2Operands but assumes that both operands are smis.
960 // Expects operands in edx, eax. 957 // Expects operands in edx, eax.
961 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); 958 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch);
962 }; 959 };
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after
2357 2354
2358 static bool CouldBeNaN(const Result& result) { 2355 static bool CouldBeNaN(const Result& result) {
2359 if (result.number_info().IsSmi()) return false; 2356 if (result.number_info().IsSmi()) return false;
2360 if (result.number_info().IsInteger32()) return false; 2357 if (result.number_info().IsInteger32()) return false;
2361 if (!result.is_constant()) return true; 2358 if (!result.is_constant()) return true;
2362 if (!result.handle()->IsHeapNumber()) return false; 2359 if (!result.handle()->IsHeapNumber()) return false;
2363 return isnan(HeapNumber::cast(*result.handle())->value()); 2360 return isnan(HeapNumber::cast(*result.handle())->value());
2364 } 2361 }
2365 2362
2366 2363
2367 // Convert from signed to unsigned comparison to match the way EFLAGS are set
2368 // by FPU and XMM compare instructions.
2369 static Condition DoubleCondition(Condition cc) {
2370 switch (cc) {
2371 case less: return below;
2372 case equal: return equal;
2373 case less_equal: return below_equal;
2374 case greater: return above;
2375 case greater_equal: return above_equal;
2376 default: UNREACHABLE();
2377 }
2378 UNREACHABLE();
2379 return equal;
2380 }
2381
2382
2383 void CodeGenerator::Comparison(AstNode* node, 2364 void CodeGenerator::Comparison(AstNode* node,
2384 Condition cc, 2365 Condition cc,
2385 bool strict, 2366 bool strict,
2386 ControlDestination* dest) { 2367 ControlDestination* dest) {
2387 // Strict only makes sense for equality comparisons. 2368 // Strict only makes sense for equality comparisons.
2388 ASSERT(!strict || cc == equal); 2369 ASSERT(!strict || cc == equal);
2389 2370
2390 Result left_side; 2371 Result left_side;
2391 Result right_side; 2372 Result right_side;
2392 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 2373 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 } 2424 }
2444 } else { 2425 } else {
2445 // Only one side is a constant Smi. 2426 // Only one side is a constant Smi.
2446 // If left side is a constant Smi, reverse the operands. 2427 // If left side is a constant Smi, reverse the operands.
2447 // Since one side is a constant Smi, conversion order does not matter. 2428 // Since one side is a constant Smi, conversion order does not matter.
2448 if (left_side_constant_smi) { 2429 if (left_side_constant_smi) {
2449 Result temp = left_side; 2430 Result temp = left_side;
2450 left_side = right_side; 2431 left_side = right_side;
2451 right_side = temp; 2432 right_side = temp;
2452 cc = ReverseCondition(cc); 2433 cc = ReverseCondition(cc);
2453 // This may re-introduce greater or less_equal as the value of cc. 2434 // This may reintroduce greater or less_equal as the value of cc.
2454 // CompareStub and the inline code both support all values of cc. 2435 // CompareStub and the inline code both support all values of cc.
2455 } 2436 }
2456 // Implement comparison against a constant Smi, inlining the case 2437 // Implement comparison against a constant Smi, inlining the case
2457 // where both sides are Smis. 2438 // where both sides are Smis.
2458 left_side.ToRegister(); 2439 left_side.ToRegister();
2459 Register left_reg = left_side.reg(); 2440 Register left_reg = left_side.reg();
2460 Handle<Object> right_val = right_side.handle(); 2441 Handle<Object> right_val = right_side.handle();
2461 2442
2462 // Here we split control flow to the stub call and inlined cases 2443 // Here we split control flow to the stub call and inlined cases
2463 // before finally splitting it to the control destination. We use 2444 // before finally splitting it to the control destination. We use
(...skipping 28 matching lines...) Expand all
2492 } else { 2473 } else {
2493 Result temp = allocator()->Allocate(); 2474 Result temp = allocator()->Allocate();
2494 __ mov(temp.reg(), Immediate(value)); 2475 __ mov(temp.reg(), Immediate(value));
2495 __ cvtsi2sd(xmm0, Operand(temp.reg())); 2476 __ cvtsi2sd(xmm0, Operand(temp.reg()));
2496 temp.Unuse(); 2477 temp.Unuse();
2497 } 2478 }
2498 __ comisd(xmm1, xmm0); 2479 __ comisd(xmm1, xmm0);
2499 // Jump to builtin for NaN. 2480 // Jump to builtin for NaN.
2500 not_number.Branch(parity_even, &left_side); 2481 not_number.Branch(parity_even, &left_side);
2501 left_side.Unuse(); 2482 left_side.Unuse();
2502 dest->true_target()->Branch(DoubleCondition(cc)); 2483 Condition double_cc = cc;
2484 switch (cc) {
2485 case less: double_cc = below; break;
2486 case equal: double_cc = equal; break;
2487 case less_equal: double_cc = below_equal; break;
2488 case greater: double_cc = above; break;
2489 case greater_equal: double_cc = above_equal; break;
2490 default: UNREACHABLE();
2491 }
2492 dest->true_target()->Branch(double_cc);
2503 dest->false_target()->Jump(); 2493 dest->false_target()->Jump();
2504 not_number.Bind(&left_side); 2494 not_number.Bind(&left_side);
2505 } 2495 }
2506 2496
2507 // Setup and call the compare stub. 2497 // Setup and call the compare stub.
2508 CompareStub stub(cc, strict, kCantBothBeNaN); 2498 CompareStub stub(cc, strict, kCantBothBeNaN);
2509 Result result = frame_->CallStub(&stub, &left_side, &right_side); 2499 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2510 result.ToRegister(); 2500 result.ToRegister();
2511 __ cmp(result.reg(), 0); 2501 __ cmp(result.reg(), 0);
2512 result.Unuse(); 2502 result.Unuse();
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2691 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2681 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2692 Immediate(1)); 2682 Immediate(1));
2693 __ bind(&characters_were_different); 2683 __ bind(&characters_were_different);
2694 } 2684 }
2695 temp2.Unuse(); 2685 temp2.Unuse();
2696 left_side.Unuse(); 2686 left_side.Unuse();
2697 right_side.Unuse(); 2687 right_side.Unuse();
2698 dest->Split(cc); 2688 dest->Split(cc);
2699 } 2689 }
2700 } else { 2690 } else {
2701 // Neither side is a constant Smi, constant 1-char string or constant null. 2691 // Neither side is a constant Smi or null.
2702 // If either side is a non-smi constant, or known to be a heap number skip 2692 // If either side is a non-smi constant, skip the smi check.
2703 // the smi check.
2704 bool known_non_smi = 2693 bool known_non_smi =
2705 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 2694 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
2706 (right_side.is_constant() && !right_side.handle()->IsSmi()) || 2695 (right_side.is_constant() && !right_side.handle()->IsSmi());
2707 left_side.number_info().IsHeapNumber() ||
2708 right_side.number_info().IsHeapNumber();
2709 NaNInformation nan_info = 2696 NaNInformation nan_info =
2710 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ? 2697 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ?
2711 kBothCouldBeNaN : 2698 kBothCouldBeNaN :
2712 kCantBothBeNaN; 2699 kCantBothBeNaN;
2713
2714 // Inline number comparison handling any combination of smi's and heap
2715 // numbers if:
2716 // code is in a loop
2717 // the compare operation is different from equal
2718 // compare is not a for-loop comparison
2719 // The reason for excluding equal is that it will most likely be done
2720 // with smi's (not heap numbers) and the code to comparing smi's is inlined
2721 // separately. The same reason applies for for-loop comparison which will
2722 // also most likely be smi comparisons.
2723 bool is_loop_condition = (node->AsExpression() != NULL)
2724 && node->AsExpression()->is_loop_condition();
2725 bool inline_number_compare =
2726 loop_nesting() > 0 && cc != equal && !is_loop_condition;
2727
2728 // Left and right needed in registers for the following code.
2729 left_side.ToRegister(); 2700 left_side.ToRegister();
2730 right_side.ToRegister(); 2701 right_side.ToRegister();
2731 2702
2732 if (known_non_smi) { 2703 if (known_non_smi) {
2733 // Inline the equality check if both operands can't be a NaN. If both 2704 // When non-smi, call out to the compare stub.
2734 // objects are the same they are equal. 2705 CompareStub stub(cc, strict, nan_info);
2735 if (nan_info == kCantBothBeNaN && cc == equal) {
2736 __ cmp(left_side.reg(), Operand(right_side.reg()));
2737 dest->true_target()->Branch(equal);
2738 }
2739
2740 // Inline number comparison.
2741 if (inline_number_compare) {
2742 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2743 }
2744
2745 // End of in-line compare, call out to the compare stub. Don't include
2746 // number comparison in the stub if it was inlined.
2747 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2748 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2706 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2749 if (cc == equal) { 2707 if (cc == equal) {
2750 __ test(answer.reg(), Operand(answer.reg())); 2708 __ test(answer.reg(), Operand(answer.reg()));
2751 } else { 2709 } else {
2752 __ cmp(answer.reg(), 0); 2710 __ cmp(answer.reg(), 0);
2753 } 2711 }
2754 answer.Unuse(); 2712 answer.Unuse();
2755 dest->Split(cc); 2713 dest->Split(cc);
2756 } else { 2714 } else {
2757 // Here we split control flow to the stub call and inlined cases 2715 // Here we split control flow to the stub call and inlined cases
2758 // before finally splitting it to the control destination. We use 2716 // before finally splitting it to the control destination. We use
2759 // a jump target and branching to duplicate the virtual frame at 2717 // a jump target and branching to duplicate the virtual frame at
2760 // the first split. We manually handle the off-frame references 2718 // the first split. We manually handle the off-frame references
2761 // by reconstituting them on the non-fall-through path. 2719 // by reconstituting them on the non-fall-through path.
2762 JumpTarget is_smi; 2720 JumpTarget is_smi;
2763 Register left_reg = left_side.reg(); 2721 Register left_reg = left_side.reg();
2764 Register right_reg = right_side.reg(); 2722 Register right_reg = right_side.reg();
2765 2723
2766 // In-line check for comparing two smis.
2767 Result temp = allocator_->Allocate(); 2724 Result temp = allocator_->Allocate();
2768 ASSERT(temp.is_valid()); 2725 ASSERT(temp.is_valid());
2769 __ mov(temp.reg(), left_side.reg()); 2726 __ mov(temp.reg(), left_side.reg());
2770 __ or_(temp.reg(), Operand(right_side.reg())); 2727 __ or_(temp.reg(), Operand(right_side.reg()));
2771 __ test(temp.reg(), Immediate(kSmiTagMask)); 2728 __ test(temp.reg(), Immediate(kSmiTagMask));
2772 temp.Unuse(); 2729 temp.Unuse();
2773 is_smi.Branch(zero, taken); 2730 is_smi.Branch(zero, taken);
2774 2731 // When non-smi, call out to the compare stub.
2775 // Inline the equality check if both operands can't be a NaN. If both 2732 CompareStub stub(cc, strict, nan_info);
2776 // objects are the same they are equal.
2777 if (nan_info == kCantBothBeNaN && cc == equal) {
2778 __ cmp(left_side.reg(), Operand(right_side.reg()));
2779 dest->true_target()->Branch(equal);
2780 }
2781
2782 // Inline number comparison.
2783 if (inline_number_compare) {
2784 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2785 }
2786
2787 // End of in-line compare, call out to the compare stub. Don't include
2788 // number comparison in the stub if it was inlined.
2789 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2790 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2733 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2791 if (cc == equal) { 2734 if (cc == equal) {
2792 __ test(answer.reg(), Operand(answer.reg())); 2735 __ test(answer.reg(), Operand(answer.reg()));
2793 } else { 2736 } else {
2794 __ cmp(answer.reg(), 0); 2737 __ cmp(answer.reg(), 0);
2795 } 2738 }
2796 answer.Unuse(); 2739 answer.Unuse();
2797 dest->true_target()->Branch(cc); 2740 dest->true_target()->Branch(cc);
2798 dest->false_target()->Jump(); 2741 dest->false_target()->Jump();
2799 2742
2800 is_smi.Bind(); 2743 is_smi.Bind();
2801 left_side = Result(left_reg); 2744 left_side = Result(left_reg);
2802 right_side = Result(right_reg); 2745 right_side = Result(right_reg);
2803 __ cmp(left_side.reg(), Operand(right_side.reg())); 2746 __ cmp(left_side.reg(), Operand(right_side.reg()));
2804 right_side.Unuse(); 2747 right_side.Unuse();
2805 left_side.Unuse(); 2748 left_side.Unuse();
2806 dest->Split(cc); 2749 dest->Split(cc);
2807 } 2750 }
2808 } 2751 }
2809 } 2752 }
2810 2753
2811 2754
2812 // Check that the comparison operand is a number. Jump to not_numbers jump
2813 // target passing the left and right result if the operand is not a number.
2814 static void CheckComparisonOperand(MacroAssembler* masm_,
2815 Result* operand,
2816 Result* left_side,
2817 Result* right_side,
2818 JumpTarget* not_numbers) {
2819 // Perform check if operand is not known to be a number.
2820 if (!operand->number_info().IsNumber()) {
2821 Label done;
2822 __ test(operand->reg(), Immediate(kSmiTagMask));
2823 __ j(zero, &done);
2824 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
2825 Immediate(Factory::heap_number_map()));
2826 not_numbers->Branch(not_equal, left_side, right_side, not_taken);
2827 __ bind(&done);
2828 }
2829 }
2830
2831
2832 // Load a comparison operand to the FPU stack. This assumes that the operand has
2833 // already been checked and is a number.
2834 static void LoadComparisonOperand(MacroAssembler* masm_,
2835 Result* operand,
2836 Result* left_side,
2837 Result* right_side) {
2838 Label done;
2839 if (operand->number_info().IsHeapNumber()) {
2840 // Operand is known to be a heap number, just load it.
2841 __ fld_d(FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2842 } else if (operand->number_info().IsSmi()) {
2843 // Operand is known to be a smi. Convert it to double and keep the original
2844 // smi.
2845 __ SmiUntag(operand->reg());
2846 __ push(operand->reg());
2847 __ fild_s(Operand(esp, 0));
2848 __ pop(operand->reg());
2849 __ SmiTag(operand->reg());
2850 } else {
2851 // Operand type not known, check for smi otherwise assume heap number.
2852 Label smi;
2853 __ test(operand->reg(), Immediate(kSmiTagMask));
2854 __ j(zero, &smi);
2855 __ fld_d(FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2856 __ jmp(&done);
2857 __ bind(&smi);
2858 __ SmiUntag(operand->reg());
2859 __ push(operand->reg());
2860 __ fild_s(Operand(esp, 0));
2861 __ pop(operand->reg());
2862 __ SmiTag(operand->reg());
2863 __ jmp(&done);
2864 }
2865 __ bind(&done);
2866 }
2867
2868
2869 // Load a comparison operand into into a XMM register. Jump to not_numbers jump
2870 // target passing the left and right result if the operand is not a number.
2871 static void LoadComparisonOperandSSE2(MacroAssembler* masm_,
2872 Result* operand,
2873 XMMRegister reg,
2874 Result* left_side,
2875 Result* right_side,
2876 JumpTarget* not_numbers) {
2877 Label done;
2878 if (operand->number_info().IsHeapNumber()) {
2879 // Operand is known to be a heap number, just load it.
2880 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2881 } else if (operand->number_info().IsSmi()) {
2882 // Operand is known to be a smi. Convert it to double and keep the original
2883 // smi.
2884 __ SmiUntag(operand->reg());
2885 __ cvtsi2sd(reg, Operand(operand->reg()));
2886 __ SmiTag(left_side->reg());
2887 } else {
2888 // Operand type not known, check for smi or heap number.
2889 Label smi;
2890 __ test(operand->reg(), Immediate(kSmiTagMask));
2891 __ j(zero, &smi);
2892 if (!operand->number_info().IsNumber()) {
2893 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
2894 Immediate(Factory::heap_number_map()));
2895 not_numbers->Branch(not_equal, left_side, right_side, taken);
2896 }
2897 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2898 __ jmp(&done);
2899
2900 __ bind(&smi);
2901 // Comvert smi to float and keep the original smi.
2902 __ SmiUntag(operand->reg());
2903 __ cvtsi2sd(reg, Operand(operand->reg()));
2904 __ SmiTag(operand->reg());
2905 __ jmp(&done);
2906 }
2907 __ bind(&done);
2908 }
2909
2910
2911 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
2912 Result* right_side,
2913 Condition cc,
2914 ControlDestination* dest) {
2915 ASSERT(left_side->is_register());
2916 ASSERT(right_side->is_register());
2917
2918 JumpTarget not_numbers;
2919 if (CpuFeatures::IsSupported(SSE2)) {
2920 CpuFeatures::Scope use_sse2(SSE2);
2921
2922 // Load left and right operand into registers xmm0 and xmm1 and compare.
2923 LoadComparisonOperandSSE2(masm_, left_side, xmm0, left_side, right_side,
2924 &not_numbers);
2925 LoadComparisonOperandSSE2(masm_, right_side, xmm1, left_side, right_side,
2926 &not_numbers);
2927 __ comisd(xmm0, xmm1);
2928 } else {
2929 Label check_right, compare;
2930
2931 // Make sure that both comparison operands are numbers.
2932 CheckComparisonOperand(masm_, left_side, left_side, right_side,
2933 &not_numbers);
2934 CheckComparisonOperand(masm_, right_side, left_side, right_side,
2935 &not_numbers);
2936
2937 // Load right and left operand to FPU stack and compare.
2938 LoadComparisonOperand(masm_, right_side, left_side, right_side);
2939 LoadComparisonOperand(masm_, left_side, left_side, right_side);
2940 __ FCmp();
2941 }
2942
2943 // Bail out if a NaN is involved.
2944 not_numbers.Branch(parity_even, left_side, right_side, not_taken);
2945
2946 // Split to destination targets based on comparison.
2947 left_side->Unuse();
2948 right_side->Unuse();
2949 dest->true_target()->Branch(DoubleCondition(cc));
2950 dest->false_target()->Jump();
2951
2952 not_numbers.Bind(left_side, right_side);
2953 }
2954
2955
2956 // Call the function just below TOS on the stack with the given 2755 // Call the function just below TOS on the stack with the given
2957 // arguments. The receiver is the TOS. 2756 // arguments. The receiver is the TOS.
2958 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 2757 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
2959 CallFunctionFlags flags, 2758 CallFunctionFlags flags,
2960 int position) { 2759 int position) {
2961 // Push the arguments ("left-to-right") on the stack. 2760 // Push the arguments ("left-to-right") on the stack.
2962 int arg_count = args->length(); 2761 int arg_count = args->length();
2963 for (int i = 0; i < arg_count; i++) { 2762 for (int i = 0; i < arg_count; i++) {
2964 Load(args->at(i)); 2763 Load(args->at(i));
2965 } 2764 }
(...skipping 8105 matching lines...) Expand 10 before | Expand all | Expand 10 after
11071 } 10870 }
11072 __ bind(&slow); 10871 __ bind(&slow);
11073 } 10872 }
11074 10873
11075 // Push arguments below the return address. 10874 // Push arguments below the return address.
11076 __ pop(ecx); 10875 __ pop(ecx);
11077 __ push(eax); 10876 __ push(eax);
11078 __ push(edx); 10877 __ push(edx);
11079 __ push(ecx); 10878 __ push(ecx);
11080 10879
11081 // Generate the number comparison code. 10880 // Inlined floating point compare.
11082 if (include_number_compare_) { 10881 // Call builtin if operands are not floating point or smi.
11083 Label non_number_comparison; 10882 Label check_for_symbols;
11084 Label unordered; 10883 Label unordered;
11085 if (CpuFeatures::IsSupported(SSE2)) { 10884 if (CpuFeatures::IsSupported(SSE2)) {
11086 CpuFeatures::Scope use_sse2(SSE2); 10885 CpuFeatures::Scope use_sse2(SSE2);
11087 CpuFeatures::Scope use_cmov(CMOV); 10886 CpuFeatures::Scope use_cmov(CMOV);
11088 10887
11089 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); 10888 FloatingPointHelper::LoadSSE2Operands(masm, &check_for_symbols);
11090 __ comisd(xmm0, xmm1); 10889 __ comisd(xmm0, xmm1);
11091 10890
11092 // Don't base result on EFLAGS when a NaN is involved. 10891 // Jump to builtin for NaN.
11093 __ j(parity_even, &unordered, not_taken); 10892 __ j(parity_even, &unordered, not_taken);
11094 // Return a result of -1, 0, or 1, based on EFLAGS. 10893 __ mov(eax, 0); // equal
11095 __ mov(eax, 0); // equal 10894 __ mov(ecx, Immediate(Smi::FromInt(1)));
11096 __ mov(ecx, Immediate(Smi::FromInt(1))); 10895 __ cmov(above, eax, Operand(ecx));
11097 __ cmov(above, eax, Operand(ecx)); 10896 __ mov(ecx, Immediate(Smi::FromInt(-1)));
11098 __ mov(ecx, Immediate(Smi::FromInt(-1))); 10897 __ cmov(below, eax, Operand(ecx));
11099 __ cmov(below, eax, Operand(ecx)); 10898 __ ret(2 * kPointerSize);
11100 __ ret(2 * kPointerSize); 10899 } else {
11101 } else { 10900 FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx);
11102 FloatingPointHelper::CheckFloatOperands( 10901 FloatingPointHelper::LoadFloatOperands(masm, ecx);
11103 masm, &non_number_comparison, ebx); 10902 __ FCmp();
11104 FloatingPointHelper::LoadFloatOperands(masm, ecx);
11105 __ FCmp();
11106 10903
11107 // Don't base result on EFLAGS when a NaN is involved. 10904 // Jump to builtin for NaN.
11108 __ j(parity_even, &unordered, not_taken); 10905 __ j(parity_even, &unordered, not_taken);
11109 10906
11110 Label below_label, above_label; 10907 Label below_lbl, above_lbl;
11111 // Return a result of -1, 0, or 1, based on EFLAGS. In all cases remove 10908 // Return a result of -1, 0, or 1, to indicate result of comparison.
11112 // two arguments from the stack as they have been pushed in preparation 10909 __ j(below, &below_lbl, not_taken);
11113 // of a possible runtime call. 10910 __ j(above, &above_lbl, not_taken);
11114 __ j(below, &below_label, not_taken);
11115 __ j(above, &above_label, not_taken);
11116 10911
11117 __ xor_(eax, Operand(eax)); 10912 __ xor_(eax, Operand(eax)); // equal
11118 __ ret(2 * kPointerSize); 10913 // Both arguments were pushed in case a runtime call was needed.
10914 __ ret(2 * kPointerSize);
11119 10915
11120 __ bind(&below_label); 10916 __ bind(&below_lbl);
11121 __ mov(eax, Immediate(Smi::FromInt(-1))); 10917 __ mov(eax, Immediate(Smi::FromInt(-1)));
11122 __ ret(2 * kPointerSize); 10918 __ ret(2 * kPointerSize);
11123 10919
11124 __ bind(&above_label); 10920 __ bind(&above_lbl);
11125 __ mov(eax, Immediate(Smi::FromInt(1))); 10921 __ mov(eax, Immediate(Smi::FromInt(1)));
11126 __ ret(2 * kPointerSize);
11127 }
11128
11129 // If one of the numbers was NaN, then the result is always false.
11130 // The cc is never not-equal.
11131 __ bind(&unordered);
11132 ASSERT(cc_ != not_equal);
11133 if (cc_ == less || cc_ == less_equal) {
11134 __ mov(eax, Immediate(Smi::FromInt(1)));
11135 } else {
11136 __ mov(eax, Immediate(Smi::FromInt(-1)));
11137 }
11138 __ ret(2 * kPointerSize); // eax, edx were pushed 10922 __ ret(2 * kPointerSize); // eax, edx were pushed
11139
11140 // The number comparison code did not provide a valid result.
11141 __ bind(&non_number_comparison);
11142 } 10923 }
10924 // If one of the numbers was NaN, then the result is always false.
10925 // The cc is never not-equal.
10926 __ bind(&unordered);
10927 ASSERT(cc_ != not_equal);
10928 if (cc_ == less || cc_ == less_equal) {
10929 __ mov(eax, Immediate(Smi::FromInt(1)));
10930 } else {
10931 __ mov(eax, Immediate(Smi::FromInt(-1)));
10932 }
10933 __ ret(2 * kPointerSize); // eax, edx were pushed
11143 10934
11144 // Fast negative check for symbol-to-symbol equality. 10935 // Fast negative check for symbol-to-symbol equality.
10936 __ bind(&check_for_symbols);
11145 Label check_for_strings; 10937 Label check_for_strings;
11146 if (cc_ == equal) { 10938 if (cc_ == equal) {
11147 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); 10939 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx);
11148 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); 10940 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx);
11149 10941
11150 // We've already checked for object identity, so if both operands 10942 // We've already checked for object identity, so if both operands
11151 // are symbols they aren't equal. Register eax already holds a 10943 // are symbols they aren't equal. Register eax already holds a
11152 // non-zero value, which indicates not equal, so just return. 10944 // non-zero value, which indicates not equal, so just return.
11153 __ ret(2 * kPointerSize); 10945 __ ret(2 * kPointerSize);
11154 } 10946 }
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
11744 __ bind(&is_not_instance); 11536 __ bind(&is_not_instance);
11745 __ Set(eax, Immediate(Smi::FromInt(1))); 11537 __ Set(eax, Immediate(Smi::FromInt(1)));
11746 __ ret(2 * kPointerSize); 11538 __ ret(2 * kPointerSize);
11747 11539
11748 // Slow-case: Go through the JavaScript implementation. 11540 // Slow-case: Go through the JavaScript implementation.
11749 __ bind(&slow); 11541 __ bind(&slow);
11750 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 11542 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
11751 } 11543 }
11752 11544
11753 11545
11546 // Unfortunately you have to run without snapshots to see most of these
11547 // names in the profile since most compare stubs end up in the snapshot.
11548 const char* CompareStub::GetName() {
11549 switch (cc_) {
11550 case less: return "CompareStub_LT";
11551 case greater: return "CompareStub_GT";
11552 case less_equal: return "CompareStub_LE";
11553 case greater_equal: return "CompareStub_GE";
11554 case not_equal: {
11555 if (strict_) {
11556 if (never_nan_nan_) {
11557 return "CompareStub_NE_STRICT_NO_NAN";
11558 } else {
11559 return "CompareStub_NE_STRICT";
11560 }
11561 } else {
11562 if (never_nan_nan_) {
11563 return "CompareStub_NE_NO_NAN";
11564 } else {
11565 return "CompareStub_NE";
11566 }
11567 }
11568 }
11569 case equal: {
11570 if (strict_) {
11571 if (never_nan_nan_) {
11572 return "CompareStub_EQ_STRICT_NO_NAN";
11573 } else {
11574 return "CompareStub_EQ_STRICT";
11575 }
11576 } else {
11577 if (never_nan_nan_) {
11578 return "CompareStub_EQ_NO_NAN";
11579 } else {
11580 return "CompareStub_EQ";
11581 }
11582 }
11583 }
11584 default: return "CompareStub";
11585 }
11586 }
11587
11588
11754 int CompareStub::MinorKey() { 11589 int CompareStub::MinorKey() {
11755 // Encode the three parameters in a unique 16 bit value. To avoid duplicate 11590 // Encode the three parameters in a unique 16 bit value. To avoid duplicate
11756 // stubs the never NaN NaN condition is only taken into account if the 11591 // stubs the never NaN NaN condition is only taken into account if the
11757 // condition is equals. 11592 // condition is equals.
11758 ASSERT(static_cast<unsigned>(cc_) < (1 << 13)); 11593 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
11759 return ConditionField::encode(static_cast<unsigned>(cc_)) 11594 return ConditionField::encode(static_cast<unsigned>(cc_))
11760 | StrictField::encode(strict_) 11595 | StrictField::encode(strict_)
11761 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) 11596 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false);
11762 | IncludeNumberCompareField::encode(include_number_compare_);
11763 } 11597 }
11764 11598
11765 11599
11766 // Unfortunately you have to run without snapshots to see most of these
11767 // names in the profile since most compare stubs end up in the snapshot.
11768 const char* CompareStub::GetName() {
11769 if (name_ != NULL) return name_;
11770 const int kMaxNameLength = 100;
11771 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
11772 if (name_ == NULL) return "OOM";
11773
11774 const char* cc_name;
11775 switch (cc_) {
11776 case less: cc_name = "LT"; break;
11777 case greater: cc_name = "GT"; break;
11778 case less_equal: cc_name = "LE"; break;
11779 case greater_equal: cc_name = "GE"; break;
11780 case equal: cc_name = "EQ"; break;
11781 case not_equal: cc_name = "NE"; break;
11782 default: cc_name = "UnknownCondition"; break;
11783 }
11784
11785 const char* strict_name = "";
11786 if (strict_ && (cc_ == equal || cc_ == not_equal)) {
11787 strict_name = "_STRICT";
11788 }
11789
11790 const char* never_nan_nan_name = "";
11791 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) {
11792 never_nan_nan_name = "_NO_NAN";
11793 }
11794
11795 const char* include_number_compare_name = "";
11796 if (!include_number_compare_) {
11797 include_number_compare_name = "_NO_NUMBER";
11798 }
11799
11800 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
11801 "CompareStub_%s%s%s%s",
11802 cc_name,
11803 strict_name,
11804 never_nan_nan_name,
11805 include_number_compare_name);
11806 return name_;
11807 }
11808
11809
11810 void StringAddStub::Generate(MacroAssembler* masm) { 11600 void StringAddStub::Generate(MacroAssembler* masm) {
11811 Label string_add_runtime; 11601 Label string_add_runtime;
11812 11602
11813 // Load the two arguments. 11603 // Load the two arguments.
11814 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 11604 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
11815 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 11605 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
11816 11606
11817 // Make sure that both arguments are strings if not known in advance. 11607 // Make sure that both arguments are strings if not known in advance.
11818 if (string_check_) { 11608 if (string_check_) {
11819 __ test(eax, Immediate(kSmiTagMask)); 11609 __ test(eax, Immediate(kSmiTagMask));
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
12430 12220
12431 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 12221 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
12432 Register left, 12222 Register left,
12433 Register right, 12223 Register right,
12434 Register scratch1, 12224 Register scratch1,
12435 Register scratch2, 12225 Register scratch2,
12436 Register scratch3) { 12226 Register scratch3) {
12437 Label result_not_equal; 12227 Label result_not_equal;
12438 Label result_greater; 12228 Label result_greater;
12439 Label compare_lengths; 12229 Label compare_lengths;
12440
12441 __ IncrementCounter(&Counters::string_compare_native, 1);
12442
12443 // Find minimum length. 12230 // Find minimum length.
12444 Label left_shorter; 12231 Label left_shorter;
12445 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 12232 __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
12446 __ mov(scratch3, scratch1); 12233 __ mov(scratch3, scratch1);
12447 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); 12234 __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
12448 12235
12449 Register length_delta = scratch3; 12236 Register length_delta = scratch3;
12450 12237
12451 __ j(less_equal, &left_shorter); 12238 __ j(less_equal, &left_shorter);
12452 // Right string is shorter. Change scratch1 to be length of right string. 12239 // Right string is shorter. Change scratch1 to be length of right string.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
12530 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 12317 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
12531 __ IncrementCounter(&Counters::string_compare_native, 1); 12318 __ IncrementCounter(&Counters::string_compare_native, 1);
12532 __ ret(2 * kPointerSize); 12319 __ ret(2 * kPointerSize);
12533 12320
12534 __ bind(&not_same); 12321 __ bind(&not_same);
12535 12322
12536 // Check that both objects are sequential ascii strings. 12323 // Check that both objects are sequential ascii strings.
12537 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); 12324 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
12538 12325
12539 // Compare flat ascii strings. 12326 // Compare flat ascii strings.
12327 __ IncrementCounter(&Counters::string_compare_native, 1);
12540 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); 12328 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
12541 12329
12542 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12330 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12543 // tagged as a small integer. 12331 // tagged as a small integer.
12544 __ bind(&runtime); 12332 __ bind(&runtime);
12545 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12333 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12546 } 12334 }
12547 12335
12548 #undef __ 12336 #undef __
12549 12337
12550 } } // namespace v8::internal 12338 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/jump-target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698