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

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

Issue 2084017: Version 2.2.11... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 7 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/x64/builtins-x64.cc ('k') | src/x64/cpu-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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #if defined(V8_TARGET_ARCH_X64)
31
30 #include "bootstrapper.h" 32 #include "bootstrapper.h"
31 #include "codegen-inl.h" 33 #include "codegen-inl.h"
32 #include "compiler.h" 34 #include "compiler.h"
33 #include "debug.h" 35 #include "debug.h"
34 #include "ic-inl.h" 36 #include "ic-inl.h"
35 #include "parser.h" 37 #include "parser.h"
36 #include "regexp-macro-assembler.h" 38 #include "regexp-macro-assembler.h"
37 #include "register-allocator-inl.h" 39 #include "register-allocator-inl.h"
38 #include "scopes.h" 40 #include "scopes.h"
39 #include "virtual-frame-inl.h" 41 #include "virtual-frame-inl.h"
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 private: 673 private:
672 Register value_; 674 Register value_;
673 Register key_; 675 Register key_;
674 Register receiver_; 676 Register receiver_;
675 Label patch_site_; 677 Label patch_site_;
676 }; 678 };
677 679
678 680
679 void DeferredReferenceSetKeyedValue::Generate() { 681 void DeferredReferenceSetKeyedValue::Generate() {
680 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 682 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1);
681 // Push receiver and key arguments on the stack. 683 // Move value, receiver, and key to registers rax, rdx, and rcx, as
682 __ push(receiver_); 684 // the IC stub expects.
683 __ push(key_); 685 // Move value to rax, using xchg if the receiver or key is in rax.
684 // Move value argument to eax as expected by the IC stub. 686 if (!value_.is(rax)) {
685 if (!value_.is(rax)) __ movq(rax, value_); 687 if (!receiver_.is(rax) && !key_.is(rax)) {
688 __ movq(rax, value_);
689 } else {
690 __ xchg(rax, value_);
691 // Update receiver_ and key_ if they are affected by the swap.
692 if (receiver_.is(rax)) {
693 receiver_ = value_;
694 } else if (receiver_.is(value_)) {
695 receiver_ = rax;
696 }
697 if (key_.is(rax)) {
698 key_ = value_;
699 } else if (key_.is(value_)) {
700 key_ = rax;
701 }
702 }
703 }
704 // Value is now in rax. Its original location is remembered in value_,
705 // and the value is restored to value_ before returning.
706 // The variables receiver_ and key_ are not preserved.
707 // Move receiver and key to rdx and rcx, swapping if necessary.
708 if (receiver_.is(rdx)) {
709 if (!key_.is(rcx)) {
710 __ movq(rcx, key_);
711 } // Else everything is already in the right place.
712 } else if (receiver_.is(rcx)) {
713 if (key_.is(rdx)) {
714 __ xchg(rcx, rdx);
715 } else if (key_.is(rcx)) {
716 __ movq(rdx, receiver_);
717 } else {
718 __ movq(rdx, receiver_);
719 __ movq(rcx, key_);
720 }
721 } else if (key_.is(rcx)) {
722 __ movq(rdx, receiver_);
723 } else {
724 __ movq(rcx, key_);
725 __ movq(rdx, receiver_);
726 }
727
686 // Call the IC stub. 728 // Call the IC stub.
687 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 729 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
688 __ Call(ic, RelocInfo::CODE_TARGET); 730 __ Call(ic, RelocInfo::CODE_TARGET);
689 // The delta from the start of the map-compare instructions (initial movq) 731 // The delta from the start of the map-compare instructions (initial movq)
690 // to the test instruction. We use masm_-> directly here instead of the 732 // to the test instruction. We use masm_-> directly here instead of the
691 // __ macro because the macro sometimes uses macro expansion to turn 733 // __ macro because the macro sometimes uses macro expansion to turn
692 // into something that can't return a value. This is encountered 734 // into something that can't return a value. This is encountered
693 // when doing generated code coverage tests. 735 // when doing generated code coverage tests.
694 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 736 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
695 // Here we use masm_-> instead of the __ macro because this is the 737 // Here we use masm_-> instead of the __ macro because this is the
696 // instruction that gets patched and coverage code gets in the way. 738 // instruction that gets patched and coverage code gets in the way.
697 masm_->testl(rax, Immediate(-delta_to_patch_site)); 739 masm_->testl(rax, Immediate(-delta_to_patch_site));
698 // Restore value (returned from store IC), key and receiver 740 // Restore value (returned from store IC).
699 // registers.
700 if (!value_.is(rax)) __ movq(value_, rax); 741 if (!value_.is(rax)) __ movq(value_, rax);
701 __ pop(key_);
702 __ pop(receiver_);
703 } 742 }
704 743
705 744
706 void CodeGenerator::CallApplyLazy(Expression* applicand, 745 void CodeGenerator::CallApplyLazy(Expression* applicand,
707 Expression* receiver, 746 Expression* receiver,
708 VariableProxy* arguments, 747 VariableProxy* arguments,
709 int position) { 748 int position) {
710 // An optimized implementation of expressions of the form 749 // An optimized implementation of expressions of the form
711 // x.apply(y, arguments). 750 // x.apply(y, arguments).
712 // If the arguments object of the scope has not been allocated, 751 // If the arguments object of the scope has not been allocated,
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 frame_->SetTypeForParamAt(slot->index(), info); 1578 frame_->SetTypeForParamAt(slot->index(), info);
1540 } 1579 }
1541 if (FLAG_debug_code && info.IsSmi()) { 1580 if (FLAG_debug_code && info.IsSmi()) {
1542 if (slot->type() == Slot::LOCAL) { 1581 if (slot->type() == Slot::LOCAL) {
1543 frame_->PushLocalAt(slot->index()); 1582 frame_->PushLocalAt(slot->index());
1544 } else { 1583 } else {
1545 frame_->PushParameterAt(slot->index()); 1584 frame_->PushParameterAt(slot->index());
1546 } 1585 }
1547 Result var = frame_->Pop(); 1586 Result var = frame_->Pop();
1548 var.ToRegister(); 1587 var.ToRegister();
1549 __ AbortIfNotSmi(var.reg(), "Non-smi value in smi-typed stack slot."); 1588 __ AbortIfNotSmi(var.reg());
1550 } 1589 }
1551 } 1590 }
1552 1591
1553 1592
1554 void CodeGenerator::VisitForStatement(ForStatement* node) { 1593 void CodeGenerator::VisitForStatement(ForStatement* node) {
1555 ASSERT(!in_spilled_code()); 1594 ASSERT(!in_spilled_code());
1556 Comment cmnt(masm_, "[ ForStatement"); 1595 Comment cmnt(masm_, "[ ForStatement");
1557 CodeForStatementPosition(node); 1596 CodeForStatementPosition(node);
1558 1597
1559 // Compile the init expression if present. 1598 // Compile the init expression if present.
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after
2792 // arguments. 2831 // arguments.
2793 2832
2794 // Prepare the stack for the call to the resolved function. 2833 // Prepare the stack for the call to the resolved function.
2795 Load(function); 2834 Load(function);
2796 2835
2797 // Allocate a frame slot for the receiver. 2836 // Allocate a frame slot for the receiver.
2798 frame_->Push(Factory::undefined_value()); 2837 frame_->Push(Factory::undefined_value());
2799 int arg_count = args->length(); 2838 int arg_count = args->length();
2800 for (int i = 0; i < arg_count; i++) { 2839 for (int i = 0; i < arg_count; i++) {
2801 Load(args->at(i)); 2840 Load(args->at(i));
2841 frame_->SpillTop();
2802 } 2842 }
2803 2843
2804 // Prepare the stack for the call to ResolvePossiblyDirectEval. 2844 // Prepare the stack for the call to ResolvePossiblyDirectEval.
2805 frame_->PushElementAt(arg_count + 1); 2845 frame_->PushElementAt(arg_count + 1);
2806 if (arg_count > 0) { 2846 if (arg_count > 0) {
2807 frame_->PushElementAt(arg_count); 2847 frame_->PushElementAt(arg_count);
2808 } else { 2848 } else {
2809 frame_->Push(Factory::undefined_value()); 2849 frame_->Push(Factory::undefined_value());
2810 } 2850 }
2811 2851
(...skipping 29 matching lines...) Expand all
2841 2881
2842 // Pass the global object as the receiver and let the IC stub 2882 // Pass the global object as the receiver and let the IC stub
2843 // patch the stack to use the global proxy as 'this' in the 2883 // patch the stack to use the global proxy as 'this' in the
2844 // invoked function. 2884 // invoked function.
2845 LoadGlobal(); 2885 LoadGlobal();
2846 2886
2847 // Load the arguments. 2887 // Load the arguments.
2848 int arg_count = args->length(); 2888 int arg_count = args->length();
2849 for (int i = 0; i < arg_count; i++) { 2889 for (int i = 0; i < arg_count; i++) {
2850 Load(args->at(i)); 2890 Load(args->at(i));
2891 frame_->SpillTop();
2851 } 2892 }
2852 2893
2853 // Push the name of the function on the frame. 2894 // Push the name of the function on the frame.
2854 frame_->Push(var->name()); 2895 frame_->Push(var->name());
2855 2896
2856 // Call the IC initialization code. 2897 // Call the IC initialization code.
2857 CodeForSourcePosition(node->position()); 2898 CodeForSourcePosition(node->position());
2858 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, 2899 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
2859 arg_count, 2900 arg_count,
2860 loop_nesting()); 2901 loop_nesting());
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2946 node->position()); 2987 node->position());
2947 2988
2948 } else { 2989 } else {
2949 // Push the receiver onto the frame. 2990 // Push the receiver onto the frame.
2950 Load(property->obj()); 2991 Load(property->obj());
2951 2992
2952 // Load the arguments. 2993 // Load the arguments.
2953 int arg_count = args->length(); 2994 int arg_count = args->length();
2954 for (int i = 0; i < arg_count; i++) { 2995 for (int i = 0; i < arg_count; i++) {
2955 Load(args->at(i)); 2996 Load(args->at(i));
2997 frame_->SpillTop();
2956 } 2998 }
2957 2999
2958 // Push the name of the function onto the frame. 3000 // Push the name of the function onto the frame.
2959 frame_->Push(name); 3001 frame_->Push(name);
2960 3002
2961 // Call the IC initialization code. 3003 // Call the IC initialization code.
2962 CodeForSourcePosition(node->position()); 3004 CodeForSourcePosition(node->position());
2963 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET, 3005 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET,
2964 arg_count, 3006 arg_count,
2965 loop_nesting()); 3007 loop_nesting());
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
3392 deferred = new DeferredPostfixCountOperation(new_value.reg(), 3434 deferred = new DeferredPostfixCountOperation(new_value.reg(),
3393 old_value.reg(), 3435 old_value.reg(),
3394 is_increment, 3436 is_increment,
3395 new_value.type_info()); 3437 new_value.type_info());
3396 } else { 3438 } else {
3397 deferred = new DeferredPrefixCountOperation(new_value.reg(), 3439 deferred = new DeferredPrefixCountOperation(new_value.reg(),
3398 is_increment, 3440 is_increment,
3399 new_value.type_info()); 3441 new_value.type_info());
3400 } 3442 }
3401 3443
3402 __ JumpIfNotSmi(new_value.reg(), deferred->entry_label()); 3444 if (new_value.is_smi()) {
3445 if (FLAG_debug_code) { __ AbortIfNotSmi(new_value.reg()); }
3446 } else {
3447 __ JumpIfNotSmi(new_value.reg(), deferred->entry_label());
3448 }
3403 if (is_increment) { 3449 if (is_increment) {
3404 __ SmiAddConstant(kScratchRegister, 3450 __ SmiAddConstant(kScratchRegister,
3405 new_value.reg(), 3451 new_value.reg(),
3406 Smi::FromInt(1), 3452 Smi::FromInt(1),
3407 deferred->entry_label()); 3453 deferred->entry_label());
3408 } else { 3454 } else {
3409 __ SmiSubConstant(kScratchRegister, 3455 __ SmiSubConstant(kScratchRegister,
3410 new_value.reg(), 3456 new_value.reg(),
3411 Smi::FromInt(1), 3457 Smi::FromInt(1),
3412 deferred->entry_label()); 3458 deferred->entry_label());
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
3826 3872
3827 __ Move(kScratchRegister, Factory::null_value()); 3873 __ Move(kScratchRegister, Factory::null_value());
3828 __ cmpq(obj.reg(), kScratchRegister); 3874 __ cmpq(obj.reg(), kScratchRegister);
3829 destination()->true_target()->Branch(equal); 3875 destination()->true_target()->Branch(equal);
3830 3876
3831 __ movq(kScratchRegister, FieldOperand(obj.reg(), HeapObject::kMapOffset)); 3877 __ movq(kScratchRegister, FieldOperand(obj.reg(), HeapObject::kMapOffset));
3832 // Undetectable objects behave like undefined when tested with typeof. 3878 // Undetectable objects behave like undefined when tested with typeof.
3833 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 3879 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
3834 Immediate(1 << Map::kIsUndetectable)); 3880 Immediate(1 << Map::kIsUndetectable));
3835 destination()->false_target()->Branch(not_zero); 3881 destination()->false_target()->Branch(not_zero);
3836 __ CmpInstanceType(kScratchRegister, FIRST_JS_OBJECT_TYPE); 3882 __ movzxbq(kScratchRegister,
3837 destination()->false_target()->Branch(less); 3883 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
3838 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); 3884 __ cmpq(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE));
3885 destination()->false_target()->Branch(below);
3886 __ cmpq(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE));
3839 obj.Unuse(); 3887 obj.Unuse();
3840 destination()->Split(less_equal); 3888 destination()->Split(below_equal);
3841 } 3889 }
3842 3890
3843 3891
3844 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { 3892 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
3845 // This generates a fast version of: 3893 // This generates a fast version of:
3846 // (%_ClassOf(arg) === 'Function') 3894 // (%_ClassOf(arg) === 'Function')
3847 ASSERT(args->length() == 1); 3895 ASSERT(args->length() == 1);
3848 Load(args->at(0)); 3896 Load(args->at(0));
3849 Result obj = frame_->Pop(); 3897 Result obj = frame_->Pop();
3850 obj.ToRegister(); 3898 obj.ToRegister();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3914 __ j(not_equal, &exit); 3962 __ j(not_equal, &exit);
3915 3963
3916 // Arguments adaptor case: Read the arguments length from the 3964 // Arguments adaptor case: Read the arguments length from the
3917 // adaptor frame. 3965 // adaptor frame.
3918 __ movq(result.reg(), 3966 __ movq(result.reg(),
3919 Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset)); 3967 Operand(fp.reg(), ArgumentsAdaptorFrameConstants::kLengthOffset));
3920 3968
3921 __ bind(&exit); 3969 __ bind(&exit);
3922 result.set_type_info(TypeInfo::Smi()); 3970 result.set_type_info(TypeInfo::Smi());
3923 if (FLAG_debug_code) { 3971 if (FLAG_debug_code) {
3924 __ AbortIfNotSmi(result.reg(), "Computed arguments.length is not a smi."); 3972 __ AbortIfNotSmi(result.reg());
3925 } 3973 }
3926 frame_->Push(&result); 3974 frame_->Push(&result);
3927 } 3975 }
3928 3976
3929 3977
3930 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3978 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3931 Comment(masm_, "[ GenerateFastCharCodeAt"); 3979 Comment(masm_, "[ GenerateFastCharCodeAt");
3932 ASSERT(args->length() == 2); 3980 ASSERT(args->length() == 2);
3933 3981
3934 Load(args->at(0)); 3982 Load(args->at(0));
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
4322 __ CallRuntime(Runtime::kNumberUnaryMinus, 1); 4370 __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
4323 __ movq(rbx, rax); 4371 __ movq(rbx, rax);
4324 4372
4325 __ bind(&heapnumber_allocated); 4373 __ bind(&heapnumber_allocated);
4326 4374
4327 // Return a random uint32 number in rax. 4375 // Return a random uint32 number in rax.
4328 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs. 4376 // The fresh HeapNumber is in rbx, which is callee-save on both x64 ABIs.
4329 __ PrepareCallCFunction(0); 4377 __ PrepareCallCFunction(0);
4330 __ CallCFunction(ExternalReference::random_uint32_function(), 0); 4378 __ CallCFunction(ExternalReference::random_uint32_function(), 0);
4331 4379
4332 // Convert 32 random bits in eax to 0.(32 random bits) in a double 4380 // Convert 32 random bits in rax to 0.(32 random bits) in a double
4333 // by computing: 4381 // by computing:
4334 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 4382 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
4335 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. 4383 __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
4336 __ movd(xmm1, rcx); 4384 __ movd(xmm1, rcx);
4337 __ movd(xmm0, rax); 4385 __ movd(xmm0, rax);
4338 __ cvtss2sd(xmm1, xmm1); 4386 __ cvtss2sd(xmm1, xmm1);
4339 __ xorpd(xmm0, xmm1); 4387 __ xorpd(xmm0, xmm1);
4340 __ subsd(xmm0, xmm1); 4388 __ subsd(xmm0, xmm1);
4341 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0); 4389 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
4342 4390
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
5093 // convert it to a boolean in the condition code register or jump to 5141 // convert it to a boolean in the condition code register or jump to
5094 // 'false_target'/'true_target' as appropriate. 5142 // 'false_target'/'true_target' as appropriate.
5095 void CodeGenerator::ToBoolean(ControlDestination* dest) { 5143 void CodeGenerator::ToBoolean(ControlDestination* dest) {
5096 Comment cmnt(masm_, "[ ToBoolean"); 5144 Comment cmnt(masm_, "[ ToBoolean");
5097 5145
5098 // The value to convert should be popped from the frame. 5146 // The value to convert should be popped from the frame.
5099 Result value = frame_->Pop(); 5147 Result value = frame_->Pop();
5100 value.ToRegister(); 5148 value.ToRegister();
5101 5149
5102 if (value.is_number()) { 5150 if (value.is_number()) {
5103 Comment cmnt(masm_, "ONLY_NUMBER");
5104 // Fast case if TypeInfo indicates only numbers. 5151 // Fast case if TypeInfo indicates only numbers.
5105 if (FLAG_debug_code) { 5152 if (FLAG_debug_code) {
5106 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); 5153 __ AbortIfNotNumber(value.reg());
5107 } 5154 }
5108 // Smi => false iff zero. 5155 // Smi => false iff zero.
5109 __ SmiCompare(value.reg(), Smi::FromInt(0)); 5156 __ SmiCompare(value.reg(), Smi::FromInt(0));
5110 dest->false_target()->Branch(equal); 5157 dest->false_target()->Branch(equal);
5111 Condition is_smi = masm_->CheckSmi(value.reg()); 5158 Condition is_smi = masm_->CheckSmi(value.reg());
5112 dest->true_target()->Branch(is_smi); 5159 dest->true_target()->Branch(is_smi);
5113 __ fldz(); 5160 __ fldz();
5114 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); 5161 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
5115 __ FCmp(); 5162 __ FCmp();
5116 value.Unuse(); 5163 value.Unuse();
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
5869 5916
5870 // Here we split control flow to the stub call and inlined cases 5917 // Here we split control flow to the stub call and inlined cases
5871 // before finally splitting it to the control destination. We use 5918 // before finally splitting it to the control destination. We use
5872 // a jump target and branching to duplicate the virtual frame at 5919 // a jump target and branching to duplicate the virtual frame at
5873 // the first split. We manually handle the off-frame references 5920 // the first split. We manually handle the off-frame references
5874 // by reconstituting them on the non-fall-through path. 5921 // by reconstituting them on the non-fall-through path.
5875 JumpTarget is_smi; 5922 JumpTarget is_smi;
5876 5923
5877 if (left_side.is_smi()) { 5924 if (left_side.is_smi()) {
5878 if (FLAG_debug_code) { 5925 if (FLAG_debug_code) {
5879 __ AbortIfNotSmi(left_side.reg(), "Non-smi value inferred as smi."); 5926 __ AbortIfNotSmi(left_side.reg());
5880 } 5927 }
5881 } else { 5928 } else {
5882 Condition left_is_smi = masm_->CheckSmi(left_side.reg()); 5929 Condition left_is_smi = masm_->CheckSmi(left_side.reg());
5883 is_smi.Branch(left_is_smi); 5930 is_smi.Branch(left_is_smi);
5884 5931
5885 bool is_loop_condition = (node->AsExpression() != NULL) && 5932 bool is_loop_condition = (node->AsExpression() != NULL) &&
5886 node->AsExpression()->is_loop_condition(); 5933 node->AsExpression()->is_loop_condition();
5887 if (!is_loop_condition && right_val->IsSmi()) { 5934 if (!is_loop_condition && right_val->IsSmi()) {
5888 // Right side is a constant smi and left side has been checked 5935 // Right side is a constant smi and left side has been checked
5889 // not to be a smi. 5936 // not to be a smi.
(...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after
6741 DeferredInlineSmiOperationReversed* deferred = 6788 DeferredInlineSmiOperationReversed* deferred =
6742 new DeferredInlineSmiOperationReversed(op, 6789 new DeferredInlineSmiOperationReversed(op,
6743 answer.reg(), 6790 answer.reg(),
6744 smi_value, 6791 smi_value,
6745 operand->reg(), 6792 operand->reg(),
6746 overwrite_mode); 6793 overwrite_mode);
6747 if (!operand->type_info().IsSmi()) { 6794 if (!operand->type_info().IsSmi()) {
6748 Condition is_smi = masm_->CheckSmi(operand->reg()); 6795 Condition is_smi = masm_->CheckSmi(operand->reg());
6749 deferred->Branch(NegateCondition(is_smi)); 6796 deferred->Branch(NegateCondition(is_smi));
6750 } else if (FLAG_debug_code) { 6797 } else if (FLAG_debug_code) {
6751 __ AbortIfNotSmi(operand->reg(), 6798 __ AbortIfNotSmi(operand->reg());
6752 "Static type info claims non-smi is smi in (const SHL smi).");
6753 } 6799 }
6754 6800
6755 __ Move(answer.reg(), smi_value); 6801 __ Move(answer.reg(), smi_value);
6756 __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg()); 6802 __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg());
6757 operand->Unuse(); 6803 operand->Unuse();
6758 6804
6759 deferred->BindExit(); 6805 deferred->BindExit();
6760 } else { 6806 } else {
6761 // Only the least significant 5 bits of the shift value are used. 6807 // Only the least significant 5 bits of the shift value are used.
6762 // In the slow case, this masking is done inside the runtime call. 6808 // In the slow case, this masking is done inside the runtime call.
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
7004 answer = allocator_->Allocate(); 7050 answer = allocator_->Allocate();
7005 ASSERT(answer.is_valid()); 7051 ASSERT(answer.is_valid());
7006 // Check that both operands are smis using the answer register as a 7052 // Check that both operands are smis using the answer register as a
7007 // temporary. 7053 // temporary.
7008 DeferredInlineBinaryOperation* deferred = 7054 DeferredInlineBinaryOperation* deferred =
7009 new DeferredInlineBinaryOperation(op, 7055 new DeferredInlineBinaryOperation(op,
7010 answer.reg(), 7056 answer.reg(),
7011 left->reg(), 7057 left->reg(),
7012 rcx, 7058 rcx,
7013 overwrite_mode); 7059 overwrite_mode);
7014 __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); 7060
7061 Label do_op;
7062 if (right_type_info.IsSmi()) {
7063 if (FLAG_debug_code) {
7064 __ AbortIfNotSmi(right->reg());
7065 }
7066 __ movq(answer.reg(), left->reg());
7067 // If left is not known to be a smi, check if it is.
7068 // If left is not known to be a number, and it isn't a smi, check if
7069 // it is a HeapNumber.
7070 if (!left_type_info.IsSmi()) {
7071 __ JumpIfSmi(answer.reg(), &do_op);
7072 if (!left_type_info.IsNumber()) {
7073 // Branch if not a heapnumber.
7074 __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
7075 Factory::heap_number_map());
7076 deferred->Branch(not_equal);
7077 }
7078 // Load integer value into answer register using truncation.
7079 __ cvttsd2si(answer.reg(),
7080 FieldOperand(answer.reg(), HeapNumber::kValueOffset));
7081 // Branch if we might have overflowed.
7082 // (False negative for Smi::kMinValue)
7083 __ cmpq(answer.reg(), Immediate(0x80000000));
7084 deferred->Branch(equal);
7085 // TODO(lrn): Inline shifts on int32 here instead of first smi-tagging.
7086 __ Integer32ToSmi(answer.reg(), answer.reg());
7087 } else {
7088 // Fast case - both are actually smis.
7089 if (FLAG_debug_code) {
7090 __ AbortIfNotSmi(left->reg());
7091 }
7092 }
7093 } else {
7094 __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label());
7095 }
7096 __ bind(&do_op);
7015 7097
7016 // Perform the operation. 7098 // Perform the operation.
7017 switch (op) { 7099 switch (op) {
7018 case Token::SAR: 7100 case Token::SAR:
7019 __ SmiShiftArithmeticRight(answer.reg(), left->reg(), rcx); 7101 __ SmiShiftArithmeticRight(answer.reg(), left->reg(), rcx);
7020 break; 7102 break;
7021 case Token::SHR: { 7103 case Token::SHR: {
7022 __ SmiShiftLogicalRight(answer.reg(), 7104 __ SmiShiftLogicalRight(answer.reg(),
7023 left->reg(), 7105 left->reg(),
7024 rcx, 7106 rcx,
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
7462 key.reg(), 7544 key.reg(),
7463 receiver.reg()); 7545 receiver.reg());
7464 7546
7465 // Check that the receiver is not a smi. 7547 // Check that the receiver is not a smi.
7466 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 7548 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
7467 7549
7468 // Check that the key is a smi. 7550 // Check that the key is a smi.
7469 if (!key.is_smi()) { 7551 if (!key.is_smi()) {
7470 __ JumpIfNotSmi(key.reg(), deferred->entry_label()); 7552 __ JumpIfNotSmi(key.reg(), deferred->entry_label());
7471 } else if (FLAG_debug_code) { 7553 } else if (FLAG_debug_code) {
7472 __ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value."); 7554 __ AbortIfNotSmi(key.reg());
7473 } 7555 }
7474 7556
7475 // Check that the receiver is a JSArray. 7557 // Check that the receiver is a JSArray.
7476 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); 7558 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
7477 deferred->Branch(not_equal); 7559 deferred->Branch(not_equal);
7478 7560
7479 // Check that the key is within bounds. Both the key and the 7561 // Check that the key is within bounds. Both the key and the
7480 // length of the JSArray are smis. Use unsigned comparison to handle 7562 // length of the JSArray are smis. Use unsigned comparison to handle
7481 // negative keys. 7563 // negative keys.
7482 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset), 7564 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
7517 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); 7599 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
7518 __ movq(Operand(tmp.reg(), 7600 __ movq(Operand(tmp.reg(),
7519 index.reg, 7601 index.reg,
7520 index.scale, 7602 index.scale,
7521 FixedArray::kHeaderSize - kHeapObjectTag), 7603 FixedArray::kHeaderSize - kHeapObjectTag),
7522 value.reg()); 7604 value.reg());
7523 __ IncrementCounter(&Counters::keyed_store_inline, 1); 7605 __ IncrementCounter(&Counters::keyed_store_inline, 1);
7524 7606
7525 deferred->BindExit(); 7607 deferred->BindExit();
7526 7608
7527 cgen_->frame()->Push(&receiver);
7528 cgen_->frame()->Push(&key);
7529 cgen_->frame()->Push(&value); 7609 cgen_->frame()->Push(&value);
7530 } else { 7610 } else {
7531 Result answer = cgen_->frame()->CallKeyedStoreIC(); 7611 Result answer = cgen_->frame()->CallKeyedStoreIC();
7532 // Make sure that we do not have a test instruction after the 7612 // Make sure that we do not have a test instruction after the
7533 // call. A test instruction after the call is used to 7613 // call. A test instruction after the call is used to
7534 // indicate that we have generated an inline version of the 7614 // indicate that we have generated an inline version of the
7535 // keyed store. 7615 // keyed store.
7536 masm->nop(); 7616 masm->nop();
7537 cgen_->frame()->Push(&answer); 7617 cgen_->frame()->Push(&answer);
7538 } 7618 }
7539 cgen_->UnloadReference(this); 7619 set_unloaded();
7540 break; 7620 break;
7541 } 7621 }
7542 7622
7543 default: 7623 default:
7544 UNREACHABLE(); 7624 UNREACHABLE();
7545 } 7625 }
7546 } 7626 }
7547 7627
7548 7628
7549 void FastNewClosureStub::Generate(MacroAssembler* masm) { 7629 void FastNewClosureStub::Generate(MacroAssembler* masm) {
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after
8891 8971
8892 // Call the function just below TOS on the stack with the given 8972 // Call the function just below TOS on the stack with the given
8893 // arguments. The receiver is the TOS. 8973 // arguments. The receiver is the TOS.
8894 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 8974 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
8895 CallFunctionFlags flags, 8975 CallFunctionFlags flags,
8896 int position) { 8976 int position) {
8897 // Push the arguments ("left-to-right") on the stack. 8977 // Push the arguments ("left-to-right") on the stack.
8898 int arg_count = args->length(); 8978 int arg_count = args->length();
8899 for (int i = 0; i < arg_count; i++) { 8979 for (int i = 0; i < arg_count; i++) {
8900 Load(args->at(i)); 8980 Load(args->at(i));
8981 frame_->SpillTop();
8901 } 8982 }
8902 8983
8903 // Record the position for debugging purposes. 8984 // Record the position for debugging purposes.
8904 CodeForSourcePosition(position); 8985 CodeForSourcePosition(position);
8905 8986
8906 // Use the shared code stub to call the function. 8987 // Use the shared code stub to call the function.
8907 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; 8988 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
8908 CallFunctionStub call_function(arg_count, in_loop, flags); 8989 CallFunctionStub call_function(arg_count, in_loop, flags);
8909 Result answer = frame_->CallStub(&call_function, arg_count + 1); 8990 Result answer = frame_->CallStub(&call_function, arg_count + 1);
8910 // Restore context and replace function on the stack with the 8991 // Restore context and replace function on the stack with the
(...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after
10007 if (!HasArgsInRegisters()) { 10088 if (!HasArgsInRegisters()) {
10008 __ movq(right, Operand(rsp, 1 * kPointerSize)); 10089 __ movq(right, Operand(rsp, 1 * kPointerSize));
10009 __ movq(left, Operand(rsp, 2 * kPointerSize)); 10090 __ movq(left, Operand(rsp, 2 * kPointerSize));
10010 } 10091 }
10011 10092
10012 Label not_smis; 10093 Label not_smis;
10013 // 2. Smi check both operands. 10094 // 2. Smi check both operands.
10014 if (static_operands_type_.IsSmi()) { 10095 if (static_operands_type_.IsSmi()) {
10015 // Skip smi check if we know that both arguments are smis. 10096 // Skip smi check if we know that both arguments are smis.
10016 if (FLAG_debug_code) { 10097 if (FLAG_debug_code) {
10017 __ AbortIfNotSmi(left, "Static type check claimed non-smi is smi."); 10098 __ AbortIfNotSmi(left);
10018 __ AbortIfNotSmi(right, "Static type check claimed non-smi is smi."); 10099 __ AbortIfNotSmi(right);
10019 } 10100 }
10020 if (op_ == Token::BIT_OR) { 10101 if (op_ == Token::BIT_OR) {
10021 // Handle OR here, since we do extra smi-checking in the or code below. 10102 // Handle OR here, since we do extra smi-checking in the or code below.
10022 __ SmiOr(right, right, left); 10103 __ SmiOr(right, right, left);
10023 GenerateReturn(masm); 10104 GenerateReturn(masm);
10024 return; 10105 return;
10025 } 10106 }
10026 } else { 10107 } else {
10027 if (op_ != Token::BIT_OR) { 10108 if (op_ != Token::BIT_OR) {
10028 // Skip the check for OR as it is better combined with the 10109 // Skip the check for OR as it is better combined with the
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
10191 // the four basic operations. The stub stays in the DEFAULT state 10272 // the four basic operations. The stub stays in the DEFAULT state
10192 // forever for all other operations (also if smi code is skipped). 10273 // forever for all other operations (also if smi code is skipped).
10193 GenerateTypeTransition(masm); 10274 GenerateTypeTransition(masm);
10194 } 10275 }
10195 10276
10196 Label not_floats; 10277 Label not_floats;
10197 // rax: y 10278 // rax: y
10198 // rdx: x 10279 // rdx: x
10199 if (static_operands_type_.IsNumber() && FLAG_debug_code) { 10280 if (static_operands_type_.IsNumber() && FLAG_debug_code) {
10200 // Assert at runtime that inputs are only numbers. 10281 // Assert at runtime that inputs are only numbers.
10201 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); 10282 __ AbortIfNotNumber(rdx);
10202 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number."); 10283 __ AbortIfNotNumber(rax);
10203 } else { 10284 } else {
10204 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 10285 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
10205 } 10286 }
10206 // Fast-case: Both operands are numbers. 10287 // Fast-case: Both operands are numbers.
10207 // xmm4 and xmm5 are volatile XMM registers. 10288 // xmm4 and xmm5 are volatile XMM registers.
10208 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5); 10289 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
10209 10290
10210 switch (op_) { 10291 switch (op_) {
10211 case Token::ADD: __ addsd(xmm4, xmm5); break; 10292 case Token::ADD: __ addsd(xmm4, xmm5); break;
10212 case Token::SUB: __ subsd(xmm4, xmm5); break; 10293 case Token::SUB: __ subsd(xmm4, xmm5); break;
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after
11582 // Call the function from C++. 11663 // Call the function from C++.
11583 return FUNCTION_CAST<ModuloFunction>(buffer); 11664 return FUNCTION_CAST<ModuloFunction>(buffer);
11584 } 11665 }
11585 11666
11586 #endif 11667 #endif
11587 11668
11588 11669
11589 #undef __ 11670 #undef __
11590 11671
11591 } } // namespace v8::internal 11672 } } // namespace v8::internal
11673
11674 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/cpu-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698