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

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

Issue 3023001: Remove unnecessary formatting differences between ia32 and x64 code generator... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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 | « no previous file | src/x64/codegen-x64.cc » ('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 16 matching lines...) Expand all
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #if defined(V8_TARGET_ARCH_IA32) 30 #if defined(V8_TARGET_ARCH_IA32)
31 31
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "codegen-inl.h" 33 #include "codegen-inl.h"
34 #include "compiler.h" 34 #include "compiler.h"
35 #include "debug.h" 35 #include "debug.h"
36 #include "ic-inl.h" 36 #include "ic-inl.h"
37 #include "jsregexp.h"
38 #include "parser.h" 37 #include "parser.h"
39 #include "regexp-macro-assembler.h" 38 #include "regexp-macro-assembler.h"
40 #include "regexp-stack.h"
41 #include "register-allocator-inl.h" 39 #include "register-allocator-inl.h"
42 #include "runtime.h"
43 #include "scopes.h" 40 #include "scopes.h"
44 #include "virtual-frame-inl.h" 41 #include "virtual-frame-inl.h"
45 42
46 namespace v8 { 43 namespace v8 {
47 namespace internal { 44 namespace internal {
48 45
49 #define __ ACCESS_MASM(masm) 46 #define __ ACCESS_MASM(masm)
50 47
51 // ------------------------------------------------------------------------- 48 // -------------------------------------------------------------------------
52 // Platform-specific FrameRegisterState functions. 49 // Platform-specific FrameRegisterState functions.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 } 133 }
137 134
138 135
139 CodeGenState::~CodeGenState() { 136 CodeGenState::~CodeGenState() {
140 ASSERT(owner_->state() == this); 137 ASSERT(owner_->state() == this);
141 owner_->set_state(previous_); 138 owner_->set_state(previous_);
142 } 139 }
143 140
144 141
145 // ------------------------------------------------------------------------- 142 // -------------------------------------------------------------------------
146 // CodeGenerator implementation 143 // CodeGenerator implementation.
147 144
148 CodeGenerator::CodeGenerator(MacroAssembler* masm) 145 CodeGenerator::CodeGenerator(MacroAssembler* masm)
149 : deferred_(8), 146 : deferred_(8),
150 masm_(masm), 147 masm_(masm),
151 info_(NULL), 148 info_(NULL),
152 frame_(NULL), 149 frame_(NULL),
153 allocator_(NULL), 150 allocator_(NULL),
154 state_(NULL), 151 state_(NULL),
155 loop_nesting_(0), 152 loop_nesting_(0),
156 in_safe_int32_mode_(false), 153 in_safe_int32_mode_(false),
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 // compile an artificial return statement just above, and (b) there 364 // compile an artificial return statement just above, and (b) there
368 // are return statements in the body but (c) they are all shadowed. 365 // are return statements in the body but (c) they are all shadowed.
369 Result return_value; 366 Result return_value;
370 function_return_.Bind(&return_value); 367 function_return_.Bind(&return_value);
371 GenerateReturnSequence(&return_value); 368 GenerateReturnSequence(&return_value);
372 } 369 }
373 } 370 }
374 } 371 }
375 372
376 // Adjust for function-level loop nesting. 373 // Adjust for function-level loop nesting.
377 ASSERT_EQ(info->loop_nesting(), loop_nesting_); 374 ASSERT_EQ(loop_nesting_, info->loop_nesting());
378 loop_nesting_ = 0; 375 loop_nesting_ = 0;
379 376
380 // Code generation state must be reset. 377 // Code generation state must be reset.
381 ASSERT(state_ == NULL); 378 ASSERT(state_ == NULL);
382 ASSERT(loop_nesting() == 0);
383 ASSERT(!function_return_is_shadowed_); 379 ASSERT(!function_return_is_shadowed_);
384 function_return_.Unuse(); 380 function_return_.Unuse();
385 DeleteFrame(); 381 DeleteFrame();
386 382
387 // Process any deferred code using the register allocator. 383 // Process any deferred code using the register allocator.
388 if (!HasStackOverflow()) { 384 if (!HasStackOverflow()) {
389 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); 385 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
390 JumpTarget::set_compiling_deferred_code(true); 386 JumpTarget::set_compiling_deferred_code(true);
391 ProcessDeferred(); 387 ProcessDeferred();
392 JumpTarget::set_compiling_deferred_code(false); 388 JumpTarget::set_compiling_deferred_code(false);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 done.Jump(); 635 done.Jump();
640 636
641 if (unsafe_bailout.is_linked()) { 637 if (unsafe_bailout.is_linked()) {
642 unsafe_bailout.Bind(); 638 unsafe_bailout.Bind();
643 LoadWithSafeInt32ModeDisabled(expr); 639 LoadWithSafeInt32ModeDisabled(expr);
644 } 640 }
645 done.Bind(); 641 done.Bind();
646 } else { 642 } else {
647 JumpTarget true_target; 643 JumpTarget true_target;
648 JumpTarget false_target; 644 JumpTarget false_target;
649
650 ControlDestination dest(&true_target, &false_target, true); 645 ControlDestination dest(&true_target, &false_target, true);
651 LoadCondition(expr, &dest, false); 646 LoadCondition(expr, &dest, false);
652 647
653 if (dest.false_was_fall_through()) { 648 if (dest.false_was_fall_through()) {
654 // The false target was just bound. 649 // The false target was just bound.
655 JumpTarget loaded; 650 JumpTarget loaded;
656 frame_->Push(Factory::false_value()); 651 frame_->Push(Factory::false_value());
657 // There may be dangling jumps to the true target. 652 // There may be dangling jumps to the true target.
658 if (true_target.is_linked()) { 653 if (true_target.is_linked()) {
659 loaded.Jump(); 654 loaded.Jump();
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 frame_->Push(&result); 772 frame_->Push(&result);
778 } 773 }
779 774
780 Variable* arguments = scope()->arguments()->var(); 775 Variable* arguments = scope()->arguments()->var();
781 Variable* shadow = scope()->arguments_shadow()->var(); 776 Variable* shadow = scope()->arguments_shadow()->var();
782 ASSERT(arguments != NULL && arguments->slot() != NULL); 777 ASSERT(arguments != NULL && arguments->slot() != NULL);
783 ASSERT(shadow != NULL && shadow->slot() != NULL); 778 ASSERT(shadow != NULL && shadow->slot() != NULL);
784 JumpTarget done; 779 JumpTarget done;
785 bool skip_arguments = false; 780 bool skip_arguments = false;
786 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) { 781 if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
787 // We have to skip storing into the arguments slot if it has already 782 // We have to skip storing into the arguments slot if it has
788 // been written to. This can happen if the a function has a local 783 // already been written to. This can happen if the a function
789 // variable named 'arguments'. 784 // has a local variable named 'arguments'.
790 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF); 785 LoadFromSlot(arguments->slot(), NOT_INSIDE_TYPEOF);
791 Result probe = frame_->Pop(); 786 Result probe = frame_->Pop();
792 if (probe.is_constant()) { 787 if (probe.is_constant()) {
793 // We have to skip updating the arguments object if it has 788 // We have to skip updating the arguments object if it has
794 // been assigned a proper value. 789 // been assigned a proper value.
795 skip_arguments = !probe.handle()->IsTheHole(); 790 skip_arguments = !probe.handle()->IsTheHole();
796 } else { 791 } else {
797 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value())); 792 __ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value()));
798 probe.Unuse(); 793 probe.Unuse();
799 done.Branch(not_equal); 794 done.Branch(not_equal);
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 unsigned int unsigned_left = left; 1422 unsigned int unsigned_left = left;
1428 if (left < 0) { 1423 if (left < 0) {
1429 // Perform arithmetic shift of a negative number by 1424 // Perform arithmetic shift of a negative number by
1430 // complementing number, logical shifting, complementing again. 1425 // complementing number, logical shifting, complementing again.
1431 unsigned_left = ~unsigned_left; 1426 unsigned_left = ~unsigned_left;
1432 unsigned_left >>= shift_amount; 1427 unsigned_left >>= shift_amount;
1433 unsigned_left = ~unsigned_left; 1428 unsigned_left = ~unsigned_left;
1434 } else { 1429 } else {
1435 unsigned_left >>= shift_amount; 1430 unsigned_left >>= shift_amount;
1436 } 1431 }
1437 ASSERT(Smi::IsValid(unsigned_left)); // Converted to signed. 1432 ASSERT(Smi::IsValid(static_cast<int32_t>(unsigned_left)));
1438 answer_object = Smi::FromInt(unsigned_left); // Converted to signed. 1433 answer_object = Smi::FromInt(static_cast<int32_t>(unsigned_left));
1439 break; 1434 break;
1440 } 1435 }
1441 default: 1436 default:
1442 UNREACHABLE(); 1437 UNREACHABLE();
1443 break; 1438 break;
1444 } 1439 }
1445 if (answer_object == Heap::undefined_value()) { 1440 if (answer_object == Heap::undefined_value()) {
1446 return false; 1441 return false;
1447 } 1442 }
1448 frame_->Push(Handle<Object>(answer_object)); 1443 frame_->Push(Handle<Object>(answer_object));
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 Token::Value op_; 1907 Token::Value op_;
1913 Register dst_; 1908 Register dst_;
1914 TypeInfo type_info_; 1909 TypeInfo type_info_;
1915 Smi* value_; 1910 Smi* value_;
1916 Register src_; 1911 Register src_;
1917 OverwriteMode overwrite_mode_; 1912 OverwriteMode overwrite_mode_;
1918 }; 1913 };
1919 1914
1920 1915
1921 void DeferredInlineSmiOperationReversed::Generate() { 1916 void DeferredInlineSmiOperationReversed::Generate() {
1922 GenericBinaryOpStub igostub( 1917 GenericBinaryOpStub stub(
1923 op_, 1918 op_,
1924 overwrite_mode_, 1919 overwrite_mode_,
1925 NO_SMI_CODE_IN_STUB, 1920 NO_SMI_CODE_IN_STUB,
1926 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); 1921 TypeInfo::Combine(TypeInfo::Smi(), type_info_));
1927 igostub.GenerateCall(masm_, value_, src_); 1922 stub.GenerateCall(masm_, value_, src_);
1928 if (!dst_.is(eax)) __ mov(dst_, eax); 1923 if (!dst_.is(eax)) __ mov(dst_, eax);
1929 } 1924 }
1930 1925
1931 1926
1932 // The result of src + value is in dst. It either overflowed or was not 1927 // The result of src + value is in dst. It either overflowed or was not
1933 // smi tagged. Undo the speculative addition and call the appropriate 1928 // smi tagged. Undo the speculative addition and call the appropriate
1934 // specialized stub for add. The result is left in dst. 1929 // specialized stub for add. The result is left in dst.
1935 class DeferredInlineSmiAdd: public DeferredCode { 1930 class DeferredInlineSmiAdd: public DeferredCode {
1936 public: 1931 public:
1937 DeferredInlineSmiAdd(Register dst, 1932 DeferredInlineSmiAdd(Register dst,
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
2417 if (int_value == 1) { 2412 if (int_value == 1) {
2418 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); 2413 __ mov(operand->reg(), Immediate(Smi::FromInt(0)));
2419 } else { 2414 } else {
2420 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); 2415 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
2421 } 2416 }
2422 deferred->BindExit(); 2417 deferred->BindExit();
2423 answer = *operand; 2418 answer = *operand;
2424 break; 2419 break;
2425 } 2420 }
2426 // Fall through if we did not find a power of 2 on the right hand side! 2421 // Fall through if we did not find a power of 2 on the right hand side!
2422 // The next case must be the default.
2427 2423
2428 default: { 2424 default: {
2429 Result constant_operand(value); 2425 Result constant_operand(value);
2430 if (reversed) { 2426 if (reversed) {
2431 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, 2427 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand,
2432 overwrite_mode); 2428 overwrite_mode);
2433 } else { 2429 } else {
2434 answer = LikelySmiBinaryOperation(expr, operand, &constant_operand, 2430 answer = LikelySmiBinaryOperation(expr, operand, &constant_operand,
2435 overwrite_mode); 2431 overwrite_mode);
2436 } 2432 }
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
2669 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset), 2665 __ cmp(FieldOperand(left_side.reg(), String::kLengthOffset),
2670 Immediate(Smi::FromInt(1))); 2666 Immediate(Smi::FromInt(1)));
2671 } 2667 }
2672 __ bind(&comparison_done); 2668 __ bind(&comparison_done);
2673 left_side.Unuse(); 2669 left_side.Unuse();
2674 right_side.Unuse(); 2670 right_side.Unuse();
2675 dest->Split(cc); 2671 dest->Split(cc);
2676 } 2672 }
2677 } else { 2673 } else {
2678 // Neither side is a constant Smi, constant 1-char string or constant null. 2674 // Neither side is a constant Smi, constant 1-char string or constant null.
2679 // If either side is a non-smi constant, or known to be a heap number skip 2675 // If either side is a non-smi constant, or known to be a heap number,
2680 // the smi check. 2676 // skip the smi check.
2681 bool known_non_smi = 2677 bool known_non_smi =
2682 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 2678 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
2683 (right_side.is_constant() && !right_side.handle()->IsSmi()) || 2679 (right_side.is_constant() && !right_side.handle()->IsSmi()) ||
2684 left_side.type_info().IsDouble() || 2680 left_side.type_info().IsDouble() ||
2685 right_side.type_info().IsDouble(); 2681 right_side.type_info().IsDouble();
2682
2686 NaNInformation nan_info = 2683 NaNInformation nan_info =
2687 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ? 2684 (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ?
2688 kBothCouldBeNaN : 2685 kBothCouldBeNaN :
2689 kCantBothBeNaN; 2686 kCantBothBeNaN;
2690 2687
2691 // Inline number comparison handling any combination of smi's and heap 2688 // Inline number comparison handling any combination of smi's and heap
2692 // numbers if: 2689 // numbers if:
2693 // code is in a loop 2690 // code is in a loop
2694 // the compare operation is different from equal 2691 // the compare operation is different from equal
2695 // compare is not a for-loop comparison 2692 // compare is not a for-loop comparison
2696 // The reason for excluding equal is that it will most likely be done 2693 // The reason for excluding equal is that it will most likely be done
2697 // with smi's (not heap numbers) and the code to comparing smi's is inlined 2694 // with smi's (not heap numbers) and the code to comparing smi's is inlined
2698 // separately. The same reason applies for for-loop comparison which will 2695 // separately. The same reason applies for for-loop comparison which will
2699 // also most likely be smi comparisons. 2696 // also most likely be smi comparisons.
2700 bool is_loop_condition = (node->AsExpression() != NULL) 2697 bool is_loop_condition = (node->AsExpression() != NULL)
2701 && node->AsExpression()->is_loop_condition(); 2698 && node->AsExpression()->is_loop_condition();
2702 bool inline_number_compare = 2699 bool inline_number_compare =
2703 loop_nesting() > 0 && cc != equal && !is_loop_condition; 2700 loop_nesting() > 0 && cc != equal && !is_loop_condition;
2704 2701
2705 // Left and right needed in registers for the following code. 2702 // Left and right needed in registers for the following code.
2706 left_side.ToRegister(); 2703 left_side.ToRegister();
2707 right_side.ToRegister(); 2704 right_side.ToRegister();
2708 2705
2709 if (known_non_smi) { 2706 if (known_non_smi) {
2710 // Inline the equality check if both operands can't be a NaN. If both 2707 // Inlined equality check:
2711 // objects are the same they are equal. 2708 // If at least one of the objects is not NaN, then if the objects
2709 // are identical, they are equal.
2712 if (nan_info == kCantBothBeNaN && cc == equal) { 2710 if (nan_info == kCantBothBeNaN && cc == equal) {
2713 __ cmp(left_side.reg(), Operand(right_side.reg())); 2711 __ cmp(left_side.reg(), Operand(right_side.reg()));
2714 dest->true_target()->Branch(equal); 2712 dest->true_target()->Branch(equal);
2715 } 2713 }
2716 2714
2717 // Inline number comparison. 2715 // Inlined number comparison:
2718 if (inline_number_compare) { 2716 if (inline_number_compare) {
2719 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); 2717 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2720 } 2718 }
2721 2719
2722 // End of in-line compare, call out to the compare stub. Don't include 2720 // End of in-line compare, call out to the compare stub. Don't include
2723 // number comparison in the stub if it was inlined. 2721 // number comparison in the stub if it was inlined.
2724 CompareStub stub(cc, strict, nan_info, !inline_number_compare); 2722 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2725 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2723 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2726 __ test(answer.reg(), Operand(answer.reg())); 2724 __ test(answer.reg(), Operand(answer.reg()));
2727 answer.Unuse(); 2725 answer.Unuse();
(...skipping 17 matching lines...) Expand all
2745 temp.Unuse(); 2743 temp.Unuse();
2746 is_smi.Branch(zero, taken); 2744 is_smi.Branch(zero, taken);
2747 2745
2748 // Inline the equality check if both operands can't be a NaN. If both 2746 // Inline the equality check if both operands can't be a NaN. If both
2749 // objects are the same they are equal. 2747 // objects are the same they are equal.
2750 if (nan_info == kCantBothBeNaN && cc == equal) { 2748 if (nan_info == kCantBothBeNaN && cc == equal) {
2751 __ cmp(left_side.reg(), Operand(right_side.reg())); 2749 __ cmp(left_side.reg(), Operand(right_side.reg()));
2752 dest->true_target()->Branch(equal); 2750 dest->true_target()->Branch(equal);
2753 } 2751 }
2754 2752
2755 // Inline number comparison. 2753 // Inlined number comparison:
2756 if (inline_number_compare) { 2754 if (inline_number_compare) {
2757 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest); 2755 GenerateInlineNumberComparison(&left_side, &right_side, cc, dest);
2758 } 2756 }
2759 2757
2760 // End of in-line compare, call out to the compare stub. Don't include 2758 // End of in-line compare, call out to the compare stub. Don't include
2761 // number comparison in the stub if it was inlined. 2759 // number comparison in the stub if it was inlined.
2762 CompareStub stub(cc, strict, nan_info, !inline_number_compare); 2760 CompareStub stub(cc, strict, nan_info, !inline_number_compare);
2763 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 2761 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
2764 __ test(answer.reg(), Operand(answer.reg())); 2762 __ test(answer.reg(), Operand(answer.reg()));
2765 answer.Unuse(); 2763 answer.Unuse();
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2963 __ jmp(&done); 2961 __ jmp(&done);
2964 } 2962 }
2965 __ bind(&done); 2963 __ bind(&done);
2966 } 2964 }
2967 2965
2968 2966
2969 // Load a comparison operand into into a XMM register. Jump to not_numbers jump 2967 // Load a comparison operand into into a XMM register. Jump to not_numbers jump
2970 // target passing the left and right result if the operand is not a number. 2968 // target passing the left and right result if the operand is not a number.
2971 static void LoadComparisonOperandSSE2(MacroAssembler* masm_, 2969 static void LoadComparisonOperandSSE2(MacroAssembler* masm_,
2972 Result* operand, 2970 Result* operand,
2973 XMMRegister reg, 2971 XMMRegister xmm_reg,
2974 Result* left_side, 2972 Result* left_side,
2975 Result* right_side, 2973 Result* right_side,
2976 JumpTarget* not_numbers) { 2974 JumpTarget* not_numbers) {
2977 Label done; 2975 Label done;
2978 if (operand->type_info().IsDouble()) { 2976 if (operand->type_info().IsDouble()) {
2979 // Operand is known to be a heap number, just load it. 2977 // Operand is known to be a heap number, just load it.
2980 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset)); 2978 __ movdbl(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2981 } else if (operand->type_info().IsSmi()) { 2979 } else if (operand->type_info().IsSmi()) {
2982 // Operand is known to be a smi. Convert it to double and keep the original 2980 // Operand is known to be a smi. Convert it to double and keep the original
2983 // smi. 2981 // smi.
2984 __ SmiUntag(operand->reg()); 2982 __ SmiUntag(operand->reg());
2985 __ cvtsi2sd(reg, Operand(operand->reg())); 2983 __ cvtsi2sd(xmm_reg, Operand(operand->reg()));
2986 __ SmiTag(operand->reg()); 2984 __ SmiTag(operand->reg());
2987 } else { 2985 } else {
2988 // Operand type not known, check for smi or heap number. 2986 // Operand type not known, check for smi or heap number.
2989 Label smi; 2987 Label smi;
2990 __ test(operand->reg(), Immediate(kSmiTagMask)); 2988 __ test(operand->reg(), Immediate(kSmiTagMask));
2991 __ j(zero, &smi); 2989 __ j(zero, &smi);
2992 if (!operand->type_info().IsNumber()) { 2990 if (!operand->type_info().IsNumber()) {
2993 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset), 2991 __ cmp(FieldOperand(operand->reg(), HeapObject::kMapOffset),
2994 Immediate(Factory::heap_number_map())); 2992 Immediate(Factory::heap_number_map()));
2995 not_numbers->Branch(not_equal, left_side, right_side, taken); 2993 not_numbers->Branch(not_equal, left_side, right_side, taken);
2996 } 2994 }
2997 __ movdbl(reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset)); 2995 __ movdbl(xmm_reg, FieldOperand(operand->reg(), HeapNumber::kValueOffset));
2998 __ jmp(&done); 2996 __ jmp(&done);
2999 2997
3000 __ bind(&smi); 2998 __ bind(&smi);
3001 // Comvert smi to float and keep the original smi. 2999 // Comvert smi to float and keep the original smi.
3002 __ SmiUntag(operand->reg()); 3000 __ SmiUntag(operand->reg());
3003 __ cvtsi2sd(reg, Operand(operand->reg())); 3001 __ cvtsi2sd(xmm_reg, Operand(operand->reg()));
3004 __ SmiTag(operand->reg()); 3002 __ SmiTag(operand->reg());
3005 __ jmp(&done); 3003 __ jmp(&done);
3006 } 3004 }
3007 __ bind(&done); 3005 __ bind(&done);
3008 } 3006 }
3009 3007
3010 3008
3011 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side, 3009 void CodeGenerator::GenerateInlineNumberComparison(Result* left_side,
3012 Result* right_side, 3010 Result* right_side,
3013 Condition cc, 3011 Condition cc,
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
3590 // reference to eax. This is safe because the current frame does not 3588 // reference to eax. This is safe because the current frame does not
3591 // contain a reference to eax (it is prepared for the return by spilling 3589 // contain a reference to eax (it is prepared for the return by spilling
3592 // all registers). 3590 // all registers).
3593 if (FLAG_trace) { 3591 if (FLAG_trace) {
3594 frame_->Push(return_value); 3592 frame_->Push(return_value);
3595 *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1); 3593 *return_value = frame_->CallRuntime(Runtime::kTraceExit, 1);
3596 } 3594 }
3597 return_value->ToRegister(eax); 3595 return_value->ToRegister(eax);
3598 3596
3599 // Add a label for checking the size of the code used for returning. 3597 // Add a label for checking the size of the code used for returning.
3598 #ifdef DEBUG
3600 Label check_exit_codesize; 3599 Label check_exit_codesize;
3601 masm_->bind(&check_exit_codesize); 3600 masm_->bind(&check_exit_codesize);
3601 #endif
3602 3602
3603 // Leave the frame and return popping the arguments and the 3603 // Leave the frame and return popping the arguments and the
3604 // receiver. 3604 // receiver.
3605 frame_->Exit(); 3605 frame_->Exit();
3606 masm_->ret((scope()->num_parameters() + 1) * kPointerSize); 3606 masm_->ret((scope()->num_parameters() + 1) * kPointerSize);
3607 DeleteFrame(); 3607 DeleteFrame();
3608 3608
3609 #ifdef ENABLE_DEBUGGER_SUPPORT 3609 #ifdef ENABLE_DEBUGGER_SUPPORT
3610 // Check that the size of the code used for returning matches what is 3610 // Check that the size of the code used for returning matches what is
3611 // expected by the debugger. 3611 // expected by the debugger.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
3712 } 3712 }
3713 // Drop the switch value. 3713 // Drop the switch value.
3714 frame_->Drop(); 3714 frame_->Drop();
3715 if (default_clause != NULL) { 3715 if (default_clause != NULL) {
3716 default_clause->body_target()->Jump(); 3716 default_clause->body_target()->Jump();
3717 } else { 3717 } else {
3718 node->break_target()->Jump(); 3718 node->break_target()->Jump();
3719 } 3719 }
3720 } 3720 }
3721 3721
3722
3723 // The last instruction emitted was a jump, either to the default 3722 // The last instruction emitted was a jump, either to the default
3724 // clause or the break target, or else to a case body from the loop 3723 // clause or the break target, or else to a case body from the loop
3725 // that compiles the tests. 3724 // that compiles the tests.
3726 ASSERT(!has_valid_frame()); 3725 ASSERT(!has_valid_frame());
3727 // Compile case bodies as needed. 3726 // Compile case bodies as needed.
3728 for (int i = 0; i < length; i++) { 3727 for (int i = 0; i < length; i++) {
3729 CaseClause* clause = cases->at(i); 3728 CaseClause* clause = cases->at(i);
3730 3729
3731 // There are two ways to reach the body: from the corresponding 3730 // There are two ways to reach the body: from the corresponding
3732 // test or as the fall through of the previous body. 3731 // test or as the fall through of the previous body.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3800 body.Bind(); 3799 body.Bind();
3801 break; 3800 break;
3802 } 3801 }
3803 3802
3804 CheckStack(); // TODO(1222600): ignore if body contains calls. 3803 CheckStack(); // TODO(1222600): ignore if body contains calls.
3805 Visit(node->body()); 3804 Visit(node->body());
3806 3805
3807 // Compile the test. 3806 // Compile the test.
3808 switch (info) { 3807 switch (info) {
3809 case ALWAYS_TRUE: 3808 case ALWAYS_TRUE:
3810 // If control flow can fall off the end of the body, jump back to 3809 // If control flow can fall off the end of the body, jump back
3811 // the top and bind the break target at the exit. 3810 // to the top and bind the break target at the exit.
3812 if (has_valid_frame()) { 3811 if (has_valid_frame()) {
3813 node->continue_target()->Jump(); 3812 node->continue_target()->Jump();
3814 } 3813 }
3815 if (node->break_target()->is_linked()) { 3814 if (node->break_target()->is_linked()) {
3816 node->break_target()->Bind(); 3815 node->break_target()->Bind();
3817 } 3816 }
3818 break; 3817 break;
3819 case ALWAYS_FALSE: 3818 case ALWAYS_FALSE:
3820 // We may have had continues or breaks in the body. 3819 // We may have had continues or breaks in the body.
3821 if (node->continue_target()->is_linked()) { 3820 if (node->continue_target()->is_linked()) {
(...skipping 15 matching lines...) Expand all
3837 ControlDestination dest(&body, node->break_target(), false); 3836 ControlDestination dest(&body, node->break_target(), false);
3838 LoadCondition(node->cond(), &dest, true); 3837 LoadCondition(node->cond(), &dest, true);
3839 } 3838 }
3840 if (node->break_target()->is_linked()) { 3839 if (node->break_target()->is_linked()) {
3841 node->break_target()->Bind(); 3840 node->break_target()->Bind();
3842 } 3841 }
3843 break; 3842 break;
3844 } 3843 }
3845 3844
3846 DecrementLoopNesting(); 3845 DecrementLoopNesting();
3846 node->continue_target()->Unuse();
3847 node->break_target()->Unuse();
3847 } 3848 }
3848 3849
3849 3850
3850 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { 3851 void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
3851 ASSERT(!in_spilled_code()); 3852 ASSERT(!in_spilled_code());
3852 Comment cmnt(masm_, "[ WhileStatement"); 3853 Comment cmnt(masm_, "[ WhileStatement");
3853 CodeForStatementPosition(node); 3854 CodeForStatementPosition(node);
3854 3855
3855 // If the condition is always false and has no side effects, we do not 3856 // If the condition is always false and has no side effects, we do not
3856 // need to compile anything. 3857 // need to compile anything.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3921 // necessary. 3922 // necessary.
3922 switch (info) { 3923 switch (info) {
3923 case ALWAYS_TRUE: 3924 case ALWAYS_TRUE:
3924 // The loop body has been labeled with the continue target. 3925 // The loop body has been labeled with the continue target.
3925 if (has_valid_frame()) { 3926 if (has_valid_frame()) {
3926 node->continue_target()->Jump(); 3927 node->continue_target()->Jump();
3927 } 3928 }
3928 break; 3929 break;
3929 case DONT_KNOW: 3930 case DONT_KNOW:
3930 if (test_at_bottom) { 3931 if (test_at_bottom) {
3931 // If we have chosen to recompile the test at the bottom, then 3932 // If we have chosen to recompile the test at the bottom,
3932 // it is the continue target. 3933 // then it is the continue target.
3933 if (node->continue_target()->is_linked()) { 3934 if (node->continue_target()->is_linked()) {
3934 node->continue_target()->Bind(); 3935 node->continue_target()->Bind();
3935 } 3936 }
3936 if (has_valid_frame()) { 3937 if (has_valid_frame()) {
3937 // The break target is the fall-through (body is a backward 3938 // The break target is the fall-through (body is a backward
3938 // jump from here and thus an invalid fall-through). 3939 // jump from here and thus an invalid fall-through).
3939 ControlDestination dest(&body, node->break_target(), false); 3940 ControlDestination dest(&body, node->break_target(), false);
3940 LoadCondition(node->cond(), &dest, true); 3941 LoadCondition(node->cond(), &dest, true);
3941 } 3942 }
3942 } else { 3943 } else {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
4038 // We are not recompiling the test at the bottom and there is no 4039 // We are not recompiling the test at the bottom and there is no
4039 // update expression. 4040 // update expression.
4040 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL); 4041 node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
4041 node->continue_target()->Bind(); 4042 node->continue_target()->Bind();
4042 } else { 4043 } else {
4043 // We are not recompiling the test at the bottom and there is an 4044 // We are not recompiling the test at the bottom and there is an
4044 // update expression. 4045 // update expression.
4045 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 4046 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
4046 loop.Bind(); 4047 loop.Bind();
4047 } 4048 }
4049
4048 // Compile the test with the body as the true target and preferred 4050 // Compile the test with the body as the true target and preferred
4049 // fall-through and with the break target as the false target. 4051 // fall-through and with the break target as the false target.
4050 ControlDestination dest(&body, node->break_target(), true); 4052 ControlDestination dest(&body, node->break_target(), true);
4051 LoadCondition(node->cond(), &dest, true); 4053 LoadCondition(node->cond(), &dest, true);
4052 4054
4053 if (dest.false_was_fall_through()) { 4055 if (dest.false_was_fall_through()) {
4054 // If we got the break target as fall-through, the test may have 4056 // If we got the break target as fall-through, the test may have
4055 // been unconditionally false (if there are no jumps to the 4057 // been unconditionally false (if there are no jumps to the
4056 // body). 4058 // body).
4057 if (!body.is_linked()) { 4059 if (!body.is_linked()) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
4147 loop.Jump(); 4149 loop.Jump();
4148 } 4150 }
4149 } 4151 }
4150 } 4152 }
4151 break; 4153 break;
4152 case ALWAYS_FALSE: 4154 case ALWAYS_FALSE:
4153 UNREACHABLE(); 4155 UNREACHABLE();
4154 break; 4156 break;
4155 } 4157 }
4156 4158
4157 // The break target may be already bound (by the condition), or 4159 // The break target may be already bound (by the condition), or there
4158 // there may not be a valid frame. Bind it only if needed. 4160 // may not be a valid frame. Bind it only if needed.
4159 if (node->break_target()->is_linked()) { 4161 if (node->break_target()->is_linked()) {
4160 node->break_target()->Bind(); 4162 node->break_target()->Bind();
4161 } 4163 }
4162 DecrementLoopNesting(); 4164 DecrementLoopNesting();
4163 } 4165 }
4164 4166
4165 4167
4166 void CodeGenerator::VisitForInStatement(ForInStatement* node) { 4168 void CodeGenerator::VisitForInStatement(ForInStatement* node) {
4167 ASSERT(!in_spilled_code()); 4169 ASSERT(!in_spilled_code());
4168 VirtualFrame::SpilledScope spilled_scope; 4170 VirtualFrame::SpilledScope spilled_scope;
(...skipping 9615 matching lines...) Expand 10 before | Expand all | Expand 10 after
13784 masm.GetCode(&desc); 13786 masm.GetCode(&desc);
13785 // Call the function from C++. 13787 // Call the function from C++.
13786 return FUNCTION_CAST<MemCopyFunction>(buffer); 13788 return FUNCTION_CAST<MemCopyFunction>(buffer);
13787 } 13789 }
13788 13790
13789 #undef __ 13791 #undef __
13790 13792
13791 } } // namespace v8::internal 13793 } } // namespace v8::internal
13792 13794
13793 #endif // V8_TARGET_ARCH_IA32 13795 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698