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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 148503002: A64: Synchronize with r15545. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 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/code-stubs-x64.h ('k') | 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2013 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) 30 #if V8_TARGET_ARCH_X64
31 31
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "regexp-macro-assembler.h" 34 #include "regexp-macro-assembler.h"
35 #include "stub-cache.h" 35 #include "stub-cache.h"
36 #include "runtime.h" 36 #include "runtime.h"
37 37
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
(...skipping 13 matching lines...) Expand all
54 Isolate* isolate, 54 Isolate* isolate,
55 CodeStubInterfaceDescriptor* descriptor) { 55 CodeStubInterfaceDescriptor* descriptor) {
56 static Register registers[] = { rax, rbx, rcx, rdx }; 56 static Register registers[] = { rax, rbx, rcx, rdx };
57 descriptor->register_param_count_ = 4; 57 descriptor->register_param_count_ = 4;
58 descriptor->register_params_ = registers; 58 descriptor->register_params_ = registers;
59 descriptor->deoptimization_handler_ = 59 descriptor->deoptimization_handler_ =
60 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; 60 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry;
61 } 61 }
62 62
63 63
64 void CreateAllocationSiteStub::InitializeInterfaceDescriptor(
65 Isolate* isolate,
66 CodeStubInterfaceDescriptor* descriptor) {
67 static Register registers[] = { rbx };
68 descriptor->register_param_count_ = 1;
69 descriptor->register_params_ = registers;
70 descriptor->deoptimization_handler_ = NULL;
71 }
72
73
64 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( 74 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor(
65 Isolate* isolate, 75 Isolate* isolate,
66 CodeStubInterfaceDescriptor* descriptor) { 76 CodeStubInterfaceDescriptor* descriptor) {
67 static Register registers[] = { rdx, rax }; 77 static Register registers[] = { rdx, rax };
68 descriptor->register_param_count_ = 2; 78 descriptor->register_param_count_ = 2;
69 descriptor->register_params_ = registers; 79 descriptor->register_params_ = registers;
70 descriptor->deoptimization_handler_ = 80 descriptor->deoptimization_handler_ =
71 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); 81 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
72 } 82 }
73 83
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 225
216 void ToBooleanStub::InitializeInterfaceDescriptor( 226 void ToBooleanStub::InitializeInterfaceDescriptor(
217 Isolate* isolate, 227 Isolate* isolate,
218 CodeStubInterfaceDescriptor* descriptor) { 228 CodeStubInterfaceDescriptor* descriptor) {
219 static Register registers[] = { rax }; 229 static Register registers[] = { rax };
220 descriptor->register_param_count_ = 1; 230 descriptor->register_param_count_ = 1;
221 descriptor->register_params_ = registers; 231 descriptor->register_params_ = registers;
222 descriptor->deoptimization_handler_ = 232 descriptor->deoptimization_handler_ =
223 FUNCTION_ADDR(ToBooleanIC_Miss); 233 FUNCTION_ADDR(ToBooleanIC_Miss);
224 descriptor->SetMissHandler( 234 descriptor->SetMissHandler(
225 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate)); 235 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate));
226 } 236 }
227 237
228 238
239 void UnaryOpStub::InitializeInterfaceDescriptor(
240 Isolate* isolate,
241 CodeStubInterfaceDescriptor* descriptor) {
242 static Register registers[] = { rax };
243 descriptor->register_param_count_ = 1;
244 descriptor->register_params_ = registers;
245 descriptor->deoptimization_handler_ =
246 FUNCTION_ADDR(UnaryOpIC_Miss);
247 }
248
249
250 void StoreGlobalStub::InitializeInterfaceDescriptor(
251 Isolate* isolate,
252 CodeStubInterfaceDescriptor* descriptor) {
253 static Register registers[] = { rdx, rcx, rax };
254 descriptor->register_param_count_ = 3;
255 descriptor->register_params_ = registers;
256 descriptor->deoptimization_handler_ =
257 FUNCTION_ADDR(StoreIC_MissFromStubFailure);
258 }
259
260
229 #define __ ACCESS_MASM(masm) 261 #define __ ACCESS_MASM(masm)
230 262
231 263
232 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { 264 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
233 // Update the static counter each time a new code stub is generated. 265 // Update the static counter each time a new code stub is generated.
234 Isolate* isolate = masm->isolate(); 266 Isolate* isolate = masm->isolate();
235 isolate->counters()->code_stubs()->Increment(); 267 isolate->counters()->code_stubs()->Increment();
236 268
237 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate); 269 CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
238 int param_count = descriptor->register_param_count_; 270 int param_count = descriptor->register_param_count_;
239 { 271 {
240 // Call the runtime system in a fresh internal frame. 272 // Call the runtime system in a fresh internal frame.
241 FrameScope scope(masm, StackFrame::INTERNAL); 273 FrameScope scope(masm, StackFrame::INTERNAL);
242 ASSERT(descriptor->register_param_count_ == 0 || 274 ASSERT(descriptor->register_param_count_ == 0 ||
243 rax.is(descriptor->register_params_[param_count - 1])); 275 rax.is(descriptor->register_params_[param_count - 1]));
244 // Push arguments 276 // Push arguments
245 for (int i = 0; i < param_count; ++i) { 277 for (int i = 0; i < param_count; ++i) {
246 __ push(descriptor->register_params_[i]); 278 __ push(descriptor->register_params_[i]);
247 } 279 }
248 ExternalReference miss = descriptor->miss_handler(); 280 ExternalReference miss = descriptor->miss_handler();
249 __ CallExternalReference(miss, descriptor->register_param_count_); 281 __ CallExternalReference(miss, descriptor->register_param_count_);
250 } 282 }
251 283
252 __ Ret(); 284 __ Ret();
253 } 285 }
254 286
255 287
256 void ToNumberStub::Generate(MacroAssembler* masm) { 288 void ToNumberStub::Generate(MacroAssembler* masm) {
257 // The ToNumber stub takes one argument in eax. 289 // The ToNumber stub takes one argument in rax.
258 Label check_heap_number, call_builtin; 290 Label check_heap_number, call_builtin;
259 __ SmiTest(rax); 291 __ SmiTest(rax);
260 __ j(not_zero, &check_heap_number, Label::kNear); 292 __ j(not_zero, &check_heap_number, Label::kNear);
261 __ Ret(); 293 __ Ret();
262 294
263 __ bind(&check_heap_number); 295 __ bind(&check_heap_number);
264 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 296 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
265 Heap::kHeapNumberMapRootIndex); 297 Heap::kHeapNumberMapRootIndex);
266 __ j(not_equal, &call_builtin, Label::kNear); 298 __ j(not_equal, &call_builtin, Label::kNear);
267 __ Ret(); 299 __ Ret();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize)); 358 __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
327 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx); 359 __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
328 360
329 // Return and remove the on-stack parameter. 361 // Return and remove the on-stack parameter.
330 __ ret(1 * kPointerSize); 362 __ ret(1 * kPointerSize);
331 363
332 __ bind(&check_optimized); 364 __ bind(&check_optimized);
333 365
334 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1); 366 __ IncrementCounter(counters->fast_new_closure_try_optimized(), 1);
335 367
336 // rcx holds native context, ebx points to fixed array of 3-element entries 368 // rcx holds native context, rbx points to fixed array of 3-element entries
337 // (native context, optimized code, literals). 369 // (native context, optimized code, literals).
338 // The optimized code map must never be empty, so check the first elements. 370 // The optimized code map must never be empty, so check the first elements.
339 Label install_optimized; 371 Label install_optimized;
340 // Speculatively move code object into edx. 372 // Speculatively move code object into edx.
341 __ movq(rdx, FieldOperand(rbx, SharedFunctionInfo::kFirstCodeSlot)); 373 __ movq(rdx, FieldOperand(rbx, SharedFunctionInfo::kFirstCodeSlot));
342 __ cmpq(rcx, FieldOperand(rbx, SharedFunctionInfo::kFirstContextSlot)); 374 __ cmpq(rcx, FieldOperand(rbx, SharedFunctionInfo::kFirstContextSlot));
343 __ j(equal, &install_optimized); 375 __ j(equal, &install_optimized);
344 376
345 // Iterate through the rest of map backwards. rdx holds an index. 377 // Iterate through the rest of map backwards. rdx holds an index.
346 Label loop; 378 Label loop;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 477
446 // Need to collect. Call into runtime system. 478 // Need to collect. Call into runtime system.
447 __ bind(&gc); 479 __ bind(&gc);
448 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); 480 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
449 } 481 }
450 482
451 483
452 void FastNewBlockContextStub::Generate(MacroAssembler* masm) { 484 void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
453 // Stack layout on entry: 485 // Stack layout on entry:
454 // 486 //
455 // [rsp + (1 * kPointerSize)]: function 487 // [rsp + (1 * kPointerSize)] : function
456 // [rsp + (2 * kPointerSize)]: serialized scope info 488 // [rsp + (2 * kPointerSize)] : serialized scope info
457 489
458 // Try to allocate the context in new space. 490 // Try to allocate the context in new space.
459 Label gc; 491 Label gc;
460 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 492 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
461 __ Allocate(FixedArray::SizeFor(length), 493 __ Allocate(FixedArray::SizeFor(length),
462 rax, rbx, rcx, &gc, TAG_OBJECT); 494 rax, rbx, rcx, &gc, TAG_OBJECT);
463 495
464 // Get the function from the stack. 496 // Get the function from the stack.
465 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 497 __ movq(rcx, Operand(rsp, 1 * kPointerSize));
466 498
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 // As the then-branch, but move double-value to result before shifting. 668 // As the then-branch, but move double-value to result before shifting.
637 __ xorl(result, double_value); 669 __ xorl(result, double_value);
638 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1)); 670 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
639 __ shll_cl(result); 671 __ shll_cl(result);
640 } 672 }
641 673
642 __ bind(&done); 674 __ bind(&done);
643 } 675 }
644 676
645 677
646 void UnaryOpStub::Generate(MacroAssembler* masm) {
647 switch (operand_type_) {
648 case UnaryOpIC::UNINITIALIZED:
649 GenerateTypeTransition(masm);
650 break;
651 case UnaryOpIC::SMI:
652 GenerateSmiStub(masm);
653 break;
654 case UnaryOpIC::NUMBER:
655 GenerateNumberStub(masm);
656 break;
657 case UnaryOpIC::GENERIC:
658 GenerateGenericStub(masm);
659 break;
660 }
661 }
662
663
664 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
665 __ pop(rcx); // Save return address.
666
667 __ push(rax); // the operand
668 __ Push(Smi::FromInt(op_));
669 __ Push(Smi::FromInt(mode_));
670 __ Push(Smi::FromInt(operand_type_));
671
672 __ push(rcx); // Push return address.
673
674 // Patch the caller to an appropriate specialized stub and return the
675 // operation result to the caller of the stub.
676 __ TailCallExternalReference(
677 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
678 }
679
680
681 // TODO(svenpanne): Use virtual functions instead of switch.
682 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
683 switch (op_) {
684 case Token::SUB:
685 GenerateSmiStubSub(masm);
686 break;
687 case Token::BIT_NOT:
688 GenerateSmiStubBitNot(masm);
689 break;
690 default:
691 UNREACHABLE();
692 }
693 }
694
695
696 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
697 Label slow;
698 GenerateSmiCodeSub(masm, &slow, &slow, Label::kNear, Label::kNear);
699 __ bind(&slow);
700 GenerateTypeTransition(masm);
701 }
702
703
704 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
705 Label non_smi;
706 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
707 __ bind(&non_smi);
708 GenerateTypeTransition(masm);
709 }
710
711
712 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
713 Label* non_smi,
714 Label* slow,
715 Label::Distance non_smi_near,
716 Label::Distance slow_near) {
717 Label done;
718 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
719 __ SmiNeg(rax, rax, &done, Label::kNear);
720 __ jmp(slow, slow_near);
721 __ bind(&done);
722 __ ret(0);
723 }
724
725
726 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
727 Label* non_smi,
728 Label::Distance non_smi_near) {
729 __ JumpIfNotSmi(rax, non_smi, non_smi_near);
730 __ SmiNot(rax, rax);
731 __ ret(0);
732 }
733
734
735 // TODO(svenpanne): Use virtual functions instead of switch.
736 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
737 switch (op_) {
738 case Token::SUB:
739 GenerateNumberStubSub(masm);
740 break;
741 case Token::BIT_NOT:
742 GenerateNumberStubBitNot(masm);
743 break;
744 default:
745 UNREACHABLE();
746 }
747 }
748
749
750 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) {
751 Label non_smi, slow, call_builtin;
752 GenerateSmiCodeSub(masm, &non_smi, &call_builtin, Label::kNear);
753 __ bind(&non_smi);
754 GenerateHeapNumberCodeSub(masm, &slow);
755 __ bind(&slow);
756 GenerateTypeTransition(masm);
757 __ bind(&call_builtin);
758 GenerateGenericCodeFallback(masm);
759 }
760
761
762 void UnaryOpStub::GenerateNumberStubBitNot(
763 MacroAssembler* masm) {
764 Label non_smi, slow;
765 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
766 __ bind(&non_smi);
767 GenerateHeapNumberCodeBitNot(masm, &slow);
768 __ bind(&slow);
769 GenerateTypeTransition(masm);
770 }
771
772
773 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
774 Label* slow) {
775 // Check if the operand is a heap number.
776 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
777 Heap::kHeapNumberMapRootIndex);
778 __ j(not_equal, slow);
779
780 // Operand is a float, negate its value by flipping the sign bit.
781 if (mode_ == UNARY_OVERWRITE) {
782 __ Set(kScratchRegister, 0x01);
783 __ shl(kScratchRegister, Immediate(63));
784 __ xor_(FieldOperand(rax, HeapNumber::kValueOffset), kScratchRegister);
785 } else {
786 // Allocate a heap number before calculating the answer,
787 // so we don't have an untagged double around during GC.
788 Label slow_allocate_heapnumber, heapnumber_allocated;
789 __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
790 __ jmp(&heapnumber_allocated);
791
792 __ bind(&slow_allocate_heapnumber);
793 {
794 FrameScope scope(masm, StackFrame::INTERNAL);
795 __ push(rax);
796 __ CallRuntime(Runtime::kNumberAlloc, 0);
797 __ movq(rcx, rax);
798 __ pop(rax);
799 }
800 __ bind(&heapnumber_allocated);
801 // rcx: allocated 'empty' number
802
803 // Copy the double value to the new heap number, flipping the sign.
804 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset));
805 __ Set(kScratchRegister, 0x01);
806 __ shl(kScratchRegister, Immediate(63));
807 __ xor_(rdx, kScratchRegister); // Flip sign.
808 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx);
809 __ movq(rax, rcx);
810 }
811 __ ret(0);
812 }
813
814
815 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
816 Label* slow) {
817 // Check if the operand is a heap number.
818 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
819 Heap::kHeapNumberMapRootIndex);
820 __ j(not_equal, slow);
821
822 // Convert the heap number in rax to an untagged integer in rcx.
823 IntegerConvert(masm, rax, rax);
824
825 // Do the bitwise operation and smi tag the result.
826 __ notl(rax);
827 __ Integer32ToSmi(rax, rax);
828 __ ret(0);
829 }
830
831
832 // TODO(svenpanne): Use virtual functions instead of switch.
833 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
834 switch (op_) {
835 case Token::SUB:
836 GenerateGenericStubSub(masm);
837 break;
838 case Token::BIT_NOT:
839 GenerateGenericStubBitNot(masm);
840 break;
841 default:
842 UNREACHABLE();
843 }
844 }
845
846
847 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
848 Label non_smi, slow;
849 GenerateSmiCodeSub(masm, &non_smi, &slow, Label::kNear);
850 __ bind(&non_smi);
851 GenerateHeapNumberCodeSub(masm, &slow);
852 __ bind(&slow);
853 GenerateGenericCodeFallback(masm);
854 }
855
856
857 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
858 Label non_smi, slow;
859 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
860 __ bind(&non_smi);
861 GenerateHeapNumberCodeBitNot(masm, &slow);
862 __ bind(&slow);
863 GenerateGenericCodeFallback(masm);
864 }
865
866
867 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
868 // Handle the slow case by jumping to the JavaScript builtin.
869 __ pop(rcx); // pop return address
870 __ push(rax);
871 __ push(rcx); // push return address
872 switch (op_) {
873 case Token::SUB:
874 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
875 break;
876 case Token::BIT_NOT:
877 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
878 break;
879 default:
880 UNREACHABLE();
881 }
882 }
883
884
885 void UnaryOpStub::PrintName(StringStream* stream) {
886 const char* op_name = Token::Name(op_);
887 const char* overwrite_name = NULL; // Make g++ happy.
888 switch (mode_) {
889 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
890 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
891 }
892 stream->Add("UnaryOpStub_%s_%s_%s",
893 op_name,
894 overwrite_name,
895 UnaryOpIC::GetName(operand_type_));
896 }
897
898
899 void BinaryOpStub::Initialize() {} 678 void BinaryOpStub::Initialize() {}
900 679
901 680
902 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 681 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
903 __ pop(rcx); // Save return address. 682 __ pop(rcx); // Save return address.
904 __ push(rdx); 683 __ push(rdx);
905 __ push(rax); 684 __ push(rax);
906 // Left and right arguments are now on top. 685 // Left and right arguments are now on top.
907 __ Push(Smi::FromInt(MinorKey())); 686 __ Push(Smi::FromInt(MinorKey()));
908 687
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 1196
1418 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, 1197 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
1419 Label* alloc_failure, 1198 Label* alloc_failure,
1420 OverwriteMode mode) { 1199 OverwriteMode mode) {
1421 Label skip_allocation; 1200 Label skip_allocation;
1422 switch (mode) { 1201 switch (mode) {
1423 case OVERWRITE_LEFT: { 1202 case OVERWRITE_LEFT: {
1424 // If the argument in rdx is already an object, we skip the 1203 // If the argument in rdx is already an object, we skip the
1425 // allocation of a heap number. 1204 // allocation of a heap number.
1426 __ JumpIfNotSmi(rdx, &skip_allocation); 1205 __ JumpIfNotSmi(rdx, &skip_allocation);
1427 // Allocate a heap number for the result. Keep eax and edx intact 1206 // Allocate a heap number for the result. Keep rax and rdx intact
1428 // for the possible runtime call. 1207 // for the possible runtime call.
1429 __ AllocateHeapNumber(rbx, rcx, alloc_failure); 1208 __ AllocateHeapNumber(rbx, rcx, alloc_failure);
1430 // Now rdx can be overwritten losing one of the arguments as we are 1209 // Now rdx can be overwritten losing one of the arguments as we are
1431 // now done and will not need it any more. 1210 // now done and will not need it any more.
1432 __ movq(rdx, rbx); 1211 __ movq(rdx, rbx);
1433 __ bind(&skip_allocation); 1212 __ bind(&skip_allocation);
1434 // Use object in rdx as a result holder 1213 // Use object in rdx as a result holder
1435 __ movq(rax, rdx); 1214 __ movq(rax, rdx);
1436 break; 1215 break;
1437 } 1216 }
(...skipping 18 matching lines...) Expand all
1456 1235
1457 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 1236 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
1458 __ push(rdx); 1237 __ push(rdx);
1459 __ push(rax); 1238 __ push(rax);
1460 } 1239 }
1461 1240
1462 1241
1463 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 1242 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
1464 // TAGGED case: 1243 // TAGGED case:
1465 // Input: 1244 // Input:
1466 // rsp[8]: argument (should be number). 1245 // rsp[8] : argument (should be number).
1467 // rsp[0]: return address. 1246 // rsp[0] : return address.
1468 // Output: 1247 // Output:
1469 // rax: tagged double result. 1248 // rax: tagged double result.
1470 // UNTAGGED case: 1249 // UNTAGGED case:
1471 // Input:: 1250 // Input::
1472 // rsp[0]: return address. 1251 // rsp[0] : return address.
1473 // xmm1: untagged double input argument 1252 // xmm1 : untagged double input argument
1474 // Output: 1253 // Output:
1475 // xmm1: untagged double result. 1254 // xmm1 : untagged double result.
1476 1255
1477 Label runtime_call; 1256 Label runtime_call;
1478 Label runtime_call_clear_stack; 1257 Label runtime_call_clear_stack;
1479 Label skip_cache; 1258 Label skip_cache;
1480 const bool tagged = (argument_type_ == TAGGED); 1259 const bool tagged = (argument_type_ == TAGGED);
1481 if (tagged) { 1260 if (tagged) {
1482 Label input_not_smi, loaded; 1261 Label input_not_smi, loaded;
1483 // Test that rax is a number. 1262 // Test that rax is a number.
1484 __ movq(rax, Operand(rsp, kPointerSize)); 1263 __ movq(rax, Operand(rsp, kPointerSize));
1485 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); 1264 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 #ifdef DEBUG 1330 #ifdef DEBUG
1552 // Check that the layout of cache elements match expectations. 1331 // Check that the layout of cache elements match expectations.
1553 { // NOLINT - doesn't like a single brace on a line. 1332 { // NOLINT - doesn't like a single brace on a line.
1554 TranscendentalCache::SubCache::Element test_elem[2]; 1333 TranscendentalCache::SubCache::Element test_elem[2];
1555 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); 1334 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
1556 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); 1335 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
1557 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); 1336 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
1558 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); 1337 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
1559 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); 1338 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
1560 // Two uint_32's and a pointer per element. 1339 // Two uint_32's and a pointer per element.
1561 CHECK_EQ(16, static_cast<int>(elem2_start - elem_start)); 1340 CHECK_EQ(2 * kIntSize + 1 * kPointerSize,
1341 static_cast<int>(elem2_start - elem_start));
1562 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start)); 1342 CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
1563 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start)); 1343 CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
1564 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start)); 1344 CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
1565 } 1345 }
1566 #endif 1346 #endif
1567 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16]. 1347 // Find the address of the rcx'th entry in the cache, i.e., &rax[rcx*16].
1568 __ addl(rcx, rcx); 1348 __ addl(rcx, rcx);
1569 __ lea(rcx, Operand(rax, rcx, times_8, 0)); 1349 __ lea(rcx, Operand(rax, rcx, times_8, 0));
1570 // Check if cache matches: Double value is stored in uint32_t[2] array. 1350 // Check if cache matches: Double value is stored in uint32_t[2] array.
1571 Label cache_miss; 1351 Label cache_miss;
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 __ cvtlsi2sd(double_exponent, exponent); 1985 __ cvtlsi2sd(double_exponent, exponent);
2206 1986
2207 // Returning or bailing out. 1987 // Returning or bailing out.
2208 Counters* counters = masm->isolate()->counters(); 1988 Counters* counters = masm->isolate()->counters();
2209 if (exponent_type_ == ON_STACK) { 1989 if (exponent_type_ == ON_STACK) {
2210 // The arguments are still on the stack. 1990 // The arguments are still on the stack.
2211 __ bind(&call_runtime); 1991 __ bind(&call_runtime);
2212 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); 1992 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
2213 1993
2214 // The stub is called from non-optimized code, which expects the result 1994 // The stub is called from non-optimized code, which expects the result
2215 // as heap number in eax. 1995 // as heap number in rax.
2216 __ bind(&done); 1996 __ bind(&done);
2217 __ AllocateHeapNumber(rax, rcx, &call_runtime); 1997 __ AllocateHeapNumber(rax, rcx, &call_runtime);
2218 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result); 1998 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), double_result);
2219 __ IncrementCounter(counters->math_pow(), 1); 1999 __ IncrementCounter(counters->math_pow(), 1);
2220 __ ret(2 * kPointerSize); 2000 __ ret(2 * kPointerSize);
2221 } else { 2001 } else {
2222 __ bind(&call_runtime); 2002 __ bind(&call_runtime);
2223 // Move base to the correct argument register. Exponent is already in xmm1. 2003 // Move base to the correct argument register. Exponent is already in xmm1.
2224 __ movsd(xmm0, double_base); 2004 __ movsd(xmm0, double_base);
2225 ASSERT(double_exponent.is(xmm1)); 2005 ASSERT(double_exponent.is(xmm1));
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2416 __ bind(&slow); 2196 __ bind(&slow);
2417 __ pop(rbx); // Return address. 2197 __ pop(rbx); // Return address.
2418 __ push(rdx); 2198 __ push(rdx);
2419 __ push(rbx); 2199 __ push(rbx);
2420 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 2200 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
2421 } 2201 }
2422 2202
2423 2203
2424 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { 2204 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
2425 // Stack layout: 2205 // Stack layout:
2426 // rsp[0] : return address 2206 // rsp[0] : return address
2427 // rsp[8] : number of parameters (tagged) 2207 // rsp[8] : number of parameters (tagged)
2428 // rsp[16] : receiver displacement 2208 // rsp[16] : receiver displacement
2429 // rsp[24] : function 2209 // rsp[24] : function
2430 // Registers used over the whole function: 2210 // Registers used over the whole function:
2431 // rbx: the mapped parameter count (untagged) 2211 // rbx: the mapped parameter count (untagged)
2432 // rax: the allocated object (tagged). 2212 // rax: the allocated object (tagged).
2433 2213
2434 Factory* factory = masm->isolate()->factory(); 2214 Factory* factory = masm->isolate()->factory();
2435 2215
2436 __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize)); 2216 __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize));
2437 // rbx = parameter count (untagged) 2217 // rbx = parameter count (untagged)
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
2632 // Do the runtime call to allocate the arguments object. 2412 // Do the runtime call to allocate the arguments object.
2633 // rcx = argument count (untagged) 2413 // rcx = argument count (untagged)
2634 __ bind(&runtime); 2414 __ bind(&runtime);
2635 __ Integer32ToSmi(rcx, rcx); 2415 __ Integer32ToSmi(rcx, rcx);
2636 __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count. 2416 __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count.
2637 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 2417 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2638 } 2418 }
2639 2419
2640 2420
2641 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { 2421 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
2642 // esp[0] : return address 2422 // rsp[0] : return address
2643 // esp[8] : number of parameters 2423 // rsp[8] : number of parameters
2644 // esp[16] : receiver displacement 2424 // rsp[16] : receiver displacement
2645 // esp[24] : function 2425 // rsp[24] : function
2646 2426
2647 // Check if the calling frame is an arguments adaptor frame. 2427 // Check if the calling frame is an arguments adaptor frame.
2648 Label runtime; 2428 Label runtime;
2649 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2429 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2650 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 2430 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2651 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2431 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2652 __ j(not_equal, &runtime); 2432 __ j(not_equal, &runtime);
2653 2433
2654 // Patch the arguments.length and the parameters pointer. 2434 // Patch the arguments.length and the parameters pointer.
2655 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2435 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2656 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 2436 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
2657 __ SmiToInteger64(rcx, rcx); 2437 __ SmiToInteger64(rcx, rcx);
2658 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, 2438 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2659 StandardFrameConstants::kCallerSPOffset)); 2439 StandardFrameConstants::kCallerSPOffset));
2660 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 2440 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2661 2441
2662 __ bind(&runtime); 2442 __ bind(&runtime);
2663 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 2443 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2664 } 2444 }
2665 2445
2666 2446
2667 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { 2447 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
2668 // rsp[0] : return address 2448 // rsp[0] : return address
2669 // rsp[8] : number of parameters 2449 // rsp[8] : number of parameters
2670 // rsp[16] : receiver displacement 2450 // rsp[16] : receiver displacement
2671 // rsp[24] : function 2451 // rsp[24] : function
2672 2452
2673 // Check if the calling frame is an arguments adaptor frame. 2453 // Check if the calling frame is an arguments adaptor frame.
2674 Label adaptor_frame, try_allocate, runtime; 2454 Label adaptor_frame, try_allocate, runtime;
2675 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2455 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2676 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 2456 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2677 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2457 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2678 __ j(equal, &adaptor_frame); 2458 __ j(equal, &adaptor_frame);
2679 2459
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2766 2546
2767 void RegExpExecStub::Generate(MacroAssembler* masm) { 2547 void RegExpExecStub::Generate(MacroAssembler* masm) {
2768 // Just jump directly to runtime if native RegExp is not selected at compile 2548 // Just jump directly to runtime if native RegExp is not selected at compile
2769 // time or if regexp entry in generated code is turned off runtime switch or 2549 // time or if regexp entry in generated code is turned off runtime switch or
2770 // at compilation. 2550 // at compilation.
2771 #ifdef V8_INTERPRETED_REGEXP 2551 #ifdef V8_INTERPRETED_REGEXP
2772 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 2552 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
2773 #else // V8_INTERPRETED_REGEXP 2553 #else // V8_INTERPRETED_REGEXP
2774 2554
2775 // Stack frame on entry. 2555 // Stack frame on entry.
2776 // rsp[0]: return address 2556 // rsp[0] : return address
2777 // rsp[8]: last_match_info (expected JSArray) 2557 // rsp[8] : last_match_info (expected JSArray)
2778 // rsp[16]: previous index 2558 // rsp[16] : previous index
2779 // rsp[24]: subject string 2559 // rsp[24] : subject string
2780 // rsp[32]: JSRegExp object 2560 // rsp[32] : JSRegExp object
2781 2561
2782 static const int kLastMatchInfoOffset = 1 * kPointerSize; 2562 static const int kLastMatchInfoOffset = 1 * kPointerSize;
2783 static const int kPreviousIndexOffset = 2 * kPointerSize; 2563 static const int kPreviousIndexOffset = 2 * kPointerSize;
2784 static const int kSubjectOffset = 3 * kPointerSize; 2564 static const int kSubjectOffset = 3 * kPointerSize;
2785 static const int kJSRegExpOffset = 4 * kPointerSize; 2565 static const int kJSRegExpOffset = 4 * kPointerSize;
2786 2566
2787 Label runtime; 2567 Label runtime;
2788 // Ensure that a RegExp stack is allocated. 2568 // Ensure that a RegExp stack is allocated.
2789 Isolate* isolate = masm->isolate(); 2569 Isolate* isolate = masm->isolate();
2790 ExternalReference address_of_regexp_stack_memory_address = 2570 ExternalReference address_of_regexp_stack_memory_address =
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
3728 // Load the cache state into rcx. 3508 // Load the cache state into rcx.
3729 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); 3509 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
3730 3510
3731 // A monomorphic cache hit or an already megamorphic state: invoke the 3511 // A monomorphic cache hit or an already megamorphic state: invoke the
3732 // function without changing the state. 3512 // function without changing the state.
3733 __ cmpq(rcx, rdi); 3513 __ cmpq(rcx, rdi);
3734 __ j(equal, &done); 3514 __ j(equal, &done);
3735 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); 3515 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate));
3736 __ j(equal, &done); 3516 __ j(equal, &done);
3737 3517
3738 // Special handling of the Array() function, which caches not only the 3518 // If we came here, we need to see if we are the array function.
3739 // monomorphic Array function but the initial ElementsKind with special 3519 // If we didn't have a matching function, and we didn't find the megamorph
3740 // sentinels 3520 // sentinel, then we have in the cell either some other function or an
3741 Handle<Object> terminal_kind_sentinel = 3521 // AllocationSite. Do a map check on the object in rcx.
3742 TypeFeedbackCells::MonomorphicArraySentinel(isolate, 3522 Handle<Map> allocation_site_map(
3743 LAST_FAST_ELEMENTS_KIND); 3523 masm->isolate()->heap()->allocation_site_map(),
3744 __ JumpIfNotSmi(rcx, &miss); 3524 masm->isolate());
3745 __ Cmp(rcx, terminal_kind_sentinel); 3525 __ Cmp(FieldOperand(rcx, 0), allocation_site_map);
3746 __ j(above, &miss); 3526 __ j(not_equal, &miss);
3527
3747 // Make sure the function is the Array() function 3528 // Make sure the function is the Array() function
3748 __ LoadArrayFunction(rcx); 3529 __ LoadArrayFunction(rcx);
3749 __ cmpq(rdi, rcx); 3530 __ cmpq(rdi, rcx);
3750 __ j(not_equal, &megamorphic); 3531 __ j(not_equal, &megamorphic);
3751 __ jmp(&done); 3532 __ jmp(&done);
3752 3533
3753 __ bind(&miss); 3534 __ bind(&miss);
3754 3535
3755 // A monomorphic miss (i.e, here the cache is not uninitialized) goes 3536 // A monomorphic miss (i.e, here the cache is not uninitialized) goes
3756 // megamorphic. 3537 // megamorphic.
3757 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); 3538 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate));
3758 __ j(equal, &initialize); 3539 __ j(equal, &initialize);
3759 // MegamorphicSentinel is an immortal immovable object (undefined) so no 3540 // MegamorphicSentinel is an immortal immovable object (undefined) so no
3760 // write-barrier is needed. 3541 // write-barrier is needed.
3761 __ bind(&megamorphic); 3542 __ bind(&megamorphic);
3762 __ Move(FieldOperand(rbx, Cell::kValueOffset), 3543 __ Move(FieldOperand(rbx, Cell::kValueOffset),
3763 TypeFeedbackCells::MegamorphicSentinel(isolate)); 3544 TypeFeedbackCells::MegamorphicSentinel(isolate));
3764 __ jmp(&done, Label::kNear); 3545 __ jmp(&done);
3765 3546
3766 // An uninitialized cache is patched with the function or sentinel to 3547 // An uninitialized cache is patched with the function or sentinel to
3767 // indicate the ElementsKind if function is the Array constructor. 3548 // indicate the ElementsKind if function is the Array constructor.
3768 __ bind(&initialize); 3549 __ bind(&initialize);
3769 // Make sure the function is the Array() function 3550 // Make sure the function is the Array() function
3770 __ LoadArrayFunction(rcx); 3551 __ LoadArrayFunction(rcx);
3771 __ cmpq(rdi, rcx); 3552 __ cmpq(rdi, rcx);
3772 __ j(not_equal, &not_array_function); 3553 __ j(not_equal, &not_array_function);
3773 3554
3774 // The target function is the Array constructor, install a sentinel value in 3555 // The target function is the Array constructor,
3775 // the constructor's type info cell that will track the initial ElementsKind 3556 // Create an AllocationSite if we don't already have it, store it in the cell
3776 // that should be used for the array when its constructed. 3557 {
3777 Handle<Object> initial_kind_sentinel = 3558 FrameScope scope(masm, StackFrame::INTERNAL);
3778 TypeFeedbackCells::MonomorphicArraySentinel(isolate, 3559
3779 GetInitialFastElementsKind()); 3560 __ push(rax);
3780 __ Move(FieldOperand(rbx, Cell::kValueOffset), 3561 __ push(rdi);
3781 initial_kind_sentinel); 3562 __ push(rbx);
3563
3564 CreateAllocationSiteStub create_stub;
3565 __ CallStub(&create_stub);
3566
3567 __ pop(rbx);
3568 __ pop(rdi);
3569 __ pop(rax);
3570 }
3782 __ jmp(&done); 3571 __ jmp(&done);
3783 3572
3784 __ bind(&not_array_function); 3573 __ bind(&not_array_function);
3785 __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi); 3574 __ movq(FieldOperand(rbx, Cell::kValueOffset), rdi);
3786 // No need for a write barrier here - cells are rescanned. 3575 // No need for a write barrier here - cells are rescanned.
3787 3576
3788 __ bind(&done); 3577 __ bind(&done);
3789 } 3578 }
3790 3579
3791 3580
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3941 } 3730 }
3942 3731
3943 3732
3944 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { 3733 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
3945 CEntryStub::GenerateAheadOfTime(isolate); 3734 CEntryStub::GenerateAheadOfTime(isolate);
3946 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 3735 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
3947 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 3736 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
3948 // It is important that the store buffer overflow stubs are generated first. 3737 // It is important that the store buffer overflow stubs are generated first.
3949 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 3738 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
3950 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 3739 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
3740 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
3951 } 3741 }
3952 3742
3953 3743
3954 void CodeStub::GenerateFPStubs(Isolate* isolate) { 3744 void CodeStub::GenerateFPStubs(Isolate* isolate) {
3955 } 3745 }
3956 3746
3957 3747
3958 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { 3748 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
3959 CEntryStub stub(1, kDontSaveFPRegs); 3749 CEntryStub stub(1, kDontSaveFPRegs);
3960 stub.GetCode(isolate)->set_is_pregenerated(true); 3750 stub.GetCode(isolate)->set_is_pregenerated(true);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
4122 // rbx: pointer to C function (C callee-saved) 3912 // rbx: pointer to C function (C callee-saved)
4123 // rbp: frame pointer of calling JS frame (restored after C call) 3913 // rbp: frame pointer of calling JS frame (restored after C call)
4124 // rsp: stack pointer (restored after C call) 3914 // rsp: stack pointer (restored after C call)
4125 // rsi: current context (restored) 3915 // rsi: current context (restored)
4126 3916
4127 // NOTE: Invocations of builtins may return failure objects 3917 // NOTE: Invocations of builtins may return failure objects
4128 // instead of a proper result. The builtin entry handles 3918 // instead of a proper result. The builtin entry handles
4129 // this by performing a garbage collection and retrying the 3919 // this by performing a garbage collection and retrying the
4130 // builtin once. 3920 // builtin once.
4131 3921
3922 ProfileEntryHookStub::MaybeCallEntryHook(masm);
3923
4132 // Enter the exit frame that transitions from JavaScript to C++. 3924 // Enter the exit frame that transitions from JavaScript to C++.
4133 #ifdef _WIN64 3925 #ifdef _WIN64
4134 int arg_stack_space = (result_size_ < 2 ? 2 : 4); 3926 int arg_stack_space = (result_size_ < 2 ? 2 : 4);
4135 #else 3927 #else
4136 int arg_stack_space = 0; 3928 int arg_stack_space = 0;
4137 #endif 3929 #endif
4138 __ EnterExitFrame(arg_stack_space, save_doubles_); 3930 __ EnterExitFrame(arg_stack_space, save_doubles_);
4139 3931
4140 // rax: Holds the context at this point, but should not be used. 3932 // rax: Holds the context at this point, but should not be used.
4141 // On entry to code generated by GenerateCore, it must hold 3933 // On entry to code generated by GenerateCore, it must hold
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4202 3994
4203 __ bind(&throw_normal_exception); 3995 __ bind(&throw_normal_exception);
4204 __ Throw(rax); 3996 __ Throw(rax);
4205 } 3997 }
4206 3998
4207 3999
4208 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 4000 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
4209 Label invoke, handler_entry, exit; 4001 Label invoke, handler_entry, exit;
4210 Label not_outermost_js, not_outermost_js_2; 4002 Label not_outermost_js, not_outermost_js_2;
4211 4003
4004 ProfileEntryHookStub::MaybeCallEntryHook(masm);
4005
4212 { // NOLINT. Scope block confuses linter. 4006 { // NOLINT. Scope block confuses linter.
4213 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 4007 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
4214 // Set up frame. 4008 // Set up frame.
4215 __ push(rbp); 4009 __ push(rbp);
4216 __ movq(rbp, rsp); 4010 __ movq(rbp, rsp);
4217 4011
4218 // Push the stack frame type marker twice. 4012 // Push the stack frame type marker twice.
4219 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 4013 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
4220 // Scratch register is neither callee-save, nor an argument register on any 4014 // Scratch register is neither callee-save, nor an argument register on any
4221 // platform. It's free to use at this point. 4015 // platform. It's free to use at this point.
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
4368 4162
4369 // Restore frame pointer and return. 4163 // Restore frame pointer and return.
4370 __ pop(rbp); 4164 __ pop(rbp);
4371 __ ret(0); 4165 __ ret(0);
4372 } 4166 }
4373 4167
4374 4168
4375 void InstanceofStub::Generate(MacroAssembler* masm) { 4169 void InstanceofStub::Generate(MacroAssembler* masm) {
4376 // Implements "value instanceof function" operator. 4170 // Implements "value instanceof function" operator.
4377 // Expected input state with no inline cache: 4171 // Expected input state with no inline cache:
4378 // rsp[0] : return address 4172 // rsp[0] : return address
4379 // rsp[1] : function pointer 4173 // rsp[8] : function pointer
4380 // rsp[2] : value 4174 // rsp[16] : value
4381 // Expected input state with an inline one-element cache: 4175 // Expected input state with an inline one-element cache:
4382 // rsp[0] : return address 4176 // rsp[0] : return address
4383 // rsp[1] : offset from return address to location of inline cache 4177 // rsp[8] : offset from return address to location of inline cache
4384 // rsp[2] : function pointer 4178 // rsp[16] : function pointer
4385 // rsp[3] : value 4179 // rsp[24] : value
4386 // Returns a bitwise zero to indicate that the value 4180 // Returns a bitwise zero to indicate that the value
4387 // is and instance of the function and anything else to 4181 // is and instance of the function and anything else to
4388 // indicate that the value is not an instance. 4182 // indicate that the value is not an instance.
4389 4183
4390 static const int kOffsetToMapCheckValue = 2; 4184 static const int kOffsetToMapCheckValue = 2;
4391 static const int kOffsetToResultValue = 18; 4185 static const int kOffsetToResultValue = 18;
4392 // The last 4 bytes of the instruction sequence 4186 // The last 4 bytes of the instruction sequence
4393 // movq(rdi, FieldOperand(rax, HeapObject::kMapOffset)) 4187 // movq(rdi, FieldOperand(rax, HeapObject::kMapOffset))
4394 // Move(kScratchRegister, Factory::the_hole_value()) 4188 // Move(kScratchRegister, Factory::the_hole_value())
4395 // in front of the hole value address. 4189 // in front of the hole value address.
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
5097 __ j(zero, &done, Label::kNear); 4891 __ j(zero, &done, Label::kNear);
5098 4892
5099 // Make count the number of bytes to copy. 4893 // Make count the number of bytes to copy.
5100 if (!ascii) { 4894 if (!ascii) {
5101 STATIC_ASSERT(2 == sizeof(uc16)); 4895 STATIC_ASSERT(2 == sizeof(uc16));
5102 __ addl(count, count); 4896 __ addl(count, count);
5103 } 4897 }
5104 4898
5105 // Don't enter the rep movs if there are less than 4 bytes to copy. 4899 // Don't enter the rep movs if there are less than 4 bytes to copy.
5106 Label last_bytes; 4900 Label last_bytes;
5107 __ testl(count, Immediate(~7)); 4901 __ testl(count, Immediate(~(kPointerSize - 1)));
5108 __ j(zero, &last_bytes, Label::kNear); 4902 __ j(zero, &last_bytes, Label::kNear);
5109 4903
5110 // Copy from edi to esi using rep movs instruction. 4904 // Copy from edi to esi using rep movs instruction.
5111 __ movl(kScratchRegister, count); 4905 __ movl(kScratchRegister, count);
5112 __ shr(count, Immediate(3)); // Number of doublewords to copy. 4906 __ shr(count, Immediate(kPointerSizeLog2)); // Number of doublewords to copy.
5113 __ repmovsq(); 4907 __ repmovsq();
5114 4908
5115 // Find number of bytes left. 4909 // Find number of bytes left.
5116 __ movl(count, kScratchRegister); 4910 __ movl(count, kScratchRegister);
5117 __ and_(count, Immediate(7)); 4911 __ and_(count, Immediate(kPointerSize - 1));
5118 4912
5119 // Check if there are more bytes to copy. 4913 // Check if there are more bytes to copy.
5120 __ bind(&last_bytes); 4914 __ bind(&last_bytes);
5121 __ testl(count, count); 4915 __ testl(count, count);
5122 __ j(zero, &done, Label::kNear); 4916 __ j(zero, &done, Label::kNear);
5123 4917
5124 // Copy remaining characters. 4918 // Copy remaining characters.
5125 Label loop; 4919 Label loop;
5126 __ bind(&loop); 4920 __ bind(&loop);
5127 __ movb(kScratchRegister, Operand(src, 0)); 4921 __ movb(kScratchRegister, Operand(src, 0));
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
5313 5107
5314 __ andl(hash, Immediate(String::kHashBitMask)); 5108 __ andl(hash, Immediate(String::kHashBitMask));
5315 5109
5316 // if (hash == 0) hash = 27; 5110 // if (hash == 0) hash = 27;
5317 Label hash_not_zero; 5111 Label hash_not_zero;
5318 __ j(not_zero, &hash_not_zero); 5112 __ j(not_zero, &hash_not_zero);
5319 __ Set(hash, StringHasher::kZeroHash); 5113 __ Set(hash, StringHasher::kZeroHash);
5320 __ bind(&hash_not_zero); 5114 __ bind(&hash_not_zero);
5321 } 5115 }
5322 5116
5117
5323 void SubStringStub::Generate(MacroAssembler* masm) { 5118 void SubStringStub::Generate(MacroAssembler* masm) {
5324 Label runtime; 5119 Label runtime;
5325 5120
5326 // Stack frame on entry. 5121 // Stack frame on entry.
5327 // rsp[0]: return address 5122 // rsp[0] : return address
5328 // rsp[8]: to 5123 // rsp[8] : to
5329 // rsp[16]: from 5124 // rsp[16] : from
5330 // rsp[24]: string 5125 // rsp[24] : string
5331 5126
5332 const int kToOffset = 1 * kPointerSize; 5127 const int kToOffset = 1 * kPointerSize;
5333 const int kFromOffset = kToOffset + kPointerSize; 5128 const int kFromOffset = kToOffset + kPointerSize;
5334 const int kStringOffset = kFromOffset + kPointerSize; 5129 const int kStringOffset = kFromOffset + kPointerSize;
5335 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; 5130 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset;
5336 5131
5337 // Make sure first argument is a string. 5132 // Make sure first argument is a string.
5338 __ movq(rax, Operand(rsp, kStringOffset)); 5133 __ movq(rax, Operand(rsp, kStringOffset));
5339 STATIC_ASSERT(kSmiTag == 0); 5134 STATIC_ASSERT(kSmiTag == 0);
5340 __ testl(rax, Immediate(kSmiTagMask)); 5135 __ testl(rax, Immediate(kSmiTagMask));
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
5679 __ j(not_equal, chars_not_equal, near_jump); 5474 __ j(not_equal, chars_not_equal, near_jump);
5680 __ incq(index); 5475 __ incq(index);
5681 __ j(not_zero, &loop); 5476 __ j(not_zero, &loop);
5682 } 5477 }
5683 5478
5684 5479
5685 void StringCompareStub::Generate(MacroAssembler* masm) { 5480 void StringCompareStub::Generate(MacroAssembler* masm) {
5686 Label runtime; 5481 Label runtime;
5687 5482
5688 // Stack frame on entry. 5483 // Stack frame on entry.
5689 // rsp[0]: return address 5484 // rsp[0] : return address
5690 // rsp[8]: right string 5485 // rsp[8] : right string
5691 // rsp[16]: left string 5486 // rsp[16] : left string
5692 5487
5693 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left 5488 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // left
5694 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right 5489 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // right
5695 5490
5696 // Check for identity. 5491 // Check for identity.
5697 Label not_same; 5492 Label not_same;
5698 __ cmpq(rdx, rax); 5493 __ cmpq(rdx, rax);
5699 __ j(not_equal, &not_same, Label::kNear); 5494 __ j(not_equal, &not_same, Label::kNear);
5700 __ Move(rax, Smi::FromInt(EQUAL)); 5495 __ Move(rax, Smi::FromInt(EQUAL));
5701 Counters* counters = masm->isolate()->counters(); 5496 Counters* counters = masm->isolate()->counters();
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
6178 __ testq(r0, r0); 5973 __ testq(r0, r0);
6179 __ j(zero, miss); 5974 __ j(zero, miss);
6180 __ jmp(done); 5975 __ jmp(done);
6181 } 5976 }
6182 5977
6183 5978
6184 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) { 5979 void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
6185 // This stub overrides SometimesSetsUpAFrame() to return false. That means 5980 // This stub overrides SometimesSetsUpAFrame() to return false. That means
6186 // we cannot call anything that could cause a GC from this stub. 5981 // we cannot call anything that could cause a GC from this stub.
6187 // Stack frame on entry: 5982 // Stack frame on entry:
6188 // esp[0 * kPointerSize]: return address. 5983 // rsp[0 * kPointerSize] : return address.
6189 // esp[1 * kPointerSize]: key's hash. 5984 // rsp[1 * kPointerSize] : key's hash.
6190 // esp[2 * kPointerSize]: key. 5985 // rsp[2 * kPointerSize] : key.
6191 // Registers: 5986 // Registers:
6192 // dictionary_: NameDictionary to probe. 5987 // dictionary_: NameDictionary to probe.
6193 // result_: used as scratch. 5988 // result_: used as scratch.
6194 // index_: will hold an index of entry if lookup is successful. 5989 // index_: will hold an index of entry if lookup is successful.
6195 // might alias with result_. 5990 // might alias with result_.
6196 // Returns: 5991 // Returns:
6197 // result_ is zero if lookup failed, non zero otherwise. 5992 // result_ is zero if lookup failed, non zero otherwise.
6198 5993
6199 Label in_dictionary, maybe_in_dictionary, not_in_dictionary; 5994 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
6200 5995
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
6561 __ pop(regs_.object()); 6356 __ pop(regs_.object());
6562 6357
6563 __ bind(&need_incremental); 6358 __ bind(&need_incremental);
6564 6359
6565 // Fall through when we need to inform the incremental marker. 6360 // Fall through when we need to inform the incremental marker.
6566 } 6361 }
6567 6362
6568 6363
6569 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { 6364 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
6570 // ----------- S t a t e ------------- 6365 // ----------- S t a t e -------------
6571 // -- rax : element value to store 6366 // -- rax : element value to store
6572 // -- rcx : element index as smi 6367 // -- rcx : element index as smi
6573 // -- rsp[0] : return address 6368 // -- rsp[0] : return address
6574 // -- rsp[8] : array literal index in function 6369 // -- rsp[8] : array literal index in function
6575 // -- rsp[16]: array literal 6370 // -- rsp[16] : array literal
6576 // clobbers rbx, rdx, rdi 6371 // clobbers rbx, rdx, rdi
6577 // ----------------------------------- 6372 // -----------------------------------
6578 6373
6579 Label element_done; 6374 Label element_done;
6580 Label double_elements; 6375 Label double_elements;
6581 Label smi_element; 6376 Label smi_element;
6582 Label slow_elements; 6377 Label slow_elements;
6583 Label fast_elements; 6378 Label fast_elements;
6584 6379
6585 // Get array literal index, array literal and its map. 6380 // Get array literal index, array literal and its map.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
6656 __ pop(rcx); 6451 __ pop(rcx);
6657 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE 6452 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE
6658 ? kPointerSize 6453 ? kPointerSize
6659 : 0; 6454 : 0;
6660 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); 6455 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset));
6661 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. 6456 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack.
6662 } 6457 }
6663 6458
6664 6459
6665 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { 6460 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
6666 if (entry_hook_ != NULL) { 6461 if (masm->isolate()->function_entry_hook() != NULL) {
6462 // It's always safe to call the entry hook stub, as the hook itself
6463 // is not allowed to call back to V8.
6464 AllowStubCallsScope allow_stub_calls(masm, true);
6465
6667 ProfileEntryHookStub stub; 6466 ProfileEntryHookStub stub;
6668 masm->CallStub(&stub); 6467 masm->CallStub(&stub);
6669 } 6468 }
6670 } 6469 }
6671 6470
6672 6471
6673 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { 6472 void ProfileEntryHookStub::Generate(MacroAssembler* masm) {
6674 // Save volatile registers. 6473 // This stub can be called from essentially anywhere, so it needs to save
6675 // Live registers at this point are the same as at the start of any 6474 // all volatile and callee-save registers.
6676 // JS function: 6475 const size_t kNumSavedRegisters = 2;
6677 // o rdi: the JS function object being called (i.e. ourselves) 6476 __ push(arg_reg_1);
6678 // o rsi: our context 6477 __ push(arg_reg_2);
6679 // o rbp: our caller's frame pointer
6680 // o rsp: stack pointer (pointing to return address)
6681 // o rcx: rcx is zero for method calls and non-zero for function calls.
6682 #ifdef _WIN64
6683 const int kNumSavedRegisters = 1;
6684
6685 __ push(rcx);
6686 #else
6687 const int kNumSavedRegisters = 3;
6688
6689 __ push(rcx);
6690 __ push(rdi);
6691 __ push(rsi);
6692 #endif
6693 6478
6694 // Calculate the original stack pointer and store it in the second arg. 6479 // Calculate the original stack pointer and store it in the second arg.
6695 #ifdef _WIN64 6480 __ lea(arg_reg_2, Operand(rsp, (kNumSavedRegisters + 1) * kPointerSize));
6696 __ lea(rdx, Operand(rsp, (kNumSavedRegisters + 1) * kPointerSize));
6697 #else
6698 __ lea(rsi, Operand(rsp, (kNumSavedRegisters + 1) * kPointerSize));
6699 #endif
6700 6481
6701 // Calculate the function address to the first arg. 6482 // Calculate the function address to the first arg.
6702 #ifdef _WIN64 6483 __ movq(arg_reg_1, Operand(rsp, kNumSavedRegisters * kPointerSize));
6703 __ movq(rcx, Operand(rsp, kNumSavedRegisters * kPointerSize)); 6484 __ subq(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
6704 __ subq(rcx, Immediate(Assembler::kShortCallInstructionLength)); 6485
6705 #else 6486 // Save the remainder of the volatile registers.
6706 __ movq(rdi, Operand(rsp, kNumSavedRegisters * kPointerSize)); 6487 masm->PushCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2);
6707 __ subq(rdi, Immediate(Assembler::kShortCallInstructionLength));
6708 #endif
6709 6488
6710 // Call the entry hook function. 6489 // Call the entry hook function.
6711 __ movq(rax, &entry_hook_, RelocInfo::NONE64); 6490 __ movq(rax, FUNCTION_ADDR(masm->isolate()->function_entry_hook()),
6712 __ movq(rax, Operand(rax, 0)); 6491 RelocInfo::NONE64);
6713 6492
6714 AllowExternalCallThatCantCauseGC scope(masm); 6493 AllowExternalCallThatCantCauseGC scope(masm);
6715 6494
6716 const int kArgumentCount = 2; 6495 const int kArgumentCount = 2;
6717 __ PrepareCallCFunction(kArgumentCount); 6496 __ PrepareCallCFunction(kArgumentCount);
6718 __ CallCFunction(rax, kArgumentCount); 6497 __ CallCFunction(rax, kArgumentCount);
6719 6498
6720 // Restore volatile regs. 6499 // Restore volatile regs.
6721 #ifdef _WIN64 6500 masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2);
6722 __ pop(rcx); 6501 __ pop(arg_reg_2);
6723 #else 6502 __ pop(arg_reg_1);
6724 __ pop(rsi);
6725 __ pop(rdi);
6726 __ pop(rcx);
6727 #endif
6728 6503
6729 __ Ret(); 6504 __ Ret();
6730 } 6505 }
6731 6506
6732 6507
6733 template<class T> 6508 template<class T>
6734 static void CreateArrayDispatch(MacroAssembler* masm) { 6509 static void CreateArrayDispatch(MacroAssembler* masm) {
6735 int last_index = GetSequenceIndexFromFastElementsKind( 6510 int last_index = GetSequenceIndexFromFastElementsKind(
6736 TERMINAL_FAST_ELEMENTS_KIND); 6511 TERMINAL_FAST_ELEMENTS_KIND);
6737 for (int i = 0; i <= last_index; ++i) { 6512 for (int i = 0; i <= last_index; ++i) {
6738 Label next; 6513 Label next;
6739 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6514 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6740 __ cmpl(rdx, Immediate(kind)); 6515 __ cmpl(rdx, Immediate(kind));
6741 __ j(not_equal, &next); 6516 __ j(not_equal, &next);
6742 T stub(kind); 6517 T stub(kind);
6743 __ TailCallStub(&stub); 6518 __ TailCallStub(&stub);
6744 __ bind(&next); 6519 __ bind(&next);
6745 } 6520 }
6746 6521
6747 // If we reached this point there is a problem. 6522 // If we reached this point there is a problem.
6748 __ Abort("Unexpected ElementsKind in array constructor"); 6523 __ Abort("Unexpected ElementsKind in array constructor");
6749 } 6524 }
6750 6525
6751 6526
6752 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { 6527 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) {
6753 // rbx - type info cell 6528 // rbx - type info cell
6754 // rdx - kind 6529 // rdx - kind
6755 // rax - number of arguments 6530 // rax - number of arguments
6756 // rdi - constructor? 6531 // rdi - constructor?
6757 // esp[0] - return address 6532 // rsp[0] - return address
6758 // esp[4] - last argument 6533 // rsp[8] - last argument
6759 ASSERT(FAST_SMI_ELEMENTS == 0); 6534 ASSERT(FAST_SMI_ELEMENTS == 0);
6760 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); 6535 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
6761 ASSERT(FAST_ELEMENTS == 2); 6536 ASSERT(FAST_ELEMENTS == 2);
6762 ASSERT(FAST_HOLEY_ELEMENTS == 3); 6537 ASSERT(FAST_HOLEY_ELEMENTS == 3);
6763 ASSERT(FAST_DOUBLE_ELEMENTS == 4); 6538 ASSERT(FAST_DOUBLE_ELEMENTS == 4);
6764 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); 6539 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5);
6765 6540
6766 Handle<Object> undefined_sentinel( 6541 Handle<Object> undefined_sentinel(
6767 masm->isolate()->heap()->undefined_value(), 6542 masm->isolate()->heap()->undefined_value(),
6768 masm->isolate()); 6543 masm->isolate());
6769 6544
6770 // is the low bit set? If so, we are holey and that is good. 6545 // is the low bit set? If so, we are holey and that is good.
6771 __ testb(rdx, Immediate(1)); 6546 __ testb(rdx, Immediate(1));
6772 Label normal_sequence; 6547 Label normal_sequence;
6773 __ j(not_zero, &normal_sequence); 6548 __ j(not_zero, &normal_sequence);
6774 6549
6775 // look at the first argument 6550 // look at the first argument
6776 __ movq(rcx, Operand(rsp, kPointerSize)); 6551 __ movq(rcx, Operand(rsp, kPointerSize));
6777 __ testq(rcx, rcx); 6552 __ testq(rcx, rcx);
6778 __ j(zero, &normal_sequence); 6553 __ j(zero, &normal_sequence);
6779 6554
6780 // We are going to create a holey array, but our kind is non-holey. 6555 // We are going to create a holey array, but our kind is non-holey.
6781 // Fix kind and retry 6556 // Fix kind and retry (only if we have an allocation site in the cell).
6782 __ incl(rdx); 6557 __ incl(rdx);
6783 __ Cmp(rbx, undefined_sentinel); 6558 __ Cmp(rbx, undefined_sentinel);
6784 __ j(equal, &normal_sequence); 6559 __ j(equal, &normal_sequence);
6560 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset));
6561 Handle<Map> allocation_site_map(
6562 masm->isolate()->heap()->allocation_site_map(),
6563 masm->isolate());
6564 __ Cmp(FieldOperand(rcx, 0), allocation_site_map);
6565 __ j(not_equal, &normal_sequence);
6785 6566
6786 // Save the resulting elements kind in type info 6567 // Save the resulting elements kind in type info
6787 __ Integer32ToSmi(rdx, rdx); 6568 __ Integer32ToSmi(rdx, rdx);
6788 __ movq(FieldOperand(rbx, kPointerSize), rdx); 6569 __ movq(FieldOperand(rcx, AllocationSite::kPayloadOffset), rdx);
6789 __ SmiToInteger32(rdx, rdx); 6570 __ SmiToInteger32(rdx, rdx);
6790 6571
6791 __ bind(&normal_sequence); 6572 __ bind(&normal_sequence);
6792 int last_index = GetSequenceIndexFromFastElementsKind( 6573 int last_index = GetSequenceIndexFromFastElementsKind(
6793 TERMINAL_FAST_ELEMENTS_KIND); 6574 TERMINAL_FAST_ELEMENTS_KIND);
6794 for (int i = 0; i <= last_index; ++i) { 6575 for (int i = 0; i <= last_index; ++i) {
6795 Label next; 6576 Label next;
6796 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6577 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6797 __ cmpl(rdx, Immediate(kind)); 6578 __ cmpl(rdx, Immediate(kind));
6798 __ j(not_equal, &next); 6579 __ j(not_equal, &next);
6799 ArraySingleArgumentConstructorStub stub(kind); 6580 ArraySingleArgumentConstructorStub stub(kind);
6800 __ TailCallStub(&stub); 6581 __ TailCallStub(&stub);
6801 __ bind(&next); 6582 __ bind(&next);
6802 } 6583 }
6803 6584
6804 // If we reached this point there is a problem. 6585 // If we reached this point there is a problem.
6805 __ Abort("Unexpected ElementsKind in array constructor"); 6586 __ Abort("Unexpected ElementsKind in array constructor");
6806 } 6587 }
6807 6588
6808 6589
6809 template<class T> 6590 template<class T>
6810 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { 6591 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) {
6811 int to_index = GetSequenceIndexFromFastElementsKind( 6592 int to_index = GetSequenceIndexFromFastElementsKind(
6812 TERMINAL_FAST_ELEMENTS_KIND); 6593 TERMINAL_FAST_ELEMENTS_KIND);
6813 for (int i = 0; i <= to_index; ++i) { 6594 for (int i = 0; i <= to_index; ++i) {
6814 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); 6595 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i);
6815 T stub(kind); 6596 T stub(kind);
6816 stub.GetCode(isolate)->set_is_pregenerated(true); 6597 stub.GetCode(isolate)->set_is_pregenerated(true);
6817 if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { 6598 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) {
6818 T stub1(kind, true); 6599 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES);
6819 stub1.GetCode(isolate)->set_is_pregenerated(true); 6600 stub1.GetCode(isolate)->set_is_pregenerated(true);
6820 } 6601 }
6821 } 6602 }
6822 } 6603 }
6823 6604
6824 6605
6825 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { 6606 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) {
6826 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( 6607 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>(
6827 isolate); 6608 isolate);
6828 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( 6609 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>(
(...skipping 13 matching lines...) Expand all
6842 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); 6623 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]);
6843 stubh2.GetCode(isolate)->set_is_pregenerated(true); 6624 stubh2.GetCode(isolate)->set_is_pregenerated(true);
6844 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); 6625 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]);
6845 stubh3.GetCode(isolate)->set_is_pregenerated(true); 6626 stubh3.GetCode(isolate)->set_is_pregenerated(true);
6846 } 6627 }
6847 } 6628 }
6848 6629
6849 6630
6850 void ArrayConstructorStub::Generate(MacroAssembler* masm) { 6631 void ArrayConstructorStub::Generate(MacroAssembler* masm) {
6851 // ----------- S t a t e ------------- 6632 // ----------- S t a t e -------------
6852 // -- rax : argc 6633 // -- rax : argc
6853 // -- rbx : type info cell 6634 // -- rbx : type info cell
6854 // -- rdi : constructor 6635 // -- rdi : constructor
6855 // -- rsp[0] : return address 6636 // -- rsp[0] : return address
6856 // -- rsp[4] : last argument 6637 // -- rsp[8] : last argument
6857 // ----------------------------------- 6638 // -----------------------------------
6858 Handle<Object> undefined_sentinel( 6639 Handle<Object> undefined_sentinel(
6859 masm->isolate()->heap()->undefined_value(), 6640 masm->isolate()->heap()->undefined_value(),
6860 masm->isolate()); 6641 masm->isolate());
6861 6642
6862 if (FLAG_debug_code) { 6643 if (FLAG_debug_code) {
6863 // The array construct code is only set for the global and natives 6644 // The array construct code is only set for the global and natives
6864 // builtin Array functions which always have maps. 6645 // builtin Array functions which always have maps.
6865 6646
6866 // Initial map for the builtin Array function should be a map. 6647 // Initial map for the builtin Array function should be a map.
6867 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 6648 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
6868 // Will both indicate a NULL and a Smi. 6649 // Will both indicate a NULL and a Smi.
6869 STATIC_ASSERT(kSmiTag == 0); 6650 STATIC_ASSERT(kSmiTag == 0);
6870 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); 6651 Condition not_smi = NegateCondition(masm->CheckSmi(rcx));
6871 __ Check(not_smi, "Unexpected initial map for Array function"); 6652 __ Check(not_smi, "Unexpected initial map for Array function");
6872 __ CmpObjectType(rcx, MAP_TYPE, rcx); 6653 __ CmpObjectType(rcx, MAP_TYPE, rcx);
6873 __ Check(equal, "Unexpected initial map for Array function"); 6654 __ Check(equal, "Unexpected initial map for Array function");
6874 6655
6875 // We should either have undefined in ebx or a valid cell 6656 // We should either have undefined in rbx or a valid cell
6876 Label okay_here; 6657 Label okay_here;
6877 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); 6658 Handle<Map> cell_map = masm->isolate()->factory()->cell_map();
6878 __ Cmp(rbx, undefined_sentinel); 6659 __ Cmp(rbx, undefined_sentinel);
6879 __ j(equal, &okay_here); 6660 __ j(equal, &okay_here);
6880 __ Cmp(FieldOperand(rbx, 0), cell_map); 6661 __ Cmp(FieldOperand(rbx, 0), cell_map);
6881 __ Assert(equal, "Expected property cell in register rbx"); 6662 __ Assert(equal, "Expected property cell in register rbx");
6882 __ bind(&okay_here); 6663 __ bind(&okay_here);
6883 } 6664 }
6884 6665
6885 Label no_info, switch_ready; 6666 Label no_info, switch_ready;
6886 // Get the elements kind and case on that. 6667 // Get the elements kind and case on that.
6887 __ Cmp(rbx, undefined_sentinel); 6668 __ Cmp(rbx, undefined_sentinel);
6888 __ j(equal, &no_info); 6669 __ j(equal, &no_info);
6889 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); 6670 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset));
6890 __ JumpIfNotSmi(rdx, &no_info); 6671
6672 // The type cell may have undefined in its value.
6673 __ Cmp(rdx, undefined_sentinel);
6674 __ j(equal, &no_info);
6675
6676 // We should have an allocation site object
6677 if (FLAG_debug_code) {
6678 __ Cmp(FieldOperand(rdx, 0),
6679 Handle<Map>(masm->isolate()->heap()->allocation_site_map()));
6680 __ Assert(equal, "Expected AllocationSite object in register rdx");
6681 }
6682
6683 __ movq(rdx, FieldOperand(rdx, AllocationSite::kPayloadOffset));
6891 __ SmiToInteger32(rdx, rdx); 6684 __ SmiToInteger32(rdx, rdx);
6892 __ jmp(&switch_ready); 6685 __ jmp(&switch_ready);
6893 __ bind(&no_info); 6686 __ bind(&no_info);
6894 __ movq(rdx, Immediate(GetInitialFastElementsKind())); 6687 __ movq(rdx, Immediate(GetInitialFastElementsKind()));
6895 __ bind(&switch_ready); 6688 __ bind(&switch_ready);
6896 6689
6897 if (argument_count_ == ANY) { 6690 if (argument_count_ == ANY) {
6898 Label not_zero_case, not_one_case; 6691 Label not_zero_case, not_one_case;
6899 __ testq(rax, rax); 6692 __ testq(rax, rax);
6900 __ j(not_zero, &not_zero_case); 6693 __ j(not_zero, &not_zero_case);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6950 __ TailCallStub(&stub1); 6743 __ TailCallStub(&stub1);
6951 6744
6952 __ bind(&not_one_case); 6745 __ bind(&not_one_case);
6953 InternalArrayNArgumentsConstructorStub stubN(kind); 6746 InternalArrayNArgumentsConstructorStub stubN(kind);
6954 __ TailCallStub(&stubN); 6747 __ TailCallStub(&stubN);
6955 } 6748 }
6956 6749
6957 6750
6958 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { 6751 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
6959 // ----------- S t a t e ------------- 6752 // ----------- S t a t e -------------
6960 // -- eax : argc 6753 // -- rax : argc
6961 // -- ebx : type info cell 6754 // -- rbx : type info cell
6962 // -- edi : constructor 6755 // -- rdi : constructor
6963 // -- esp[0] : return address 6756 // -- rsp[0] : return address
6964 // -- esp[4] : last argument 6757 // -- rsp[8] : last argument
6965 // ----------------------------------- 6758 // -----------------------------------
6966 6759
6967 if (FLAG_debug_code) { 6760 if (FLAG_debug_code) {
6968 // The array construct code is only set for the global and natives 6761 // The array construct code is only set for the global and natives
6969 // builtin Array functions which always have maps. 6762 // builtin Array functions which always have maps.
6970 6763
6971 // Initial map for the builtin Array function should be a map. 6764 // Initial map for the builtin Array function should be a map.
6972 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 6765 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset));
6973 // Will both indicate a NULL and a Smi. 6766 // Will both indicate a NULL and a Smi.
6974 STATIC_ASSERT(kSmiTag == 0); 6767 STATIC_ASSERT(kSmiTag == 0);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
7006 __ bind(&fast_elements_case); 6799 __ bind(&fast_elements_case);
7007 GenerateCase(masm, FAST_ELEMENTS); 6800 GenerateCase(masm, FAST_ELEMENTS);
7008 } 6801 }
7009 6802
7010 6803
7011 #undef __ 6804 #undef __
7012 6805
7013 } } // namespace v8::internal 6806 } } // namespace v8::internal
7014 6807
7015 #endif // V8_TARGET_ARCH_X64 6808 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698