| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |