OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. | 75 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
76 __ call(RBX); | 76 __ call(RBX); |
77 | 77 |
78 // Reset exit frame information in Isolate structure. | 78 // Reset exit frame information in Isolate structure. |
79 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 79 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
80 | 80 |
81 // Load Context pointer from Isolate structure into RBX. | 81 // Load Context pointer from Isolate structure into RBX. |
82 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); | 82 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
83 | 83 |
84 // Reset Context pointer in Isolate structure. | 84 // Reset Context pointer in Isolate structure. |
85 const Immediate raw_null = | 85 const Immediate& raw_null = |
86 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 86 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
87 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | 87 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
88 | 88 |
89 // Cache Context pointer into CTX while executing Dart code. | 89 // Cache Context pointer into CTX while executing Dart code. |
90 __ movq(CTX, RBX); | 90 __ movq(CTX, RBX); |
91 | 91 |
92 __ LeaveFrame(); | 92 __ LeaveFrame(); |
93 __ ret(); | 93 __ ret(); |
94 } | 94 } |
95 | 95 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. | 163 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. |
164 __ call(RBX); | 164 __ call(RBX); |
165 | 165 |
166 // Reset exit frame information in Isolate structure. | 166 // Reset exit frame information in Isolate structure. |
167 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 167 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
168 | 168 |
169 // Load Context pointer from Isolate structure into R8. | 169 // Load Context pointer from Isolate structure into R8. |
170 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 170 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
171 | 171 |
172 // Reset Context pointer in Isolate structure. | 172 // Reset Context pointer in Isolate structure. |
173 const Immediate raw_null = | 173 const Immediate& raw_null = |
174 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 174 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
175 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); | 175 __ movq(Address(CTX, Isolate::top_context_offset()), raw_null); |
176 | 176 |
177 // Cache Context pointer into CTX while executing Dart code. | 177 // Cache Context pointer into CTX while executing Dart code. |
178 __ movq(CTX, R8); | 178 __ movq(CTX, R8); |
179 | 179 |
180 __ LeaveFrame(); | 180 __ LeaveFrame(); |
181 __ ret(); | 181 __ ret(); |
182 } | 182 } |
183 | 183 |
184 | 184 |
185 // Input parameters: | 185 // Input parameters: |
186 // R10: arguments descriptor array. | 186 // R10: arguments descriptor array. |
187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
188 const Immediate raw_null = | 188 const Immediate& raw_null = |
189 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 189 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
190 AssemblerMacros::EnterStubFrame(assembler); | 190 AssemblerMacros::EnterStubFrame(assembler); |
191 __ pushq(R10); // Preserve arguments descriptor array. | 191 __ pushq(R10); // Preserve arguments descriptor array. |
192 __ pushq(raw_null); // Setup space on stack for return value. | 192 __ pushq(raw_null); // Setup space on stack for return value. |
193 __ CallRuntime(kPatchStaticCallRuntimeEntry); | 193 __ CallRuntime(kPatchStaticCallRuntimeEntry); |
194 __ popq(RAX); // Get Code object result. | 194 __ popq(RAX); // Get Code object result. |
195 __ popq(R10); // Restore arguments descriptor array. | 195 __ popq(R10); // Restore arguments descriptor array. |
196 // Remove the stub frame as we are about to jump to the dart function. | 196 // Remove the stub frame as we are about to jump to the dart function. |
197 __ LeaveFrame(); | 197 __ LeaveFrame(); |
198 | 198 |
199 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 199 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
200 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 200 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
201 __ jmp(RBX); | 201 __ jmp(RBX); |
202 } | 202 } |
203 | 203 |
204 | 204 |
205 // Called from a static call only when an invalid code has been entered | 205 // Called from a static call only when an invalid code has been entered |
206 // (invalid because its function was optimized or deoptimized). | 206 // (invalid because its function was optimized or deoptimized). |
207 // R10: arguments descriptor array. | 207 // R10: arguments descriptor array. |
208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
209 const Immediate raw_null = | 209 const Immediate& raw_null = |
210 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 210 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
211 AssemblerMacros::EnterStubFrame(assembler); | 211 AssemblerMacros::EnterStubFrame(assembler); |
212 __ pushq(R10); // Preserve arguments descriptor array. | 212 __ pushq(R10); // Preserve arguments descriptor array. |
213 __ pushq(raw_null); // Setup space on stack for return value. | 213 __ pushq(raw_null); // Setup space on stack for return value. |
214 __ CallRuntime(kFixCallersTargetRuntimeEntry); | 214 __ CallRuntime(kFixCallersTargetRuntimeEntry); |
215 __ popq(RAX); // Get Code object. | 215 __ popq(RAX); // Get Code object. |
216 __ popq(R10); // Restore arguments descriptor array. | 216 __ popq(R10); // Restore arguments descriptor array. |
217 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 217 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
218 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 218 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
219 __ LeaveFrame(); | 219 __ LeaveFrame(); |
220 __ jmp(RAX); | 220 __ jmp(RAX); |
221 __ int3(); | 221 __ int3(); |
222 } | 222 } |
223 | 223 |
224 | 224 |
225 // Input parameters: | 225 // Input parameters: |
226 // R10: smi-tagged argument count, may be zero. | 226 // R10: smi-tagged argument count, may be zero. |
227 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { | 227 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { |
228 const Immediate raw_null = | 228 const Immediate& raw_null = |
229 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 229 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
230 | 230 |
231 // Allocate array to store arguments of caller. | 231 // Allocate array to store arguments of caller. |
232 __ movq(RBX, raw_null); // Null element type for raw Array. | 232 __ movq(RBX, raw_null); // Null element type for raw Array. |
233 __ call(&StubCode::AllocateArrayLabel()); | 233 __ call(&StubCode::AllocateArrayLabel()); |
234 __ SmiUntag(R10); | 234 __ SmiUntag(R10); |
235 // RAX: newly allocated array. | 235 // RAX: newly allocated array. |
236 // R10: length of the array (was preserved by the stub). | 236 // R10: length of the array (was preserved by the stub). |
237 __ pushq(RAX); // Array is in RAX and on top of stack. | 237 __ pushq(RAX); // Array is in RAX and on top of stack. |
238 __ leaq(R12, Address(RSP, R10, TIMES_8, arg_offset)); // Addr of first arg. | 238 __ leaq(R12, Address(RSP, R10, TIMES_8, arg_offset)); // Addr of first arg. |
(...skipping 13 matching lines...) Expand all Loading... |
252 | 252 |
253 // Input parameters: | 253 // Input parameters: |
254 // RBX: ic-data. | 254 // RBX: ic-data. |
255 // R10: arguments descriptor array. | 255 // R10: arguments descriptor array. |
256 // Note: The receiver object is the first argument to the function being | 256 // Note: The receiver object is the first argument to the function being |
257 // called, the stub accesses the receiver from this location directly | 257 // called, the stub accesses the receiver from this location directly |
258 // when trying to resolve the call. | 258 // when trying to resolve the call. |
259 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 259 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
260 AssemblerMacros::EnterStubFrame(assembler); | 260 AssemblerMacros::EnterStubFrame(assembler); |
261 | 261 |
262 const Immediate raw_null = | 262 const Immediate& raw_null = |
263 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 263 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
264 __ pushq(raw_null); // Space for the return value. | 264 __ pushq(raw_null); // Space for the return value. |
265 | 265 |
266 // Push the receiver as an argument. Load the smi-tagged argument | 266 // Push the receiver as an argument. Load the smi-tagged argument |
267 // count into R13 to index the receiver in the stack. There are | 267 // count into R13 to index the receiver in the stack. There are |
268 // three words (null, stub's pc marker, saved fp) above the return | 268 // three words (null, stub's pc marker, saved fp) above the return |
269 // address. | 269 // address. |
270 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 270 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
271 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); | 271 __ pushq(Address(RSP, R13, TIMES_4, (3 * kWordSize))); |
272 | 272 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 // Load the receiver into RAX. The argument count in the arguments | 423 // Load the receiver into RAX. The argument count in the arguments |
424 // descriptor in R10 is a smi. | 424 // descriptor in R10 is a smi. |
425 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 425 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
426 // Two words (saved fp, stub's pc marker) in the stack above the return | 426 // Two words (saved fp, stub's pc marker) in the stack above the return |
427 // address. | 427 // address. |
428 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); | 428 __ movq(RAX, Address(RSP, RAX, TIMES_4, 2 * kWordSize)); |
429 // Preserve IC data and arguments descriptor. | 429 // Preserve IC data and arguments descriptor. |
430 __ pushq(RBX); | 430 __ pushq(RBX); |
431 __ pushq(R10); | 431 __ pushq(R10); |
432 | 432 |
433 const Immediate raw_null = | 433 const Immediate& raw_null = |
434 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); | 434 Immediate(reinterpret_cast<intptr_t>(Instructions::null())); |
435 __ pushq(raw_null); // Space for the result of the runtime call. | 435 __ pushq(raw_null); // Space for the result of the runtime call. |
436 __ pushq(RAX); // Receiver. | 436 __ pushq(RAX); // Receiver. |
437 __ pushq(RBX); // IC data. | 437 __ pushq(RBX); // IC data. |
438 __ pushq(R10); // Arguments descriptor. | 438 __ pushq(R10); // Arguments descriptor. |
439 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); | 439 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry); |
440 // Discard arguments. | 440 // Discard arguments. |
441 __ popq(RAX); | 441 __ popq(RAX); |
442 __ popq(RAX); | 442 __ popq(RAX); |
443 __ popq(RAX); | 443 __ popq(RAX); |
(...skipping 14 matching lines...) Expand all Loading... |
458 | 458 |
459 | 459 |
460 // Called for inline allocation of arrays. | 460 // Called for inline allocation of arrays. |
461 // Input parameters: | 461 // Input parameters: |
462 // R10 : Array length as Smi. | 462 // R10 : Array length as Smi. |
463 // RBX : array element type (either NULL or an instantiated type). | 463 // RBX : array element type (either NULL or an instantiated type). |
464 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 464 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
465 // The newly allocated object is returned in RAX. | 465 // The newly allocated object is returned in RAX. |
466 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 466 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
467 Label slow_case; | 467 Label slow_case; |
468 const Immediate raw_null = | 468 const Immediate& raw_null = |
469 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 469 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
470 | 470 |
471 if (FLAG_inline_alloc) { | 471 if (FLAG_inline_alloc) { |
472 // Compute the size to be allocated, it is based on the array length | 472 // Compute the size to be allocated, it is based on the array length |
473 // and is computed as: | 473 // and is computed as: |
474 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 474 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
475 // Assert that length is a Smi. | 475 // Assert that length is a Smi. |
476 __ testq(R10, Immediate(kSmiTagSize)); | 476 __ testq(R10, Immediate(kSmiTagSize)); |
477 if (FLAG_use_slow_path) { | 477 if (FLAG_use_slow_path) { |
478 __ jmp(&slow_case); | 478 __ jmp(&slow_case); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 __ ret(); | 589 __ ret(); |
590 } | 590 } |
591 | 591 |
592 | 592 |
593 // Input parameters: | 593 // Input parameters: |
594 // R10: Arguments descriptor array. | 594 // R10: Arguments descriptor array. |
595 // Note: The closure object is the first argument to the function being | 595 // Note: The closure object is the first argument to the function being |
596 // called, the stub accesses the closure from this location directly | 596 // called, the stub accesses the closure from this location directly |
597 // when trying to resolve the call. | 597 // when trying to resolve the call. |
598 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 598 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
599 const Immediate raw_null = | 599 const Immediate& raw_null = |
600 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 600 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
601 | 601 |
602 // Load num_args. | 602 // Load num_args. |
603 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 603 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
604 // Load closure object in R13. | 604 // Load closure object in R13. |
605 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. | 605 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. |
606 | 606 |
607 // Verify that R13 is a closure by checking its class. | 607 // Verify that R13 is a closure by checking its class. |
608 Label not_closure; | 608 Label not_closure; |
609 __ cmpq(R13, raw_null); | 609 __ cmpq(R13, raw_null); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 __ ret(); | 816 __ ret(); |
817 } | 817 } |
818 | 818 |
819 | 819 |
820 // Called for inline allocation of contexts. | 820 // Called for inline allocation of contexts. |
821 // Input: | 821 // Input: |
822 // R10: number of context variables. | 822 // R10: number of context variables. |
823 // Output: | 823 // Output: |
824 // RAX: new allocated RawContext object. | 824 // RAX: new allocated RawContext object. |
825 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 825 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
826 const Immediate raw_null = | 826 const Immediate& raw_null = |
827 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 827 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
828 if (FLAG_inline_alloc) { | 828 if (FLAG_inline_alloc) { |
829 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 829 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
830 Label slow_case; | 830 Label slow_case; |
831 Heap* heap = Isolate::Current()->heap(); | 831 Heap* heap = Isolate::Current()->heap(); |
832 // First compute the rounded instance size. | 832 // First compute the rounded instance size. |
833 // R10: number of context variables. | 833 // R10: number of context variables. |
834 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 834 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
835 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 835 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
836 __ andq(R13, Immediate(-kObjectAlignment)); | 836 __ andq(R13, Immediate(-kObjectAlignment)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 892 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
893 | 893 |
894 // Setup isolate field. | 894 // Setup isolate field. |
895 // Load Isolate pointer from Context structure into R13. | 895 // Load Isolate pointer from Context structure into R13. |
896 // RAX: new object. | 896 // RAX: new object. |
897 // R10: number of context variables. | 897 // R10: number of context variables. |
898 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | 898 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
899 // R13: Isolate, not an object. | 899 // R13: Isolate, not an object. |
900 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); | 900 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13); |
901 | 901 |
902 const Immediate raw_null = | 902 const Immediate& raw_null = |
903 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 903 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
904 // Setup the parent field. | 904 // Setup the parent field. |
905 // RAX: new object. | 905 // RAX: new object. |
906 // R10: number of context variables. | 906 // R10: number of context variables. |
907 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); | 907 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null); |
908 | 908 |
909 // Initialize the context variables. | 909 // Initialize the context variables. |
910 // RAX: new object. | 910 // RAX: new object. |
911 // R10: number of context variables. | 911 // R10: number of context variables. |
912 { | 912 { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 | 995 |
996 // Called for inline allocation of objects. | 996 // Called for inline allocation of objects. |
997 // Input parameters: | 997 // Input parameters: |
998 // RSP + 16 : type arguments object (only if class is parameterized). | 998 // RSP + 16 : type arguments object (only if class is parameterized). |
999 // RSP + 8 : type arguments of instantiator (only if class is parameterized). | 999 // RSP + 8 : type arguments of instantiator (only if class is parameterized). |
1000 // RSP : points to return address. | 1000 // RSP : points to return address. |
1001 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1001 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
1002 const Class& cls) { | 1002 const Class& cls) { |
1003 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; | 1003 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
1004 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; | 1004 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
1005 const Immediate raw_null = | 1005 const Immediate& raw_null = |
1006 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1006 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1007 // The generated code is different if the class is parameterized. | 1007 // The generated code is different if the class is parameterized. |
1008 const bool is_cls_parameterized = | 1008 const bool is_cls_parameterized = |
1009 cls.type_arguments_field_offset() != Class::kNoTypeArguments; | 1009 cls.type_arguments_field_offset() != Class::kNoTypeArguments; |
1010 // kInlineInstanceSize is a constant used as a threshold for determining | 1010 // kInlineInstanceSize is a constant used as a threshold for determining |
1011 // when the object initialization should be done as a loop or as | 1011 // when the object initialization should be done as a loop or as |
1012 // straight line code. | 1012 // straight line code. |
1013 const int kInlineInstanceSize = 12; // In words. | 1013 const int kInlineInstanceSize = 12; // In words. |
1014 const intptr_t instance_size = cls.instance_size(); | 1014 const intptr_t instance_size = cls.instance_size(); |
1015 ASSERT(instance_size > 0); | 1015 ASSERT(instance_size > 0); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 // RDI: new object type arguments (if is_cls_parameterized). | 1091 // RDI: new object type arguments (if is_cls_parameterized). |
1092 __ LoadObject(RDX, cls); // Load class of object to be allocated. | 1092 __ LoadObject(RDX, cls); // Load class of object to be allocated. |
1093 // Set the tags. | 1093 // Set the tags. |
1094 uword tags = 0; | 1094 uword tags = 0; |
1095 tags = RawObject::SizeTag::update(instance_size, tags); | 1095 tags = RawObject::SizeTag::update(instance_size, tags); |
1096 ASSERT(cls.id() != kIllegalCid); | 1096 ASSERT(cls.id() != kIllegalCid); |
1097 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1097 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1098 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1098 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
1099 | 1099 |
1100 // Initialize the remaining words of the object. | 1100 // Initialize the remaining words of the object. |
1101 const Immediate raw_null = | 1101 const Immediate& raw_null = |
1102 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1102 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1103 | 1103 |
1104 // RAX: new object start. | 1104 // RAX: new object start. |
1105 // RBX: next object start. | 1105 // RBX: next object start. |
1106 // RDX: class of the object to be allocated. | 1106 // RDX: class of the object to be allocated. |
1107 // RDI: new object type arguments (if is_cls_parameterized). | 1107 // RDI: new object type arguments (if is_cls_parameterized). |
1108 // First try inlining the initialization without a loop. | 1108 // First try inlining the initialization without a loop. |
1109 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1109 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1110 // Check if the object contains any non-header fields. | 1110 // Check if the object contains any non-header fields. |
1111 // Small objects are initialized using a consecutive set of writes. | 1111 // Small objects are initialized using a consecutive set of writes. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1170 } | 1170 } |
1171 | 1171 |
1172 | 1172 |
1173 // Called for inline allocation of closures. | 1173 // Called for inline allocation of closures. |
1174 // Input parameters: | 1174 // Input parameters: |
1175 // RSP + 16 : receiver (null if not an implicit instance closure). | 1175 // RSP + 16 : receiver (null if not an implicit instance closure). |
1176 // RSP + 8 : type arguments object (null if class is not parameterized). | 1176 // RSP + 8 : type arguments object (null if class is not parameterized). |
1177 // RSP : points to return address. | 1177 // RSP : points to return address. |
1178 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1178 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
1179 const Function& func) { | 1179 const Function& func) { |
1180 const Immediate raw_null = | 1180 const Immediate& raw_null = |
1181 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1181 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1182 ASSERT(func.IsClosureFunction()); | 1182 ASSERT(func.IsClosureFunction()); |
1183 const bool is_implicit_static_closure = | 1183 const bool is_implicit_static_closure = |
1184 func.IsImplicitStaticClosureFunction(); | 1184 func.IsImplicitStaticClosureFunction(); |
1185 const bool is_implicit_instance_closure = | 1185 const bool is_implicit_instance_closure = |
1186 func.IsImplicitInstanceClosureFunction(); | 1186 func.IsImplicitInstanceClosureFunction(); |
1187 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1187 const Class& cls = Class::ZoneHandle(func.signature_class()); |
1188 const bool has_type_arguments = cls.HasTypeArguments(); | 1188 const bool has_type_arguments = cls.HasTypeArguments(); |
1189 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 1189 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
1190 const intptr_t kReceiverOffset = 2 * kWordSize; | 1190 const intptr_t kReceiverOffset = 2 * kWordSize; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1329 // RBP - 8 : PC marker => RawInstruction object. | 1329 // RBP - 8 : PC marker => RawInstruction object. |
1330 // RBP : points to previous frame pointer. | 1330 // RBP : points to previous frame pointer. |
1331 // RBP + 8 : points to return address. | 1331 // RBP + 8 : points to return address. |
1332 // RBP + 16 : address of last argument (arg n-1). | 1332 // RBP + 16 : address of last argument (arg n-1). |
1333 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). | 1333 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
1334 // RBX : ic-data. | 1334 // RBX : ic-data. |
1335 // R10 : arguments descriptor array. | 1335 // R10 : arguments descriptor array. |
1336 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1336 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
1337 // The target function was not found, so invoke method | 1337 // The target function was not found, so invoke method |
1338 // "dynamic noSuchMethod(InvocationMirror invocation)". | 1338 // "dynamic noSuchMethod(InvocationMirror invocation)". |
1339 const Immediate raw_null = | 1339 const Immediate& raw_null = |
1340 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1340 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1341 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1341 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1342 __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver. | 1342 __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver. |
1343 | 1343 |
1344 // Create a stub frame. | 1344 // Create a stub frame. |
1345 AssemblerMacros::EnterStubFrame(assembler); | 1345 AssemblerMacros::EnterStubFrame(assembler); |
1346 | 1346 |
1347 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. | 1347 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
1348 __ pushq(RAX); // Receiver. | 1348 __ pushq(RAX); // Receiver. |
1349 __ pushq(RBX); // IC data array. | 1349 __ pushq(RBX); // IC data array. |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 | 1510 |
1511 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1511 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
1512 __ addq(R12, Immediate(entry_size)); // Next entry. | 1512 __ addq(R12, Immediate(entry_size)); // Next entry. |
1513 __ movq(R13, Address(R12, 0)); // Next class ID. | 1513 __ movq(R13, Address(R12, 0)); // Next class ID. |
1514 | 1514 |
1515 __ Bind(&test); | 1515 __ Bind(&test); |
1516 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1516 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
1517 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1517 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
1518 | 1518 |
1519 // IC miss. | 1519 // IC miss. |
1520 const Immediate raw_null = | 1520 const Immediate& raw_null = |
1521 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1521 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1522 // Compute address of arguments (first read number of arguments from | 1522 // Compute address of arguments (first read number of arguments from |
1523 // arguments descriptor array and then compute address on the stack). | 1523 // arguments descriptor array and then compute address on the stack). |
1524 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1524 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
1525 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1525 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
1526 AssemblerMacros::EnterStubFrame(assembler); | 1526 AssemblerMacros::EnterStubFrame(assembler); |
1527 __ pushq(R10); // Preserve arguments descriptor array. | 1527 __ pushq(R10); // Preserve arguments descriptor array. |
1528 __ pushq(RBX); // Preserve IC data object. | 1528 __ pushq(RBX); // Preserve IC data object. |
1529 __ pushq(raw_null); // Setup space on stack for result (target code object). | 1529 __ pushq(raw_null); // Setup space on stack for result (target code object). |
1530 // Push call arguments. | 1530 // Push call arguments. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1662 | 1662 |
1663 // Megamorphic call is currently implemented as IC call but through a stub | 1663 // Megamorphic call is currently implemented as IC call but through a stub |
1664 // that does not check/count function invocations. | 1664 // that does not check/count function invocations. |
1665 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1665 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
1666 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1666 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1667 } | 1667 } |
1668 | 1668 |
1669 // R10: Arguments descriptor array. | 1669 // R10: Arguments descriptor array. |
1670 // TOS(0): return address (Dart code). | 1670 // TOS(0): return address (Dart code). |
1671 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1671 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
1672 const Immediate raw_null = | 1672 const Immediate& raw_null = |
1673 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1673 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1674 AssemblerMacros::EnterStubFrame(assembler); | 1674 AssemblerMacros::EnterStubFrame(assembler); |
1675 __ pushq(R10); // Preserve arguments descriptor. | 1675 __ pushq(R10); // Preserve arguments descriptor. |
1676 __ pushq(raw_null); // Room for result. | 1676 __ pushq(raw_null); // Room for result. |
1677 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); | 1677 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); |
1678 __ popq(RAX); // Code object. | 1678 __ popq(RAX); // Code object. |
1679 __ popq(R10); // Restore arguments descriptor. | 1679 __ popq(R10); // Restore arguments descriptor. |
1680 __ LeaveFrame(); | 1680 __ LeaveFrame(); |
1681 | 1681 |
1682 // Now call the static function. The breakpoint handler function | 1682 // Now call the static function. The breakpoint handler function |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1733 | 1733 |
1734 | 1734 |
1735 // Used to check class and type arguments. Arguments passed on stack: | 1735 // Used to check class and type arguments. Arguments passed on stack: |
1736 // TOS + 0: return address. | 1736 // TOS + 0: return address. |
1737 // TOS + 1: instantiator type arguments (can be NULL). | 1737 // TOS + 1: instantiator type arguments (can be NULL). |
1738 // TOS + 2: instance. | 1738 // TOS + 2: instance. |
1739 // TOS + 3: SubtypeTestCache. | 1739 // TOS + 3: SubtypeTestCache. |
1740 // Result in RCX: null -> not found, otherwise result (true or false). | 1740 // Result in RCX: null -> not found, otherwise result (true or false). |
1741 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1741 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
1742 ASSERT((1 <= n) && (n <= 3)); | 1742 ASSERT((1 <= n) && (n <= 3)); |
1743 const Immediate raw_null = | 1743 const Immediate& raw_null = |
1744 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1744 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1745 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1745 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
1746 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1746 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
1747 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1747 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
1748 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1748 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
1749 if (n > 1) { | 1749 if (n > 1) { |
1750 __ LoadClass(R10, RAX); | 1750 __ LoadClass(R10, RAX); |
1751 // Compute instance type arguments into R13. | 1751 // Compute instance type arguments into R13. |
1752 Label has_no_type_arguments; | 1752 Label has_no_type_arguments; |
1753 __ movq(R13, raw_null); | 1753 __ movq(R13, raw_null); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 __ Drop(4); | 1980 __ Drop(4); |
1981 __ LeaveFrame(); | 1981 __ LeaveFrame(); |
1982 | 1982 |
1983 __ jmp(&compute_result, Assembler::kNearJump); | 1983 __ jmp(&compute_result, Assembler::kNearJump); |
1984 } | 1984 } |
1985 | 1985 |
1986 // Calls to the runtime to optimize the given function. | 1986 // Calls to the runtime to optimize the given function. |
1987 // RDI: function to be reoptimized. | 1987 // RDI: function to be reoptimized. |
1988 // R10: argument descriptor (preserved). | 1988 // R10: argument descriptor (preserved). |
1989 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1989 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
1990 const Immediate raw_null = | 1990 const Immediate& raw_null = |
1991 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1991 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1992 AssemblerMacros::EnterStubFrame(assembler); | 1992 AssemblerMacros::EnterStubFrame(assembler); |
1993 __ pushq(R10); | 1993 __ pushq(R10); |
1994 __ pushq(raw_null); // Setup space on stack for return value. | 1994 __ pushq(raw_null); // Setup space on stack for return value. |
1995 __ pushq(RDI); | 1995 __ pushq(RDI); |
1996 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 1996 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
1997 __ popq(RAX); // Disard argument. | 1997 __ popq(RAX); // Disard argument. |
1998 __ popq(RAX); // Get Code object. | 1998 __ popq(RAX); // Get Code object. |
1999 __ popq(R10); // Restore argument descriptor. | 1999 __ popq(R10); // Restore argument descriptor. |
2000 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 2000 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 __ cmpq(left, right); | 2076 __ cmpq(left, right); |
2077 __ Bind(&done); | 2077 __ Bind(&done); |
2078 __ popq(right); | 2078 __ popq(right); |
2079 __ popq(left); | 2079 __ popq(left); |
2080 __ ret(); | 2080 __ ret(); |
2081 } | 2081 } |
2082 | 2082 |
2083 } // namespace dart | 2083 } // namespace dart |
2084 | 2084 |
2085 #endif // defined TARGET_ARCH_X64 | 2085 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |