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

Side by Side Diff: runtime/vm/stub_code_x64.cc

Issue 9114054: Port a couple more stubs to x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/ic_data.h" 10 #include "vm/ic_data.h"
11 #include "vm/object_store.h" 11 #include "vm/object_store.h"
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); 669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset()));
670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); 670 __ movq(RBX, Address(RBX, Isolate::object_store_offset()));
671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); 671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset()));
672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); 672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX);
673 // Calculate the size tag. 673 // Calculate the size tag.
674 // RAX: new object start as a tagged pointer. 674 // RAX: new object start as a tagged pointer.
675 // R12: new object end address. 675 // R12: new object end address.
676 // R10: Array length as Smi. 676 // R10: Array length as Smi.
677 { 677 {
678 Label size_tag_overflow, done; 678 Label size_tag_overflow, done;
679 __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi. 679 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi.
680 ASSERT(kSmiTagShift == 1); 680 ASSERT(kSmiTagShift == 1);
681 __ andq(RBX, Immediate(-kObjectAlignment)); 681 __ andq(RBX, Immediate(-kObjectAlignment));
682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); 682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag));
683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); 683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); 684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2));
685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); 685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX);
686 __ jmp(&done); 686 __ jmp(&done);
687 687
688 __ Bind(&size_tag_overflow); 688 __ Bind(&size_tag_overflow);
689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); 689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0));
690 __ Bind(&done); 690 __ Bind(&done);
691 } 691 }
692 692
693 // Initialize all array elements to raw_null. 693 // Initialize all array elements to raw_null.
694 // RAX: new object start as a tagged pointer. 694 // RAX: new object start as a tagged pointer.
695 // R12: new object end address. 695 // R12: new object end address.
696 __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
696 // RBX: iterator which initially points to the start of the variable 697 // RBX: iterator which initially points to the start of the variable
697 // data area to be initialized. 698 // data area to be initialized.
698 __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
699 Label done; 699 Label done;
700 Label init_loop; 700 Label init_loop;
701 __ Bind(&init_loop); 701 __ Bind(&init_loop);
702 __ cmpq(RBX, R12); 702 __ cmpq(RBX, R12);
703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
704 __ movq(Address(RBX, 0), raw_null); 704 __ movq(Address(RBX, 0), raw_null);
705 __ addq(RBX, Immediate(kWordSize)); 705 __ addq(RBX, Immediate(kWordSize));
706 __ jmp(&init_loop, Assembler::kNearJump); 706 __ jmp(&init_loop, Assembler::kNearJump);
707 __ Bind(&done); 707 __ Bind(&done);
708 708
(...skipping 14 matching lines...) Expand all
723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); 723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry);
724 __ popq(RAX); // Pop instantiator. 724 __ popq(RAX); // Pop instantiator.
725 __ popq(RAX); // Pop element type argument. 725 __ popq(RAX); // Pop element type argument.
726 __ popq(R10); // Pop array length argument. 726 __ popq(R10); // Pop array length argument.
727 __ popq(RAX); // Pop return value from return slot. 727 __ popq(RAX); // Pop return value from return slot.
728 __ LeaveFrame(); 728 __ LeaveFrame();
729 __ ret(); 729 __ ret();
730 } 730 }
731 731
732 732
733 // Input parameters:
734 // R10: Arguments descriptor array (num_args is first Smi element, closure
735 // object is not included in num_args).
736 // Note: The closure object is pushed before the first argument to the function
737 // being called, the stub accesses the closure from this location directly
738 // when setting up the context and resolving the entry point.
739 // Uses R13.
733 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 740 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
734 __ Unimplemented("CallClosureFunction stub"); 741 const Immediate raw_null =
742 Immediate(reinterpret_cast<intptr_t>(Object::null()));
743
744 // Total number of args is the first Smi in args descriptor array (R10).
745 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args.
746 // Load closure object in R13.
747 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi.
748
749 // Verify that R13 is a closure by checking its class.
750 Label not_closure;
751 __ cmpq(R13, raw_null);
752 // Not a closure, but null object.
753 __ j(EQUAL, &not_closure, Assembler::kNearJump);
754 __ testq(R13, Immediate(kSmiTagMask));
755 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi.
756 // Verify that the class of the object is a closure class by checking that
757 // class.signature_function() is not null.
758 __ movq(RAX, FieldAddress(R13, Object::class_offset()));
759 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset()));
760 __ cmpq(RAX, raw_null);
761 // Actual class is not a closure class.
762 __ j(EQUAL, &not_closure, Assembler::kNearJump);
763
764 // RAX is just the signature function. Load the actual closure function.
765 __ movq(RBX, FieldAddress(R13, Closure::function_offset()));
766
767 // Load closure context in CTX; note that CTX has already been preserved.
768 __ movq(CTX, FieldAddress(R13, Closure::context_offset()));
769
770 // Load closure function code in RAX.
771 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
772 __ cmpq(RAX, raw_null);
773 Label function_compiled;
774 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump);
775
776 // Create a stub frame as we are pushing some objects on the stack before
777 // calling into the runtime.
778 __ EnterFrame(0);
779
780 __ pushq(R10); // Preserve arguments descriptor array.
781 __ pushq(RBX);
782 __ CallRuntimeFromStub(kCompileFunctionRuntimeEntry);
783 __ popq(RBX); // Restore read-only function object argument in RBX.
784 __ popq(R10); // Restore arguments descriptor array.
785 // Restore RAX.
786 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
787
788 // Remove the stub frame as we are about to jump to the closure function.
789 __ LeaveFrame();
790
791 __ Bind(&function_compiled);
792 // RAX: Code.
793 // RBX: Function.
794 // R10: Arguments descriptor array (num_args is first Smi element).
795
796 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
797 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
798 __ jmp(RBX);
799
800 __ Bind(&not_closure);
801 // Call runtime to report that a closure call was attempted on a non-closure
802 // object, passing the non-closure object and its arguments array.
803 // R13: non-closure object.
804 // R10: arguments descriptor array (num_args is first Smi element, closure
805 // object is not included in num_args).
806
807 // Create a stub frame as we are pushing some objects on the stack before
808 // calling into the runtime.
809 __ EnterFrame(0);
810
811 __ pushq(raw_null); // Setup space on stack for result from error reporting.
812 __ pushq(R13); // Non-closure object.
813 // Total number of args is the first Smi in args descriptor array (R10).
814 __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args.
815 __ SmiUntag(R13);
816 // See stack layout below explaining "wordSize * 4" offset.
817 PushArgumentsArray(assembler, (kWordSize * 4));
818
819 // Stack:
820 // TOS + 0: Argument array.
821 // TOS + 1: Non-closure object.
822 // TOS + 2: Place for result from reporting the error.
823 // TOS + 3: Saved RBP of previous frame. <== RBP
824 // TOS + 4: Dart code return address
825 // TOS + 5: Last argument of caller.
826 // ....
827 __ CallRuntimeFromStub(kReportObjectNotClosureRuntimeEntry);
828 __ Stop("runtime call throws an exception");
735 } 829 }
736 830
737 831
738 // Called when invoking Dart code from C++ (VM code). 832 // Called when invoking Dart code from C++ (VM code).
739 // Input parameters: 833 // Input parameters:
740 // RSP : points to return address. 834 // RSP : points to return address.
741 // RDI : entrypoint of the Dart function to call. 835 // RDI : entrypoint of the Dart function to call.
742 // RSI : arguments descriptor array. 836 // RSI : arguments descriptor array.
743 // RDX : pointer to the argument array. 837 // RDX : pointer to the argument array.
744 // RCX : new context containing the current isolate pointer. 838 // RCX : new context containing the current isolate pointer.
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 940
847 // Restore the frame pointer. 941 // Restore the frame pointer.
848 __ LeaveFrame(); 942 __ LeaveFrame();
849 943
850 __ ret(); 944 __ ret();
851 } 945 }
852 946
853 947
854 // Called for inline allocation of contexts. 948 // Called for inline allocation of contexts.
855 // Input: 949 // Input:
856 // RDX: number of context variables. 950 // R10: number of context variables.
857 // Output: 951 // Output:
858 // RAX: new allocated RawContext object. 952 // RAX: new allocated RawContext object.
859 // RBX and RDX are destroyed.
860 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 953 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
861 const Immediate raw_null = 954 const Immediate raw_null =
862 Immediate(reinterpret_cast<intptr_t>(Object::null())); 955 Immediate(reinterpret_cast<intptr_t>(Object::null()));
863 if (false) { 956 if (FLAG_inline_alloc) {
864 // TODO(regis): Implement fast inline allocation of contexts. 957 const Class& context_class = Class::ZoneHandle(Object::context_class());
865 __ Unimplemented("AllocateContext stub - inline allocation"); 958 Label slow_case;
959 Heap* heap = Isolate::Current()->heap();
960 // First compute the rounded instance size.
961 // R10: number of context variables.
962 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
963 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
964 __ andq(R13, Immediate(-kObjectAlignment));
965
966 // Now allocate the object.
967 // R10: number of context variables.
968 __ movq(RAX, Immediate(heap->TopAddress()));
969 __ movq(RAX, Address(RAX, 0));
970 __ addq(R13, RAX);
971 // Check if the allocation fits into the remaining space.
972 // RAX: potential new object.
973 // R13: potential next object start.
974 // R10: number of context variables.
975 __ movq(RDI, Immediate(heap->EndAddress()));
976 __ cmpq(R13, Address(RDI, 0));
977 if (FLAG_use_slow_path) {
978 __ jmp(&slow_case);
979 } else {
980 __ j(ABOVE_EQUAL, &slow_case);
981 }
982
983 // Successfully allocated the object, now update top to point to
984 // next object start and initialize the object.
985 // RAX: new object.
986 // R13: next object start.
987 // R10: number of context variables.
988 __ movq(RDI, Immediate(heap->TopAddress()));
989 __ movq(Address(RDI, 0), R13);
990 __ addq(RAX, Immediate(kHeapObjectTag));
991
992 // Initialize the class field in the context object.
993 // RAX: new object.
994 // R10: number of context variables.
995 __ LoadObject(R13, context_class); // Load up class field of context.
996 __ StoreIntoObject(RAX,
997 FieldAddress(RAX, Context::class_offset()),
998 R13);
999 // Calculate the size tag.
1000 // RAX: new object.
1001 // R10: number of context variables.
1002 {
1003 Label size_tag_overflow, done;
1004 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
1005 __ andq(R13, Immediate(-kObjectAlignment));
1006 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag));
1007 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
1008 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2));
1009 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags.
1010 __ jmp(&done);
1011
1012 __ Bind(&size_tag_overflow);
1013 // Set overflow size tag value.
1014 __ movq(FieldAddress(RAX, Context::tags_offset()), Immediate(0));
1015 __ Bind(&done);
1016 }
1017
1018 // Setup up number of context variables field.
1019 // RAX: new object.
1020 // R10: number of context variables as integer value (not object).
1021 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
1022
1023 // Setup isolate field.
1024 // Load Isolate pointer from Context structure into R13.
1025 // RAX: new object.
1026 // R10: number of context variables.
1027 __ movq(R13, FieldAddress(CTX, Context::isolate_offset()));
1028 // R13: Isolate, not an object.
1029 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13);
1030
1031 const Immediate raw_null =
1032 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1033 // Setup the parent field.
1034 // RAX: new object.
1035 // R10: number of context variables.
1036 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null);
1037
1038 // Initialize the context variables.
1039 // RAX: new object.
1040 // R10: number of context variables.
1041 {
1042 Label loop, entry;
1043 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
1044
1045 __ jmp(&entry, Assembler::kNearJump);
1046 __ Bind(&loop);
1047 __ decq(R10);
1048 __ movq(Address(R13, R10, TIMES_8, 0), raw_null);
1049 __ Bind(&entry);
1050 __ cmpq(R10, Immediate(0));
1051 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1052 }
1053
1054 // Done allocating and initializing the context.
1055 // RAX: new object.
1056 __ ret();
1057
1058 __ Bind(&slow_case);
866 } 1059 }
867 // Create the stub frame. 1060 // Create a stub frame.
868 __ EnterFrame(0); 1061 __ EnterFrame(0);
869 __ pushq(raw_null); // Setup space on stack for the return value. 1062 __ pushq(raw_null); // Setup space on stack for the return value.
870 __ SmiTag(RDX); 1063 __ SmiTag(R10);
871 __ pushq(RDX); // Push number of context variables. 1064 __ pushq(R10); // Push number of context variables.
872 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. 1065 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context.
873 __ popq(RAX); // Pop number of context variables argument. 1066 __ popq(RAX); // Pop number of context variables argument.
874 __ popq(RAX); // Pop the new context object. 1067 __ popq(RAX); // Pop the new context object.
875 // RAX: new object 1068 // RAX: new object
876 // Restore the frame pointer. 1069 // Restore the frame pointer.
877 __ LeaveFrame(); 1070 __ LeaveFrame();
878 __ ret(); 1071 __ ret();
879 } 1072 }
880 1073
881 1074
882
883
884 // Called for inline allocation of objects. 1075 // Called for inline allocation of objects.
885 // Input parameters: 1076 // Input parameters:
886 // RSP + 16 : type arguments object (only if class is parameterized). 1077 // RSP + 16 : type arguments object (only if class is parameterized).
887 // RSP + 8 : type arguments of instantiator (only if class is parameterized). 1078 // RSP + 8 : type arguments of instantiator (only if class is parameterized).
888 // RSP : points to return address. 1079 // RSP : points to return address.
889 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers. 1080 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers.
890 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1081 void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
891 const Class& cls) { 1082 const Class& cls) {
892 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; 1083 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize;
893 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; 1084 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize;
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1281 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1091 ASSERT(func.IsClosureFunction()); 1282 ASSERT(func.IsClosureFunction());
1092 const bool is_implicit_static_closure = 1283 const bool is_implicit_static_closure =
1093 func.IsImplicitStaticClosureFunction(); 1284 func.IsImplicitStaticClosureFunction();
1094 const bool is_implicit_instance_closure = 1285 const bool is_implicit_instance_closure =
1095 func.IsImplicitInstanceClosureFunction(); 1286 func.IsImplicitInstanceClosureFunction();
1096 const Class& cls = Class::ZoneHandle(func.signature_class()); 1287 const Class& cls = Class::ZoneHandle(func.signature_class());
1097 const bool has_type_arguments = cls.HasTypeArguments(); 1288 const bool has_type_arguments = cls.HasTypeArguments();
1098 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 1289 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
1099 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; 1290 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize;
1100 if (false) { 1291 const intptr_t closure_size = Closure::InstanceSize();
1101 // TODO(regis): Implement inline context allocation. 1292 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver.
1102 __ Unimplemented("AllocateClosure stub - inline allocation"); 1293 if (FLAG_inline_alloc &&
1294 PageSpace::IsPageAllocatableSize(closure_size + context_size)) {
1295 Label slow_case;
1296 Heap* heap = Isolate::Current()->heap();
1297 __ movq(RAX, Immediate(heap->TopAddress()));
1298 __ movq(RAX, Address(RAX, 0));
1299 __ leaq(R13, Address(RAX, closure_size));
1300 if (is_implicit_instance_closure) {
1301 __ movq(RBX, R13); // RBX: new context address.
1302 __ addq(R13, Immediate(context_size));
1303 }
1304 // Check if the allocation fits into the remaining space.
1305 // RAX: potential new closure object.
1306 // RBX: potential new context object (only if is_implicit_closure).
1307 // R13: potential next object start.
1308 __ movq(RDI, Immediate(heap->EndAddress()));
1309 __ cmpq(R13, Address(RDI, 0));
1310 if (FLAG_use_slow_path) {
1311 __ jmp(&slow_case);
1312 } else {
1313 __ j(ABOVE_EQUAL, &slow_case);
1314 }
1315
1316 // Successfully allocated the object, now update top to point to
1317 // next object start and initialize the object.
1318 __ movq(RDI, Immediate(heap->TopAddress()));
1319 __ movq(Address(RDI, 0), R13);
1320
1321 // Initialize the class field in the object.
1322 // RAX: new closure object.
1323 // RBX: new context object (only if is_implicit_closure).
1324 __ LoadObject(R10, cls); // Load signature class of closure.
1325 __ movq(Address(RAX, Closure::class_offset()), R10);
1326 // Set the tags.
1327 __ movq(Address(RAX, Closure::tags_offset()),
1328 Immediate(RawObject::SizeTag::encode(closure_size)));
1329
1330 // Initialize the function field in the object.
1331 // RAX: new closure object.
1332 // RBX: new context object (only if is_implicit_closure).
1333 // R13: next object start.
1334 __ LoadObject(R10, func); // Load function of closure to be allocated.
1335 __ movq(Address(RAX, Closure::function_offset()), R10);
1336
1337 // Setup the context for this closure.
1338 if (is_implicit_static_closure) {
1339 ObjectStore* object_store = Isolate::Current()->object_store();
1340 ASSERT(object_store != NULL);
1341 const Context& empty_context =
1342 Context::ZoneHandle(object_store->empty_context());
1343 __ LoadObject(R10, empty_context);
1344 __ movq(Address(RAX, Closure::context_offset()), R10);
1345 } else if (is_implicit_instance_closure) {
1346 // Initialize the new context capturing the receiver.
1347
1348 // Set the class field to the Context class.
1349 __ LoadObject(R13, Class::ZoneHandle(Object::context_class()));
1350 __ movq(Address(RBX, Context::class_offset()), R13);
1351 // Set the tags.
1352 __ movq(Address(RBX, Context::tags_offset()),
1353 Immediate(RawObject::SizeTag::encode(context_size)));
1354
1355 // Set number of variables field to 1 (for captured receiver).
1356 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1));
1357
1358 // Set isolate field to isolate of current context.
1359 __ movq(R10, FieldAddress(CTX, Context::isolate_offset()));
1360 __ movq(Address(RBX, Context::isolate_offset()), R10);
1361
1362 // Set the parent field to null.
1363 __ movq(Address(RBX, Context::parent_offset()), raw_null);
1364
1365 // Initialize the context variable to the receiver.
1366 __ movq(R10, Address(RSP, kReceiverOffset));
1367 __ movq(Address(RBX, Context::variable_offset(0)), R10);
1368
1369 // Set the newly allocated context in the newly allocated closure.
1370 __ addq(RBX, Immediate(kHeapObjectTag));
1371 __ movq(Address(RAX, Closure::context_offset()), RBX);
1372 } else {
1373 __ movq(Address(RAX, Closure::context_offset()), CTX);
1374 }
1375
1376 // Set the type arguments field in the newly allocated closure.
1377 if (has_type_arguments) {
1378 ASSERT(!is_implicit_static_closure);
1379 // Use the passed-in type arguments.
1380 __ movq(R10, Address(RSP, kTypeArgumentsOffset));
1381 __ movq(Address(RAX, Closure::type_arguments_offset()), R10);
1382 } else {
1383 // Set to null.
1384 __ movq(Address(RAX, Closure::type_arguments_offset()), raw_null);
1385 }
1386
1387 __ movq(Address(RAX, Closure::smrck_offset()), raw_null);
1388
1389 // Done allocating and initializing the instance.
1390 // RAX: new object.
1391 __ addq(RAX, Immediate(kHeapObjectTag));
1392 __ ret();
1393
1394 __ Bind(&slow_case);
1103 } 1395 }
1104 if (has_type_arguments) { 1396 if (has_type_arguments) {
1105 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); 1397 __ movq(RCX, Address(RSP, kTypeArgumentsOffset));
1106 } 1398 }
1107 if (is_implicit_instance_closure) { 1399 if (is_implicit_instance_closure) {
1108 __ movq(RAX, Address(RSP, kReceiverOffset)); 1400 __ movq(RAX, Address(RSP, kReceiverOffset));
1109 } 1401 }
1110 // Create the stub frame. 1402 // Create the stub frame.
1111 __ EnterFrame(0); 1403 __ EnterFrame(0);
1112 __ pushq(raw_null); // Setup space on stack for the return value. 1404 __ pushq(raw_null); // Setup space on stack for the return value.
(...skipping 21 matching lines...) Expand all
1134 } 1426 }
1135 __ popq(RAX); // Pop the function object. 1427 __ popq(RAX); // Pop the function object.
1136 __ popq(RAX); // Pop the result. 1428 __ popq(RAX); // Pop the result.
1137 // RAX: New closure object. 1429 // RAX: New closure object.
1138 // Restore the calling frame. 1430 // Restore the calling frame.
1139 __ LeaveFrame(); 1431 __ LeaveFrame();
1140 __ ret(); 1432 __ ret();
1141 } 1433 }
1142 1434
1143 1435
1436 // Called for invoking noSuchMethod function from the entry code of a dart
1437 // function after an error in passed named arguments is detected.
1438 // Input parameters:
1439 // RBP : points to previous frame pointer.
1440 // RBP + 8 : points to return address.
1441 // RBP + 16 : address of last argument (arg n-1).
1442 // RBP + 16 + 8*(n-1) : address of first argument (arg 0).
1443 // RBX : ic-data array.
1444 // R10 : arguments descriptor array.
1144 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1445 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1145 __ Unimplemented("CallNoSuchMethodFunction stub"); 1446 // The target function was not found, so invoke method
1447 // "void noSuchMethod(function_name, Array arguments)".
1448 // TODO(regis): For now, we simply pass the actual arguments, both positional
1449 // and named, as the argument array. This is not correct if out-of-order
1450 // named arguments were passed.
1451 // The signature of the "noSuchMethod" method has to change from
1452 // noSuchMethod(String name, Array arguments) to something like
1453 // noSuchMethod(InvocationMirror call).
1454 // Also, the class NoSuchMethodException has to be modified accordingly.
1455 // Total number of args is the first Smi in args descriptor array (R10).
1456 const Immediate raw_null =
1457 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1458 __ movq(R13, FieldAddress(R10, Array::data_offset()));
1459 __ SmiUntag(R13);
1460 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver.
1461
1462 __ EnterFrame(0);
1463 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod.
1464 __ pushq(RAX); // Receiver.
1465 __ pushq(RBX); // IC data array.
1466 __ pushq(R10); // Arguments descriptor array.
1467 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver.
1468 // See stack layout below explaining "wordSize * 8" offset.
1469 PushArgumentsArray(assembler, (kWordSize * 8));
1470
1471 // Stack:
1472 // TOS + 0: Argument array.
1473 // TOS + 1: Arguments descriptor array.
1474 // TOS + 2: Ic-data array.
1475 // TOS + 3: Receiver.
1476 // TOS + 4: Place for result from noSuchMethod.
1477 // TOS + 5: Saved RBP of previous frame. <== RBP
1478 // TOS + 6: Dart callee (or stub) code return address
1479 // TOS + 7: Saved RBP of dart caller frame.
1480 // TOS + 8: Dart caller code return address
1481 // TOS + 9: Last argument of caller.
1482 // ....
1483 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry);
1484 // Remove arguments.
1485 __ popq(RAX);
1486 __ popq(RAX);
1487 __ popq(RAX);
1488 __ popq(RAX);
1489 __ popq(RAX); // Get result into RAX.
1490
1491 // Remove the stub frame as we are about to return.
1492 __ LeaveFrame();
1493 __ ret();
1146 } 1494 }
1147 1495
1148 1496
1497
1149 // Generate inline cache check for 'num_args'. 1498 // Generate inline cache check for 'num_args'.
1150 // RBX: Inline cache data array. 1499 // RBX: Inline cache data array.
1151 // R10: Arguments array. 1500 // R10: Arguments array.
1152 // TOS(0): return address 1501 // TOS(0): return address
1153 // Control flow: 1502 // Control flow:
1154 // - If receiver is null -> jump to IC miss. 1503 // - If receiver is null -> jump to IC miss.
1155 // - If receiver is Smi -> load Smi class. 1504 // - If receiver is Smi -> load Smi class.
1156 // - If receiver is not-Smi -> load receiver's class. 1505 // - If receiver is not-Smi -> load receiver's class.
1157 // - Check if 'num_args' (including receiver) match any IC data group. 1506 // - Check if 'num_args' (including receiver) match any IC data group.
1158 // - Match found -> jump to target. 1507 // - Match found -> jump to target.
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1312 } 1661 }
1313 1662
1314 1663
1315 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { 1664 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
1316 __ Unimplemented("BreakpointDynamic stub"); 1665 __ Unimplemented("BreakpointDynamic stub");
1317 } 1666 }
1318 1667
1319 } // namespace dart 1668 } // namespace dart
1320 1669
1321 #endif // defined TARGET_ARCH_X64 1670 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698