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

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

Issue 1117011: Inline floating point compare... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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 | Annotate | Revision Log
« 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
914 // Code pattern for loading floating point values. Input values must 915 // Code pattern for loading floating point values. Input values must
915 // be either smi or heap number objects (fp values). Requirements: 916 // be either smi or heap number objects (fp values). Requirements:
916 // operand_1 on TOS+1 or in edx, operand_2 on TOS+2 or in eax. 917 // operand_1 on TOS+1 or in edx, operand_2 on TOS+2 or in eax.
917 // Returns operands as floating point numbers on FPU stack. 918 // Returns operands as floating point numbers on FPU stack.
918 static void LoadFloatOperands(MacroAssembler* masm, 919 static void LoadFloatOperands(MacroAssembler* masm,
919 Register scratch, 920 Register scratch,
920 ArgLocation arg_location = ARGS_ON_STACK); 921 ArgLocation arg_location = ARGS_ON_STACK);
921 922
922 // Similar to LoadFloatOperand but assumes that both operands are smis. 923 // Similar to LoadFloatOperand but assumes that both operands are smis.
923 // Expects operands in edx, eax. 924 // Expects operands in edx, eax.
924 static void LoadFloatSmis(MacroAssembler* masm, Register scratch); 925 static void LoadFloatSmis(MacroAssembler* masm, Register scratch);
925 926
926 // Test if operands are smi or number objects (fp). Requirements: 927 // Test if operands are smi or number objects (fp). Requirements:
927 // operand_1 in eax, operand_2 in edx; falls through on float 928 // operand_1 in eax, operand_2 in edx; falls through on float
928 // operands, jumps to the non_float label otherwise. 929 // operands, jumps to the non_float label otherwise.
929 static void CheckFloatOperands(MacroAssembler* masm, 930 static void CheckFloatOperands(MacroAssembler* masm,
930 Label* non_float, 931 Label* non_float,
931 Register scratch); 932 Register scratch);
933
932 // Takes the operands in edx and eax and loads them as integers in eax 934 // Takes the operands in edx and eax and loads them as integers in eax
933 // and ecx. 935 // and ecx.
934 static void LoadAsIntegers(MacroAssembler* masm, 936 static void LoadAsIntegers(MacroAssembler* masm,
935 NumberInfo number_info, 937 NumberInfo number_info,
936 bool use_sse3, 938 bool use_sse3,
937 Label* operand_conversion_failure); 939 Label* operand_conversion_failure);
938 static void LoadNumbersAsIntegers(MacroAssembler* masm, 940 static void LoadNumbersAsIntegers(MacroAssembler* masm,
939 NumberInfo number_info, 941 NumberInfo number_info,
940 bool use_sse3, 942 bool use_sse3,
941 Label* operand_conversion_failure); 943 Label* operand_conversion_failure);
942 static void LoadUnknownsAsIntegers(MacroAssembler* masm, 944 static void LoadUnknownsAsIntegers(MacroAssembler* masm,
943 bool use_sse3, 945 bool use_sse3,
944 Label* operand_conversion_failure); 946 Label* operand_conversion_failure);
945 947
946 // Test if operands are smis or heap numbers and load them 948 // Test if operands are smis or heap numbers and load them
947 // into xmm0 and xmm1 if they are. Operands are in edx and eax. 949 // into xmm0 and xmm1 if they are. Operands are in edx and eax.
948 // Leaves operands unchanged. 950 // Leaves operands unchanged.
949 static void LoadSSE2Operands(MacroAssembler* masm); 951 static void LoadSSE2Operands(MacroAssembler* masm);
952
950 // Test if operands are numbers (smi or HeapNumber objects), and load 953 // Test if operands are numbers (smi or HeapNumber objects), and load
951 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if 954 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
952 // either operand is not a number. Operands are in edx and eax. 955 // either operand is not a number. Operands are in edx and eax.
953 // Leaves operands unchanged. 956 // Leaves operands unchanged.
954 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers); 957 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers);
955 958
956 // Similar to LoadSSE2Operands but assumes that both operands are smis. 959 // Similar to LoadSSE2Operands but assumes that both operands are smis.
957 // Expects operands in edx, eax. 960 // Expects operands in edx, eax.
958 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch); 961 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch);
959 }; 962 };
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after
2354 2357
2355 static bool CouldBeNaN(const Result& result) { 2358 static bool CouldBeNaN(const Result& result) {
2356 if (result.number_info().IsSmi()) return false; 2359 if (result.number_info().IsSmi()) return false;
2357 if (result.number_info().IsInteger32()) return false; 2360 if (result.number_info().IsInteger32()) return false;
2358 if (!result.is_constant()) return true; 2361 if (!result.is_constant()) return true;
2359 if (!result.handle()->IsHeapNumber()) return false; 2362 if (!result.handle()->IsHeapNumber()) return false;
2360 return isnan(HeapNumber::cast(*result.handle())->value()); 2363 return isnan(HeapNumber::cast(*result.handle())->value());
2361 } 2364 }
2362 2365
2363 2366
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
2364 void CodeGenerator::Comparison(AstNode* node, 2383 void CodeGenerator::Comparison(AstNode* node,
2365 Condition cc, 2384 Condition cc,
2366 bool strict, 2385 bool strict,
2367 ControlDestination* dest) { 2386 ControlDestination* dest) {
2368 // Strict only makes sense for equality comparisons. 2387 // Strict only makes sense for equality comparisons.
2369 ASSERT(!strict || cc == equal); 2388 ASSERT(!strict || cc == equal);
2370 2389
2371 Result left_side; 2390 Result left_side;
2372 Result right_side; 2391 Result right_side;
2373 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 2392 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2424 } 2443 }
2425 } else { 2444 } else {
2426 // Only one side is a constant Smi. 2445 // Only one side is a constant Smi.
2427 // If left side is a constant Smi, reverse the operands. 2446 // If left side is a constant Smi, reverse the operands.
2428 // Since one side is a constant Smi, conversion order does not matter. 2447 // Since one side is a constant Smi, conversion order does not matter.
2429 if (left_side_constant_smi) { 2448 if (left_side_constant_smi) {
2430 Result temp = left_side; 2449 Result temp = left_side;
2431 left_side = right_side; 2450 left_side = right_side;
2432 right_side = temp; 2451 right_side = temp;
2433 cc = ReverseCondition(cc); 2452 cc = ReverseCondition(cc);
2434 // This may reintroduce greater or less_equal as the value of cc. 2453 // This may re-introduce greater or less_equal as the value of cc.
2435 // CompareStub and the inline code both support all values of cc. 2454 // CompareStub and the inline code both support all values of cc.
2436 } 2455 }
2437 // Implement comparison against a constant Smi, inlining the case 2456 // Implement comparison against a constant Smi, inlining the case
2438 // where both sides are Smis. 2457 // where both sides are Smis.
2439 left_side.ToRegister(); 2458 left_side.ToRegister();
2440 Register left_reg = left_side.reg(); 2459 Register left_reg = left_side.reg();
2441 Handle<Object> right_val = right_side.handle(); 2460 Handle<Object> right_val = right_side.handle();
2442 2461
2443 // Here we split control flow to the stub call and inlined cases 2462 // Here we split control flow to the stub call and inlined cases
2444 // before finally splitting it to the control destination. We use 2463 // before finally splitting it to the control destination. We use
(...skipping 28 matching lines...) Expand all
2473 } else { 2492 } else {
2474 Result temp = allocator()->Allocate(); 2493 Result temp = allocator()->Allocate();
2475 __ mov(temp.reg(), Immediate(value)); 2494 __ mov(temp.reg(), Immediate(value));
2476 __ cvtsi2sd(xmm0, Operand(temp.reg())); 2495 __ cvtsi2sd(xmm0, Operand(temp.reg()));
2477 temp.Unuse(); 2496 temp.Unuse();
2478 } 2497 }
2479 __ comisd(xmm1, xmm0); 2498 __ comisd(xmm1, xmm0);
2480 // Jump to builtin for NaN. 2499 // Jump to builtin for NaN.
2481 not_number.Branch(parity_even, &left_side); 2500 not_number.Branch(parity_even, &left_side);
2482 left_side.Unuse(); 2501 left_side.Unuse();
2483 Condition double_cc = cc; 2502 dest->true_target()->Branch(DoubleCondition(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);
2493 dest->false_target()->Jump(); 2503 dest->false_target()->Jump();
2494 not_number.Bind(&left_side); 2504 not_number.Bind(&left_side);
2495 } 2505 }
2496 2506
2497 // Setup and call the compare stub. 2507 // Setup and call the compare stub.
2498 CompareStub stub(cc, strict, kCantBothBeNaN); 2508 CompareStub stub(cc, strict, kCantBothBeNaN);
2499 Result result = frame_->CallStub(&stub, &left_side, &right_side); 2509 Result result = frame_->CallStub(&stub, &left_side, &right_side);
2500 result.ToRegister(); 2510 result.ToRegister();
2501 __ cmp(result.reg(), 0); 2511 __ cmp(result.reg(), 0);
2502 result.Unuse(); 2512 result.Unuse();
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2681 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2691 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2682 Immediate(1)); 2692 Immediate(1));
2683 __ bind(&characters_were_different); 2693 __ bind(&characters_were_different);
2684 } 2694 }
2685 temp2.Unuse(); 2695 temp2.Unuse();
2686 left_side.Unuse(); 2696 left_side.Unuse();
2687 right_side.Unuse(); 2697 right_side.Unuse();
2688 dest->Split(cc); 2698 dest->Split(cc);
2689 } 2699 }
2690 } else { 2700 } else {
2691 // Neither side is a constant Smi or null. 2701 // Neither side is a constant Smi, constant 1-char string or constant null.
2692 // If either side is a non-smi constant, skip the smi check. 2702 // If either side is a non-smi constant, or known to be a heap number skip
2703 // the smi check.
2693 bool known_non_smi = 2704 bool known_non_smi =
2694 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 2705 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
2695 (right_side.is_constant() && !right_side.handle()->IsSmi()); 2706 (right_side.is_constant() && !right_side.handle()->IsSmi()) ||
2707 left_side.number_info().IsHeapNumber() ||
2708 right_side.number_info().IsHeapNumber();
2696 NaNInformation nan_info = 2709 NaNInformation nan_info =
2697 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ? 2710 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ?
2698 kBothCouldBeNaN : 2711 kBothCouldBeNaN :
2699 kCantBothBeNaN; 2712 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_for_loop_compare = (node->AsCompareOperation() != NULL)
2724 && node->AsCompareOperation()->is_for_loop_condition();
2725 bool inline_number_compare = loop_nesting() > 0
2726 && cc != equal
2727 && !is_for_loop_compare;
2728
2729 // Left and right needed in registers for the following code.
2700 left_side.ToRegister(); 2730 left_side.ToRegister();
2701 right_side.ToRegister(); 2731 right_side.ToRegister();
2702 2732
2703 if (known_non_smi) { 2733 if (known_non_smi) {
2704 // When non-smi, call out to the compare stub. 2734 // Inline the equality check if both operands can't be a NaN. If both
2705 CompareStub stub(cc, strict, nan_info); 2735 // objects are the same they are equal.
2736 if (nan_info == kCantBothBeNaN && cc == equal) {
Erik Corry 2010/03/23 18:09:24 This seems wrong. If one side is a constant fp nu
Søren Thygesen Gjesse 2010/03/23 20:40:01 This will only provide true when the objects are t
2737 __ cmp(left_side.reg(), Operand(right_side.reg()));
2738 dest->true_target()->Branch(equal);
2739 }
2740
2741 // Inline number comparison.
2742 if (inline_number_compare) {
2743 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2744 }
2745
2746 // End of in-line compare, call out to the compare stub. Don't include
2747 // number comparison in the stub if it was inlined.
2748 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2706 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2749 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2707 if (cc == equal) { 2750 if (cc == equal) {
2708 __ test(answer.reg(), Operand(answer.reg())); 2751 __ test(answer.reg(), Operand(answer.reg()));
2709 } else { 2752 } else {
2710 __ cmp(answer.reg(), 0); 2753 __ cmp(answer.reg(), 0);
2711 } 2754 }
2712 answer.Unuse(); 2755 answer.Unuse();
2713 dest->Split(cc); 2756 dest->Split(cc);
2714 } else { 2757 } else {
2715 // Here we split control flow to the stub call and inlined cases 2758 // Here we split control flow to the stub call and inlined cases
2716 // before finally splitting it to the control destination. We use 2759 // before finally splitting it to the control destination. We use
2717 // a jump target and branching to duplicate the virtual frame at 2760 // a jump target and branching to duplicate the virtual frame at
2718 // the first split. We manually handle the off-frame references 2761 // the first split. We manually handle the off-frame references
2719 // by reconstituting them on the non-fall-through path. 2762 // by reconstituting them on the non-fall-through path.
2720 JumpTarget is_smi; 2763 JumpTarget is_smi;
2721 Register left_reg = left_side.reg(); 2764 Register left_reg = left_side.reg();
2722 Register right_reg = right_side.reg(); 2765 Register right_reg = right_side.reg();
2723 2766
2767 // In-line check for comparing two smis.
2724 Result temp = allocator_->Allocate(); 2768 Result temp = allocator_->Allocate();
2725 ASSERT(temp.is_valid()); 2769 ASSERT(temp.is_valid());
2726 __ mov(temp.reg(), left_side.reg()); 2770 __ mov(temp.reg(), left_side.reg());
2727 __ or_(temp.reg(), Operand(right_side.reg())); 2771 __ or_(temp.reg(), Operand(right_side.reg()));
2728 __ test(temp.reg(), Immediate(kSmiTagMask)); 2772 __ test(temp.reg(), Immediate(kSmiTagMask));
2729 temp.Unuse(); 2773 temp.Unuse();
2730 is_smi.Branch(zero, taken); 2774 is_smi.Branch(zero, taken);
2731 // When non-smi, call out to the compare stub. 2775
2732 CompareStub stub(cc, strict, nan_info); 2776 // Inline the equality check if both operands can't be a NaN. If both
2777 // objects are the same they are equal.
2778 if (nan_info == kCantBothBeNaN && cc == equal) {
2779 __ cmp(left_side.reg(), Operand(right_side.reg()));
2780 dest->true_target()->Branch(equal);
2781 }
2782
2783 // Inline number comparison.
2784 if (inline_number_compare) {
2785 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2786 }
2787
2788 // End of in-line compare, call out to the compare stub. Don't include
2789 // number comparison in the stub if it was inlined.
2790 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2733 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2791 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2734 if (cc == equal) { 2792 if (cc == equal) {
2735 __ test(answer.reg(), Operand(answer.reg())); 2793 __ test(answer.reg(), Operand(answer.reg()));
2736 } else { 2794 } else {
2737 __ cmp(answer.reg(), 0); 2795 __ cmp(answer.reg(), 0);
2738 } 2796 }
2739 answer.Unuse(); 2797 answer.Unuse();
2740 dest->true_target()->Branch(cc); 2798 dest->true_target()->Branch(cc);
2741 dest->false_target()->Jump(); 2799 dest->false_target()->Jump();
2742 2800
2743 is_smi.Bind(); 2801 is_smi.Bind();
2744 left_side = Result(left_reg); 2802 left_side = Result(left_reg);
2745 right_side = Result(right_reg); 2803 right_side = Result(right_reg);
2746 __ cmp(left_side.reg(), Operand(right_side.reg())); 2804 __ cmp(left_side.reg(), Operand(right_side.reg()));
2747 right_side.Unuse(); 2805 right_side.Unuse();
2748 left_side.Unuse(); 2806 left_side.Unuse();
2749 dest->Split(cc); 2807 dest->Split(cc);
2750 } 2808 }
2751 } 2809 }
2752 } 2810 }
2753 2811
2754 2812
2813 // Check that the comparison operand is a number. Jump to not_numbers jump
2814 // target passing the left and right result if the operand is not a number.
2815 static void CheckComparisonOperand(MacroAssembler* masm_,
2816 Result* operand,
2817 Result* left_side,
2818 Result* right_side,
2819 JumpTarget* not_numbers) {
2820 // Perform check if operand is not known to be a number.
2821 if (!operand->number_info().IsNumber()) {
2822 Label done;
2823 __ test(operand->reg(), Immediate(kSmiTagMask));
2824 __ j(zero, &done);
2825 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
2826 Immediate(Factory::heap_number_map()));
2827 not_numbers->Branch(not_equal, left_side, right_side, not_taken);
2828 __ bind(&done);
2829 }
2830 }
2831
2832
2833 // Load a comparison operand to the FPU stack. This assumes that the operand has
2834 // already been checked and is a number.
2835 static void LoadComparisonOperand(MacroAssembler* masm_,
2836 Result* operand,
2837 Result* left_side,
2838 Result* right_side) {
2839 Label done;
2840 if (operand->number_info().IsHeapNumber()) {
2841 // Operand is known to be a heap number, just load it.
2842 __ fld_d(FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2843 } else if (operand->number_info().IsSmi()) {
2844 // Operand is known to be a smi. Convert it to double and keep the original
2845 // smi.
2846 __ SmiUntag(operand->reg());
2847 __ push(operand->reg());
2848 __ fild_s(Operand(esp, 0));
2849 __ pop(operand->reg());
2850 __ SmiTag(operand->reg());
2851 } else {
2852 // Operand type not known, check for smi otherwise assume heap number.
2853 Label smi;
2854 __ test(operand->reg(), Immediate(kSmiTagMask));
2855 __ j(zero, &smi);
2856 __ fld_d(FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2857 __ jmp(&done);
2858 __ bind(&smi);
2859 __ SmiUntag(operand->reg());
2860 __ push(operand->reg());
2861 __ fild_s(Operand(esp, 0));
2862 __ pop(operand->reg());
2863 __ SmiTag(operand->reg());
2864 __ jmp(&done);
2865 }
2866 __ bind(&done);
2867 }
2868
2869
2870 // Load a comparison operand into into a XMM register. Jump to not_numbers jump
2871 // target passing the left and right result if the operand is not a number.
2872 static void LoadComparisonOperandSSE2(MacroAssembler* masm_,
2873 Result* operand,
2874 XMMRegister reg,
2875 Result* left_side,
2876 Result* right_side,
2877 JumpTarget* not_numbers) {
2878 Label done;
2879 if (operand->number_info().IsHeapNumber()) {
2880 // Operand is known to be a heap number, just load it.
2881 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2882 } else if (operand->number_info().IsSmi()) {
2883 // Operand is known to be a smi. Convert it to double and keep the original
2884 // smi.
2885 __ SmiUntag(operand->reg());
2886 __ cvtsi2sd(reg, Operand(operand->reg()));
2887 __ SmiTag(left_side->reg());
2888 } else {
2889 // Operand type not known, check for smi or heap number.
2890 Label smi;
2891 __ test(operand->reg(), Immediate(kSmiTagMask));
2892 __ j(zero, &smi);
2893 if (!operand->number_info().IsNumber()) {
2894 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
2895 Immediate(Factory::heap_number_map()));
2896 not_numbers->Branch(not_equal, left_side, right_side, taken);
2897 }
2898 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2899 __ jmp(&done);
2900
2901 __ bind(&smi);
2902 // Comvert smi to float and keep the original smi.
2903 __ SmiUntag(operand->reg());
2904 __ cvtsi2sd(reg, Operand(operand->reg()));
2905 __ SmiTag(operand->reg());
2906 __ jmp(&done);
2907 }
2908 __ bind(&done);
2909 }
2910
2911
2912 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
2913 Result* right_side,
2914 Condition cc,
2915 ControlDestination* dest) {
2916 ASSERT(left_side->is_register());
2917 ASSERT(right_side->is_register());
2918
2919 JumpTarget not_numbers;
2920 if (CpuFeatures::IsSupported(SSE2)) {
2921 CpuFeatures::Scope use_sse2(SSE2);
2922
2923 // Load left and right operand into registers xmm0 and xmm1 and compare.
2924 LoadComparisonOperandSSE2(masm_, left_side, xmm0, left_side, right_side,
2925 &not_numbers);
2926 LoadComparisonOperandSSE2(masm_, right_side, xmm1, left_side, right_side,
2927 &not_numbers);
2928 __ comisd(xmm0, xmm1);
2929 } else {
2930 Label check_right, compare;
2931
2932 // Make sure that both comparison operands are numbers.
2933 CheckComparisonOperand(masm_, left_side, left_side, right_side,
2934 &not_numbers);
2935 CheckComparisonOperand(masm_, right_side, left_side, right_side,
2936 &not_numbers);
2937
2938 // Load right and left operand to FPU stack and compare.
2939 LoadComparisonOperand(masm_, right_side, left_side, right_side);
2940 LoadComparisonOperand(masm_, left_side, left_side, right_side);
2941 __ FCmp();
2942 }
2943
2944 // Bail out if a NaN is involved.
2945 not_numbers.Branch(parity_even, left_side, right_side, not_taken);
2946
2947 // Split to destination targets based on comparison.
2948 left_side->Unuse();
2949 right_side->Unuse();
2950 dest->true_target()->Branch(DoubleCondition(cc));
2951 dest->false_target()->Jump();
2952
2953 not_numbers.Bind(left_side, right_side);
2954 }
2955
2956
2755 // Call the function just below TOS on the stack with the given 2957 // Call the function just below TOS on the stack with the given
2756 // arguments. The receiver is the TOS. 2958 // arguments. The receiver is the TOS.
2757 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 2959 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
2758 CallFunctionFlags flags, 2960 CallFunctionFlags flags,
2759 int position) { 2961 int position) {
2760 // Push the arguments ("left-to-right") on the stack. 2962 // Push the arguments ("left-to-right") on the stack.
2761 int arg_count = args->length(); 2963 int arg_count = args->length();
2762 for (int i = 0; i < arg_count; i++) { 2964 for (int i = 0; i < arg_count; i++) {
2763 Load(args->at(i)); 2965 Load(args->at(i));
2764 } 2966 }
(...skipping 8049 matching lines...) Expand 10 before | Expand all | Expand 10 after
10814 } 11016 }
10815 __ bind(&slow); 11017 __ bind(&slow);
10816 } 11018 }
10817 11019
10818 // Push arguments below the return address. 11020 // Push arguments below the return address.
10819 __ pop(ecx); 11021 __ pop(ecx);
10820 __ push(eax); 11022 __ push(eax);
10821 __ push(edx); 11023 __ push(edx);
10822 __ push(ecx); 11024 __ push(ecx);
10823 11025
10824 // Inlined floating point compare. 11026 // Generate the number comparison code.
10825 // Call builtin if operands are not floating point or smi. 11027 if (include_number_compare_) {
10826 Label check_for_symbols; 11028 Label non_number_comparison;
10827 Label unordered; 11029 Label unordered;
10828 if (CpuFeatures::IsSupported(SSE2)) { 11030 if (CpuFeatures::IsSupported(SSE2)) {
10829 CpuFeatures::Scope use_sse2(SSE2); 11031 CpuFeatures::Scope use_sse2(SSE2);
10830 CpuFeatures::Scope use_cmov(CMOV); 11032 CpuFeatures::Scope use_cmov(CMOV);
10831 11033
10832 FloatingPointHelper::LoadSSE2Operands(masm, &check_for_symbols); 11034 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
10833 __ comisd(xmm0, xmm1); 11035 __ comisd(xmm0, xmm1);
10834 11036
10835 // Jump to builtin for NaN. 11037 // Don't base result on EFLAGS when a NaN is involved.
10836 __ j(parity_even, &unordered, not_taken); 11038 __ j(parity_even, &unordered, not_taken);
10837 __ mov(eax, 0); // equal 11039 // Return a result of -1, 0, or 1, based on EFLAGS.
10838 __ mov(ecx, Immediate(Smi::FromInt(1))); 11040 __ mov(eax, 0); // equal
10839 __ cmov(above, eax, Operand(ecx)); 11041 __ mov(ecx, Immediate(Smi::FromInt(1)));
10840 __ mov(ecx, Immediate(Smi::FromInt(-1))); 11042 __ cmov(above, eax, Operand(ecx));
10841 __ cmov(below, eax, Operand(ecx)); 11043 __ mov(ecx, Immediate(Smi::FromInt(-1)));
10842 __ ret(2 * kPointerSize); 11044 __ cmov(below, eax, Operand(ecx));
10843 } else { 11045 __ ret(2 * kPointerSize);
10844 FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols, ebx); 11046 } else {
10845 FloatingPointHelper::LoadFloatOperands(masm, ecx); 11047 FloatingPointHelper::CheckFloatOperands(
10846 __ FCmp(); 11048 masm, &non_number_comparison, ebx);
11049 FloatingPointHelper::LoadFloatOperands(masm, ecx);
11050 __ FCmp();
10847 11051
10848 // Jump to builtin for NaN. 11052 // Don't base result on EFLAGS when a NaN is involved.
10849 __ j(parity_even, &unordered, not_taken); 11053 __ j(parity_even, &unordered, not_taken);
10850 11054
10851 Label below_lbl, above_lbl; 11055 Label below_label, above_label;
10852 // Return a result of -1, 0, or 1, to indicate result of comparison. 11056 // Return a result of -1, 0, or 1, based on EFLAGS. In all cases remove
10853 __ j(below, &below_lbl, not_taken); 11057 // two arguments from the stack as they have been pushed in preparation
10854 __ j(above, &above_lbl, not_taken); 11058 // of a possible runtime call.
11059 __ j(below, &below_label, not_taken);
11060 __ j(above, &above_label, not_taken);
10855 11061
10856 __ xor_(eax, Operand(eax)); // equal 11062 __ xor_(eax, Operand(eax));
10857 // Both arguments were pushed in case a runtime call was needed. 11063 __ ret(2 * kPointerSize);
10858 __ ret(2 * kPointerSize);
10859 11064
10860 __ bind(&below_lbl); 11065 __ bind(&below_label);
10861 __ mov(eax, Immediate(Smi::FromInt(-1))); 11066 __ mov(eax, Immediate(Smi::FromInt(-1)));
10862 __ ret(2 * kPointerSize); 11067 __ ret(2 * kPointerSize);
10863 11068
10864 __ bind(&above_lbl); 11069 __ bind(&above_label);
10865 __ mov(eax, Immediate(Smi::FromInt(1))); 11070 __ mov(eax, Immediate(Smi::FromInt(1)));
11071 __ ret(2 * kPointerSize);
11072 }
11073
11074 // If one of the numbers was NaN, then the result is always false.
11075 // The cc is never not-equal.
11076 __ bind(&unordered);
11077 ASSERT(cc_ != not_equal);
11078 if (cc_ == less || cc_ == less_equal) {
11079 __ mov(eax, Immediate(Smi::FromInt(1)));
11080 } else {
11081 __ mov(eax, Immediate(Smi::FromInt(-1)));
11082 }
10866 __ ret(2 * kPointerSize); // eax, edx were pushed 11083 __ ret(2 * kPointerSize); // eax, edx were pushed
11084
11085 // The number comparison code did not provide a valid result.
11086 __ bind(&non_number_comparison);
10867 } 11087 }
10868 // If one of the numbers was NaN, then the result is always false.
10869 // The cc is never not-equal.
10870 __ bind(&unordered);
10871 ASSERT(cc_ != not_equal);
10872 if (cc_ == less || cc_ == less_equal) {
10873 __ mov(eax, Immediate(Smi::FromInt(1)));
10874 } else {
10875 __ mov(eax, Immediate(Smi::FromInt(-1)));
10876 }
10877 __ ret(2 * kPointerSize); // eax, edx were pushed
10878 11088
10879 // Fast negative check for symbol-to-symbol equality. 11089 // Fast negative check for symbol-to-symbol equality.
10880 __ bind(&check_for_symbols);
10881 Label check_for_strings; 11090 Label check_for_strings;
10882 if (cc_ == equal) { 11091 if (cc_ == equal) {
10883 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); 11092 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx);
10884 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); 11093 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx);
10885 11094
10886 // We've already checked for object identity, so if both operands 11095 // We've already checked for object identity, so if both operands
10887 // are symbols they aren't equal. Register eax already holds a 11096 // are symbols they aren't equal. Register eax already holds a
10888 // non-zero value, which indicates not equal, so just return. 11097 // non-zero value, which indicates not equal, so just return.
10889 __ ret(2 * kPointerSize); 11098 __ ret(2 * kPointerSize);
10890 } 11099 }
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
11527 } 11736 }
11528 default: return "CompareStub"; 11737 default: return "CompareStub";
11529 } 11738 }
11530 } 11739 }
11531 11740
11532 11741
11533 int CompareStub::MinorKey() { 11742 int CompareStub::MinorKey() {
11534 // Encode the three parameters in a unique 16 bit value. To avoid duplicate 11743 // Encode the three parameters in a unique 16 bit value. To avoid duplicate
11535 // stubs the never NaN NaN condition is only taken into account if the 11744 // stubs the never NaN NaN condition is only taken into account if the
11536 // condition is equals. 11745 // condition is equals.
11537 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); 11746 ASSERT(static_cast<unsigned>(cc_) < (1 << 13));
11538 return ConditionField::encode(static_cast<unsigned>(cc_)) 11747 return ConditionField::encode(static_cast<unsigned>(cc_))
11539 | StrictField::encode(strict_) 11748 | StrictField::encode(strict_)
11540 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false); 11749 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
11750 | IncludeNumberCompareField::encode(include_number_compare_);
11541 } 11751 }
11542 11752
11543 11753
11544 void StringAddStub::Generate(MacroAssembler* masm) { 11754 void StringAddStub::Generate(MacroAssembler* masm) {
11545 Label string_add_runtime; 11755 Label string_add_runtime;
11546 11756
11547 // Load the two arguments. 11757 // Load the two arguments.
11548 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. 11758 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument.
11549 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. 11759 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument.
11550 11760
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after
12164 12374
12165 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 12375 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
12166 Register left, 12376 Register left,
12167 Register right, 12377 Register right,
12168 Register scratch1, 12378 Register scratch1,
12169 Register scratch2, 12379 Register scratch2,
12170 Register scratch3) { 12380 Register scratch3) {
12171 Label result_not_equal; 12381 Label result_not_equal;
12172 Label result_greater; 12382 Label result_greater;
12173 Label compare_lengths; 12383 Label compare_lengths;
12384
12385 __ IncrementCounter(&Counters::string_compare_native, 1);
12386
12174 // Find minimum length. 12387 // Find minimum length.
12175 Label left_shorter; 12388 Label left_shorter;
12176 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); 12389 __ mov(scratch1, FieldOperand(left, String::kLengthOffset));
12177 __ mov(scratch3, scratch1); 12390 __ mov(scratch3, scratch1);
12178 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); 12391 __ sub(scratch3, FieldOperand(right, String::kLengthOffset));
12179 12392
12180 Register length_delta = scratch3; 12393 Register length_delta = scratch3;
12181 12394
12182 __ j(less_equal, &left_shorter); 12395 __ j(less_equal, &left_shorter);
12183 // Right string is shorter. Change scratch1 to be length of right string. 12396 // Right string is shorter. Change scratch1 to be length of right string.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
12261 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 12474 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
12262 __ IncrementCounter(&Counters::string_compare_native, 1); 12475 __ IncrementCounter(&Counters::string_compare_native, 1);
12263 __ ret(2 * kPointerSize); 12476 __ ret(2 * kPointerSize);
12264 12477
12265 __ bind(&not_same); 12478 __ bind(&not_same);
12266 12479
12267 // Check that both objects are sequential ascii strings. 12480 // Check that both objects are sequential ascii strings.
12268 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); 12481 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime);
12269 12482
12270 // Compare flat ascii strings. 12483 // Compare flat ascii strings.
12271 __ IncrementCounter(&Counters::string_compare_native, 1);
12272 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); 12484 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi);
12273 12485
12274 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 12486 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12275 // tagged as a small integer. 12487 // tagged as a small integer.
12276 __ bind(&runtime); 12488 __ bind(&runtime);
12277 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 12489 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12278 } 12490 }
12279 12491
12280 #undef __ 12492 #undef __
12281 12493
12282 } } // namespace v8::internal 12494 } } // 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