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

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

Issue 11442010: Introduce a class encapsulating arguments descriptor arrays. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporated review comments. Created 8 years 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
« runtime/vm/dart_entry.cc ('K') | « runtime/vm/stub_code_ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, 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/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/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
12 #include "vm/instructions.h" 13 #include "vm/instructions.h"
13 #include "vm/object_store.h" 14 #include "vm/object_store.h"
14 #include "vm/pages.h" 15 #include "vm/pages.h"
15 #include "vm/resolver.h" 16 #include "vm/resolver.h"
16 #include "vm/scavenger.h" 17 #include "vm/scavenger.h"
17 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
18 19
19 20
20 #define __ assembler-> 21 #define __ assembler->
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 176
176 // Cache Context pointer into CTX while executing Dart code. 177 // Cache Context pointer into CTX while executing Dart code.
177 __ movq(CTX, R8); 178 __ movq(CTX, R8);
178 179
179 __ LeaveFrame(); 180 __ LeaveFrame();
180 __ ret(); 181 __ ret();
181 } 182 }
182 183
183 184
184 // Input parameters: 185 // Input parameters:
185 // R10: arguments descriptor array (num_args is first Smi element). 186 // R10: arguments descriptor array.
186 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 187 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
187 const Immediate raw_null = 188 const Immediate raw_null =
188 Immediate(reinterpret_cast<intptr_t>(Object::null())); 189 Immediate(reinterpret_cast<intptr_t>(Object::null()));
189 AssemblerMacros::EnterStubFrame(assembler); 190 AssemblerMacros::EnterStubFrame(assembler);
190 __ pushq(R10); // Preserve arguments descriptor array. 191 __ pushq(R10); // Preserve arguments descriptor array.
191 __ pushq(raw_null); // Setup space on stack for return value. 192 __ pushq(raw_null); // Setup space on stack for return value.
192 __ CallRuntime(kPatchStaticCallRuntimeEntry); 193 __ CallRuntime(kPatchStaticCallRuntimeEntry);
193 __ popq(RAX); // Get Code object result. 194 __ popq(RAX); // Get Code object result.
194 __ popq(R10); // Restore arguments descriptor array. 195 __ popq(R10); // Restore arguments descriptor array.
195 // 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.
196 __ LeaveFrame(); 197 __ LeaveFrame();
197 198
198 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); 199 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
199 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 200 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
200 __ jmp(RBX); 201 __ jmp(RBX);
201 } 202 }
202 203
203 204
204 // 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
205 // (invalid because its function was optimized or deoptimized). 206 // (invalid because its function was optimized or deoptimized).
206 // R10: arguments descriptor array (num_args is first Smi element). 207 // R10: arguments descriptor array.
207 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 208 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
208 const Immediate raw_null = 209 const Immediate raw_null =
209 Immediate(reinterpret_cast<intptr_t>(Object::null())); 210 Immediate(reinterpret_cast<intptr_t>(Object::null()));
210 AssemblerMacros::EnterStubFrame(assembler); 211 AssemblerMacros::EnterStubFrame(assembler);
211 __ pushq(R10); // Preserve arguments descriptor array. 212 __ pushq(R10); // Preserve arguments descriptor array.
212 __ pushq(raw_null); // Setup space on stack for return value. 213 __ pushq(raw_null); // Setup space on stack for return value.
213 __ CallRuntime(kFixCallersTargetRuntimeEntry); 214 __ CallRuntime(kFixCallersTargetRuntimeEntry);
214 __ popq(RAX); // Get Code object. 215 __ popq(RAX); // Get Code object.
215 __ popq(R10); // Restore arguments descriptor array. 216 __ popq(R10); // Restore arguments descriptor array.
216 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); 217 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
(...skipping 29 matching lines...) Expand all
246 __ AddImmediate(RBX, Immediate(kWordSize)); 247 __ AddImmediate(RBX, Immediate(kWordSize));
247 __ AddImmediate(R12, Immediate(-kWordSize)); 248 __ AddImmediate(R12, Immediate(-kWordSize));
248 __ Bind(&loop_condition); 249 __ Bind(&loop_condition);
249 __ decq(R10); 250 __ decq(R10);
250 __ j(POSITIVE, &loop, Assembler::kNearJump); 251 __ j(POSITIVE, &loop, Assembler::kNearJump);
251 } 252 }
252 253
253 254
254 // Input parameters: 255 // Input parameters:
255 // RBX: ic-data. 256 // RBX: ic-data.
256 // R10: arguments descriptor array (num_args is first Smi element). 257 // R10: arguments descriptor array.
257 // Note: The receiver object is the first argument to the function being 258 // Note: The receiver object is the first argument to the function being
258 // called, the stub accesses the receiver from this location directly 259 // called, the stub accesses the receiver from this location directly
259 // when trying to resolve the call. 260 // when trying to resolve the call.
260 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { 261 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) {
261 const Immediate raw_null = 262 const Immediate raw_null =
262 Immediate(reinterpret_cast<intptr_t>(Object::null())); 263 Immediate(reinterpret_cast<intptr_t>(Object::null()));
263 264
264 // Create a stub frame as we are pushing some objects on the stack before 265 // Create a stub frame as we are pushing some objects on the stack before
265 // calling into the runtime. 266 // calling into the runtime.
266 AssemblerMacros::EnterStubFrame(assembler); 267 AssemblerMacros::EnterStubFrame(assembler);
267 268
268 // Preserve values across call to resolving. 269 // Preserve values across call to resolving.
269 // Stack at this point: 270 // Stack at this point:
270 // TOS + 0: PC marker => RawInstruction object. 271 // TOS + 0: PC marker => RawInstruction object.
271 // TOS + 1: Saved RBP of previous frame. <== RBP 272 // TOS + 1: Saved RBP of previous frame. <== RBP
272 // TOS + 2: Dart code return address 273 // TOS + 2: Dart code return address
273 // TOS + 3: Last argument of caller. 274 // TOS + 3: Last argument of caller.
274 // .... 275 // ....
275 // Total number of args is the first Smi in args descriptor array (R10). 276 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
276 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
277 __ movq(RAX, Address(RBP, RAX, TIMES_4, kWordSize)); // Get receiver. 277 __ movq(RAX, Address(RBP, RAX, TIMES_4, kWordSize)); // Get receiver.
278 __ pushq(R10); // Preserve arguments descriptor array. 278 __ pushq(R10); // Preserve arguments descriptor array.
279 __ pushq(RAX); // Preserve receiver. 279 __ pushq(RAX); // Preserve receiver.
280 __ pushq(RBX); // Preserve ic-data. 280 __ pushq(RBX); // Preserve ic-data.
281 // First resolve the function to get the function object. 281 // First resolve the function to get the function object.
282 282
283 __ pushq(raw_null); // Setup space on stack for return value. 283 __ pushq(raw_null); // Setup space on stack for return value.
284 __ pushq(RAX); // Push receiver. 284 __ pushq(RAX); // Push receiver.
285 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry); 285 __ CallRuntime(kResolveCompileInstanceFunctionRuntimeEntry);
286 __ popq(RAX); // Remove receiver pushed earlier. 286 __ popq(RAX); // Remove receiver pushed earlier.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 365
366 __ cmpq(RBX, raw_null); 366 __ cmpq(RBX, raw_null);
367 Label function_not_found; 367 Label function_not_found;
368 __ j(EQUAL, &function_not_found); 368 __ j(EQUAL, &function_not_found);
369 369
370 // RBX: Closure object. 370 // RBX: Closure object.
371 // R13: Arguments descriptor array. 371 // R13: Arguments descriptor array.
372 __ pushq(raw_null); // Setup space on stack for result from invoking Closure. 372 __ pushq(raw_null); // Setup space on stack for result from invoking Closure.
373 __ pushq(RBX); // Closure object. 373 __ pushq(RBX); // Closure object.
374 __ pushq(R13); // Arguments descriptor. 374 __ pushq(R13); // Arguments descriptor.
375 __ movq(R13, FieldAddress(R13, Array::data_offset())); 375 __ movq(R13, FieldAddress(R13, ArgumentsDescriptor::count_offset()));
376 __ SmiUntag(R13); 376 __ SmiUntag(R13);
377 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. 377 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver.
378 PushArgumentsArray(assembler, (kWordSize * 6)); 378 PushArgumentsArray(assembler, (kWordSize * 6));
379 // Stack layout explaining "(kWordSize * 6)" offset. 379 // Stack layout explaining "(kWordSize * 6)" offset.
380 // TOS + 0: Argument array. 380 // TOS + 0: Argument array.
381 // TOS + 1: Arguments descriptor array. 381 // TOS + 1: Arguments descriptor array.
382 // TOS + 2: Closure object. 382 // TOS + 2: Closure object.
383 // TOS + 3: Place for result from closure function. 383 // TOS + 3: Place for result from closure function.
384 // TOS + 4: PC marker => RawInstruction object. 384 // TOS + 4: PC marker => RawInstruction object.
385 // TOS + 5: Saved RBP of previous frame. <== RBP 385 // TOS + 5: Saved RBP of previous frame. <== RBP
(...skipping 11 matching lines...) Expand all
397 // Remove the stub frame as we are about to return. 397 // Remove the stub frame as we are about to return.
398 __ LeaveFrame(); 398 __ LeaveFrame();
399 __ ret(); 399 __ ret();
400 400
401 __ Bind(&function_not_found); 401 __ Bind(&function_not_found);
402 // The target function was not found, so invoke method 402 // The target function was not found, so invoke method
403 // "void noSuchMethod(function_name, args_array)". 403 // "void noSuchMethod(function_name, args_array)".
404 // RAX: receiver. 404 // RAX: receiver.
405 // R10: ic-data. 405 // R10: ic-data.
406 // RBX: raw_null. 406 // RBX: raw_null.
407 // R13: argument descriptor array. 407 // R13: arguments descriptor array.
408 408
409 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. 409 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod.
410 __ pushq(RAX); // Receiver. 410 __ pushq(RAX); // Receiver.
411 __ pushq(R10); // IC-data array. 411 __ pushq(R10); // IC-data array.
412 __ pushq(R13); // Argument descriptor array. 412 __ pushq(R13); // Arguments descriptor array.
413 __ movq(R13, FieldAddress(R13, Array::data_offset())); 413 __ movq(R13, FieldAddress(R13, ArgumentsDescriptor::count_offset()));
414 __ SmiUntag(R13); 414 __ SmiUntag(R13);
415 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. 415 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver.
416 // See stack layout below explaining "wordSize * 7" offset. 416 // See stack layout below explaining "wordSize * 7" offset.
417 PushArgumentsArray(assembler, (kWordSize * 7)); 417 PushArgumentsArray(assembler, (kWordSize * 7));
418 418
419 // Stack: 419 // Stack:
420 // TOS + 0: Argument array. 420 // TOS + 0: Arguments array.
421 // TOS + 1: Argument descriptor array. 421 // TOS + 1: Arguments descriptor array.
422 // TOS + 2: IC-data array. 422 // TOS + 2: IC-data array.
423 // TOS + 3: Receiver. 423 // TOS + 3: Receiver.
424 // TOS + 4: Place for result from noSuchMethod. 424 // TOS + 4: Place for result from noSuchMethod.
425 // TOS + 5: PC marker => RawInstruction object. 425 // TOS + 5: PC marker => RawInstruction object.
426 // TOS + 6: Saved RBP of previous frame. <== RBP 426 // TOS + 6: Saved RBP of previous frame. <== RBP
427 // TOS + 7: Dart code return address 427 // TOS + 7: Dart code return address
428 // TOS + 8: Last argument of caller. 428 // TOS + 8: Last argument of caller.
429 // .... 429 // ....
430 430
431 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); 431 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 __ CallRuntime(kAllocateArrayRuntimeEntry); 683 __ CallRuntime(kAllocateArrayRuntimeEntry);
684 __ popq(RAX); // Pop element type argument. 684 __ popq(RAX); // Pop element type argument.
685 __ popq(R10); // Pop array length argument. 685 __ popq(R10); // Pop array length argument.
686 __ popq(RAX); // Pop return value from return slot. 686 __ popq(RAX); // Pop return value from return slot.
687 __ LeaveFrame(); 687 __ LeaveFrame();
688 __ ret(); 688 __ ret();
689 } 689 }
690 690
691 691
692 // Input parameters: 692 // Input parameters:
693 // R10: Arguments descriptor array (num_args is first Smi element, closure 693 // R10: Arguments descriptor array.
694 // object is included in num_args and is first argument).
695 // Note: The closure object is the first argument to the function being 694 // Note: The closure object is the first argument to the function being
696 // called, the stub accesses the closure from this location directly 695 // called, the stub accesses the closure from this location directly
697 // when trying to resolve the call. 696 // when trying to resolve the call.
698 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 697 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
699 const Immediate raw_null = 698 const Immediate raw_null =
700 Immediate(reinterpret_cast<intptr_t>(Object::null())); 699 Immediate(reinterpret_cast<intptr_t>(Object::null()));
701 700
702 // Total number of args is the first Smi in args descriptor array (R10). 701 // Load num_args.
703 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args. 702 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
704 // Load closure object in R13. 703 // Load closure object in R13.
705 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. 704 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi.
706 705
707 // Verify that R13 is a closure by checking its class. 706 // Verify that R13 is a closure by checking its class.
708 Label not_closure; 707 Label not_closure;
709 __ cmpq(R13, raw_null); 708 __ cmpq(R13, raw_null);
710 // Not a closure, but null object. 709 // Not a closure, but null object.
711 __ j(EQUAL, &not_closure); 710 __ j(EQUAL, &not_closure);
712 __ testq(R13, Immediate(kSmiTagMask)); 711 __ testq(R13, Immediate(kSmiTagMask));
713 __ j(ZERO, &not_closure); // Not a closure, but a smi. 712 __ j(ZERO, &not_closure); // Not a closure, but a smi.
(...skipping 28 matching lines...) Expand all
742 __ popq(R10); // Restore arguments descriptor array. 741 __ popq(R10); // Restore arguments descriptor array.
743 // Restore RAX. 742 // Restore RAX.
744 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); 743 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
745 744
746 // Remove the stub frame as we are about to jump to the closure function. 745 // Remove the stub frame as we are about to jump to the closure function.
747 __ LeaveFrame(); 746 __ LeaveFrame();
748 747
749 __ Bind(&function_compiled); 748 __ Bind(&function_compiled);
750 // RAX: Code. 749 // RAX: Code.
751 // RBX: Function. 750 // RBX: Function.
752 // R10: Arguments descriptor array (num_args is first Smi element). 751 // R10: Arguments descriptor array.
753 752
754 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); 753 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
755 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 754 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
756 __ jmp(RBX); 755 __ jmp(RBX);
757 756
758 __ Bind(&not_closure); 757 __ Bind(&not_closure);
759 // Call runtime to report that a closure call was attempted on a non-closure 758 // Call runtime to report that a closure call was attempted on a non-closure
760 // object, passing the non-closure object and its arguments array. 759 // object, passing the non-closure object and its arguments array.
761 // R13: non-closure object. 760 // R13: non-closure object.
762 // R10: arguments descriptor array (num_args is first Smi element, closure 761 // R10: arguments descriptor array.
763 // object is included in num_args).
764 762
765 // Create a stub frame as we are pushing some objects on the stack before 763 // Create a stub frame as we are pushing some objects on the stack before
766 // calling into the runtime. 764 // calling into the runtime.
767 AssemblerMacros::EnterStubFrame(assembler); 765 AssemblerMacros::EnterStubFrame(assembler);
768 766
769 __ pushq(raw_null); // Setup space on stack for result from error reporting. 767 __ pushq(raw_null); // Setup space on stack for result from error reporting.
770 __ pushq(R13); // Non-closure object. 768 __ pushq(R13); // Non-closure object.
771 // Total number of args is the first Smi in args descriptor array (R10). 769 // Load num_args.
772 __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args. 770 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
773 __ SmiUntag(R13); 771 __ SmiUntag(R13);
774 __ subq(R13, Immediate(1)); // Arguments array length, minus the closure. 772 __ subq(R13, Immediate(1)); // Arguments array length, minus the closure.
775 // See stack layout below explaining "wordSize * 5" offset. 773 // See stack layout below explaining "wordSize * 5" offset.
776 PushArgumentsArray(assembler, (kWordSize * 5)); 774 PushArgumentsArray(assembler, (kWordSize * 5));
777 775
778 // Stack: 776 // Stack:
779 // TOS + 0: Argument array. 777 // TOS + 0: Argument array.
780 // TOS + 1: Non-closure object. 778 // TOS + 1: Non-closure object.
781 // TOS + 2: Place for result from reporting the error. 779 // TOS + 2: Place for result from reporting the error.
782 // TOS + 3: PC marker => RawInstruction object. 780 // TOS + 3: PC marker => RawInstruction object.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 // Note that VisitObjectPointers will find this saved Context pointer during 836 // Note that VisitObjectPointers will find this saved Context pointer during
839 // GC marking, since it traverses any information between SP and 837 // GC marking, since it traverses any information between SP and
840 // FP - kExitLinkOffsetInEntryFrame. 838 // FP - kExitLinkOffsetInEntryFrame.
841 __ movq(RAX, Address(R8, Isolate::top_context_offset())); 839 __ movq(RAX, Address(R8, Isolate::top_context_offset()));
842 __ pushq(RAX); 840 __ pushq(RAX);
843 841
844 // Load arguments descriptor array into R10, which is passed to Dart code. 842 // Load arguments descriptor array into R10, which is passed to Dart code.
845 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); 843 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
846 844
847 // Load number of arguments into RBX. 845 // Load number of arguments into RBX.
848 __ movq(RBX, FieldAddress(R10, Array::data_offset())); 846 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
849 __ SmiUntag(RBX); 847 __ SmiUntag(RBX);
850 848
851 // Set up arguments for the Dart call. 849 // Set up arguments for the Dart call.
852 Label push_arguments; 850 Label push_arguments;
853 Label done_push_arguments; 851 Label done_push_arguments;
854 __ testq(RBX, RBX); // check if there are arguments. 852 __ testq(RBX, RBX); // check if there are arguments.
855 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); 853 __ j(ZERO, &done_push_arguments, Assembler::kNearJump);
856 __ movq(RAX, Immediate(0)); 854 __ movq(RAX, Immediate(0));
857 __ Bind(&push_arguments); 855 __ Bind(&push_arguments);
858 __ movq(RCX, Address(RDX, RAX, TIMES_8, 0)); // RDX is start of arguments. 856 __ movq(RCX, Address(RDX, RAX, TIMES_8, 0)); // RDX is start of arguments.
859 __ movq(RCX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle)); 857 __ movq(RCX, Address(RCX, VMHandles::kOffsetOfRawPtrInHandle));
860 __ pushq(RCX); 858 __ pushq(RCX);
861 __ incq(RAX); 859 __ incq(RAX);
862 __ cmpq(RAX, RBX); 860 __ cmpq(RAX, RBX);
863 __ j(LESS, &push_arguments, Assembler::kNearJump); 861 __ j(LESS, &push_arguments, Assembler::kNearJump);
864 __ Bind(&done_push_arguments); 862 __ Bind(&done_push_arguments);
865 863
866 // Call the Dart code entrypoint. 864 // Call the Dart code entrypoint.
867 __ call(RDI); // R10 is the arguments descriptor array. 865 __ call(RDI); // R10 is the arguments descriptor array.
868 866
869 // Read the saved new Context pointer. 867 // Read the saved new Context pointer.
870 __ movq(CTX, Address(RBP, kNewContextOffset)); 868 __ movq(CTX, Address(RBP, kNewContextOffset));
871 __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle)); 869 __ movq(CTX, Address(CTX, VMHandles::kOffsetOfRawPtrInHandle));
872 870
873 // Read the saved arguments descriptor array to obtain the number of passed 871 // Read the saved arguments descriptor array to obtain the number of passed
874 // arguments, which is the first element of the array, a Smi. 872 // arguments.
875 __ movq(RSI, Address(RBP, kArgumentsDescOffset)); 873 __ movq(RSI, Address(RBP, kArgumentsDescOffset));
876 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle)); 874 __ movq(R10, Address(RSI, VMHandles::kOffsetOfRawPtrInHandle));
877 __ movq(RDX, FieldAddress(R10, Array::data_offset())); 875 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
878 // Get rid of arguments pushed on the stack. 876 // Get rid of arguments pushed on the stack.
879 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. 877 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi.
880 878
881 // Load Isolate pointer from Context structure into CTX. Drop Context. 879 // Load Isolate pointer from Context structure into CTX. Drop Context.
882 __ movq(CTX, FieldAddress(CTX, Context::isolate_offset())); 880 __ movq(CTX, FieldAddress(CTX, Context::isolate_offset()));
883 881
884 // Restore the saved Context pointer into the Isolate structure. 882 // Restore the saved Context pointer into the Isolate structure.
885 // Uses RCX as a temporary register for this. 883 // Uses RCX as a temporary register for this.
886 __ popq(RCX); 884 __ popq(RCX);
887 __ movq(Address(CTX, Isolate::top_context_offset()), RCX); 885 __ movq(Address(CTX, Isolate::top_context_offset()), RCX);
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1422 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1425 // The target function was not found, so invoke method 1423 // The target function was not found, so invoke method
1426 // "void noSuchMethod(function_name, Array arguments)". 1424 // "void noSuchMethod(function_name, Array arguments)".
1427 // TODO(regis): For now, we simply pass the actual arguments, both positional 1425 // TODO(regis): For now, we simply pass the actual arguments, both positional
1428 // and named, as the argument array. This is not correct if out-of-order 1426 // and named, as the argument array. This is not correct if out-of-order
1429 // named arguments were passed. 1427 // named arguments were passed.
1430 // The signature of the "noSuchMethod" method has to change from 1428 // The signature of the "noSuchMethod" method has to change from
1431 // noSuchMethod(String name, Array arguments) to something like 1429 // noSuchMethod(String name, Array arguments) to something like
1432 // noSuchMethod(InvocationMirror call). 1430 // noSuchMethod(InvocationMirror call).
1433 // Also, the class NoSuchMethodError has to be modified accordingly. 1431 // Also, the class NoSuchMethodError has to be modified accordingly.
1434 // Total number of args is the first Smi in args descriptor array (R10).
1435 const Immediate raw_null = 1432 const Immediate raw_null =
1436 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1433 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1437 __ movq(R13, FieldAddress(R10, Array::data_offset())); 1434 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1438 __ SmiUntag(R13); 1435 __ SmiUntag(R13);
1439 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver. 1436 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver.
1440 1437
1441 // Create a stub frame. 1438 // Create a stub frame.
1442 AssemblerMacros::EnterStubFrame(assembler); 1439 AssemblerMacros::EnterStubFrame(assembler);
1443 1440
1444 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. 1441 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod.
1445 __ pushq(RAX); // Receiver. 1442 __ pushq(RAX); // Receiver.
1446 __ pushq(RBX); // IC data array. 1443 __ pushq(RBX); // IC data array.
1447 __ pushq(R10); // Arguments descriptor array. 1444 __ pushq(R10); // Arguments descriptor array.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 1559
1563 // Loop that checks if there is an IC data match. 1560 // Loop that checks if there is an IC data match.
1564 Label loop, update, test, found, get_class_id_as_smi; 1561 Label loop, update, test, found, get_class_id_as_smi;
1565 // RBX: IC data object (preserved). 1562 // RBX: IC data object (preserved).
1566 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1563 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1567 // R12: ic_data_array with check entries: classes and target functions. 1564 // R12: ic_data_array with check entries: classes and target functions.
1568 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1565 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1569 // R12: points directly to the first ic data array element. 1566 // R12: points directly to the first ic data array element.
1570 1567
1571 // Get the receiver's class ID (first read number of arguments from 1568 // Get the receiver's class ID (first read number of arguments from
1572 // argument descriptor array and then access the receiver from the stack). 1569 // arguments descriptor array and then access the receiver from the stack).
1573 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1570 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1574 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. 1571 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1575 __ call(&get_class_id_as_smi); 1572 __ call(&get_class_id_as_smi);
1576 // RAX: receiver's class ID as smi. 1573 // RAX: receiver's class ID as smi.
1577 __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check. 1574 __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check.
1578 __ jmp(&test); 1575 __ jmp(&test);
1579 1576
1580 __ Bind(&loop); 1577 __ Bind(&loop);
1581 for (int i = 0; i < num_args; i++) { 1578 for (int i = 0; i < num_args; i++) {
1582 if (i > 0) { 1579 if (i > 0) {
1583 // If not the first, load the next argument's class ID. 1580 // If not the first, load the next argument's class ID.
1584 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1581 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1585 __ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize)); 1582 __ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize));
1586 __ call(&get_class_id_as_smi); 1583 __ call(&get_class_id_as_smi);
1587 // RAX: next argument class ID (smi). 1584 // RAX: next argument class ID (smi).
1588 __ movq(R13, Address(R12, i * kWordSize)); 1585 __ movq(R13, Address(R12, i * kWordSize));
1589 // R13: next class ID to check (smi). 1586 // R13: next class ID to check (smi).
1590 } 1587 }
1591 __ cmpq(RAX, R13); // Class id match? 1588 __ cmpq(RAX, R13); // Class id match?
1592 if (i < (num_args - 1)) { 1589 if (i < (num_args - 1)) {
1593 __ j(NOT_EQUAL, &update); // Continue. 1590 __ j(NOT_EQUAL, &update); // Continue.
1594 } else { 1591 } else {
1595 // Last check, all checks before matched. 1592 // Last check, all checks before matched.
1596 __ j(EQUAL, &found); // Break. 1593 __ j(EQUAL, &found); // Break.
1597 } 1594 }
1598 } 1595 }
1599 __ Bind(&update); 1596 __ Bind(&update);
1600 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1597 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1601 if (num_args > 1) { 1598 if (num_args > 1) {
1602 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1599 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1603 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); 1600 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0));
1604 __ call(&get_class_id_as_smi); 1601 __ call(&get_class_id_as_smi);
1605 } 1602 }
1606 1603
1607 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1604 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1608 __ addq(R12, Immediate(entry_size)); // Next entry. 1605 __ addq(R12, Immediate(entry_size)); // Next entry.
1609 __ movq(R13, Address(R12, 0)); // Next class ID. 1606 __ movq(R13, Address(R12, 0)); // Next class ID.
1610 1607
1611 __ Bind(&test); 1608 __ Bind(&test);
1612 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1609 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1613 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1614 1611
1615 // IC miss. 1612 // IC miss.
1616 const Immediate raw_null = 1613 const Immediate raw_null =
1617 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1614 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1618 // Compute address of arguments (first read number of arguments from 1615 // Compute address of arguments (first read number of arguments from
1619 // argument descriptor array and then compute address on the stack). 1616 // arguments descriptor array and then compute address on the stack).
1620 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1617 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1621 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1618 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1622 AssemblerMacros::EnterStubFrame(assembler); 1619 AssemblerMacros::EnterStubFrame(assembler);
1623 __ pushq(R10); // Preserve arguments array. 1620 __ pushq(R10); // Preserve arguments descriptor array.
1624 __ pushq(RBX); // Preserve IC data array 1621 __ pushq(RBX); // Preserve IC data array
1625 __ pushq(raw_null); // Setup space on stack for result (target code object). 1622 __ pushq(raw_null); // Setup space on stack for result (target code object).
1626 // Push call arguments. 1623 // Push call arguments.
1627 for (intptr_t i = 0; i < num_args; i++) { 1624 for (intptr_t i = 0; i < num_args; i++) {
1628 __ movq(R10, Address(RAX, -kWordSize * i)); 1625 __ movq(R10, Address(RAX, -kWordSize * i));
1629 __ pushq(R10); 1626 __ pushq(R10);
1630 } 1627 }
1631 if (num_args == 1) { 1628 if (num_args == 1) {
1632 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); 1629 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
1633 } else if (num_args == 2) { 1630 } else if (num_args == 2) {
1634 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1631 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry);
1635 } else if (num_args == 3) { 1632 } else if (num_args == 3) {
1636 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1633 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry);
1637 } else { 1634 } else {
1638 UNIMPLEMENTED(); 1635 UNIMPLEMENTED();
1639 } 1636 }
1640 // Remove call arguments pushed earlier. 1637 // Remove call arguments pushed earlier.
1641 for (intptr_t i = 0; i < num_args; i++) { 1638 for (intptr_t i = 0; i < num_args; i++) {
1642 __ popq(RAX); 1639 __ popq(RAX);
1643 } 1640 }
1644 __ popq(RAX); // Pop returned code object into RAX (null if not found). 1641 __ popq(RAX); // Pop returned code object into RAX (null if not found).
1645 __ popq(RBX); // Restore IC data array. 1642 __ popq(RBX); // Restore IC data array.
1646 __ popq(R10); // Restore arguments array. 1643 __ popq(R10); // Restore arguments descriptor array.
1647 __ LeaveFrame(); 1644 __ LeaveFrame();
1648 Label call_target_function; 1645 Label call_target_function;
1649 __ cmpq(RAX, raw_null); 1646 __ cmpq(RAX, raw_null);
1650 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); 1647 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump);
1651 // NoSuchMethod or closure. 1648 // NoSuchMethod or closure.
1652 // Mark IC call that it may be a closure call that does not collect 1649 // Mark IC call that it may be a closure call that does not collect
1653 // type feedback. 1650 // type feedback.
1654 __ movb(FieldAddress(RBX, ICData::is_closure_call_offset()), Immediate(1)); 1651 __ movb(FieldAddress(RBX, ICData::is_closure_call_offset()), Immediate(1));
1655 __ jmp(&StubCode::InstanceFunctionLookupLabel()); 1652 __ jmp(&StubCode::InstanceFunctionLookupLabel());
1656 1653
(...skipping 25 matching lines...) Expand all
1682 __ Bind(&not_smi); 1679 __ Bind(&not_smi);
1683 __ LoadClassId(RAX, RAX); 1680 __ LoadClassId(RAX, RAX);
1684 __ SmiTag(RAX); 1681 __ SmiTag(RAX);
1685 __ ret(); 1682 __ ret();
1686 } 1683 }
1687 1684
1688 1685
1689 // Use inline cache data array to invoke the target or continue in inline 1686 // Use inline cache data array to invoke the target or continue in inline
1690 // cache miss handler. Stub for 1-argument check (receiver class). 1687 // cache miss handler. Stub for 1-argument check (receiver class).
1691 // RBX: Inline cache data object. 1688 // RBX: Inline cache data object.
1692 // RDX: Arguments array. 1689 // R10: Arguments descriptor array.
1693 // TOS(0): Return address. 1690 // TOS(0): Return address.
1694 // Inline cache data object structure: 1691 // Inline cache data object structure:
1695 // 0: function-name 1692 // 0: function-name
1696 // 1: N, number of arguments checked. 1693 // 1: N, number of arguments checked.
1697 // 2 .. (length - 1): group of checks, each check containing: 1694 // 2 .. (length - 1): group of checks, each check containing:
1698 // - N classes. 1695 // - N classes.
1699 // - 1 target function. 1696 // - 1 target function.
1700 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1697 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1701 GenerateUsageCounterIncrement(assembler, RCX); 1698 GenerateUsageCounterIncrement(assembler, RCX);
1702 GenerateNArgsCheckInlineCacheStub(assembler, 1); 1699 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1703 } 1700 }
1704 1701
1705 1702
1706 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1703 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1707 GenerateUsageCounterIncrement(assembler, RCX); 1704 GenerateUsageCounterIncrement(assembler, RCX);
1708 GenerateNArgsCheckInlineCacheStub(assembler, 2); 1705 GenerateNArgsCheckInlineCacheStub(assembler, 2);
1709 } 1706 }
1710 1707
1711 1708
1712 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { 1709 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
1713 GenerateUsageCounterIncrement(assembler, RCX); 1710 GenerateUsageCounterIncrement(assembler, RCX);
1714 GenerateNArgsCheckInlineCacheStub(assembler, 3); 1711 GenerateNArgsCheckInlineCacheStub(assembler, 3);
1715 } 1712 }
1716 1713
1717 // Use inline cache data array to invoke the target or continue in inline 1714 // Use inline cache data array to invoke the target or continue in inline
1718 // cache miss handler. Stub for 1-argument check (receiver class). 1715 // cache miss handler. Stub for 1-argument check (receiver class).
1719 // RDI: function which counter needs to be incremented. 1716 // RDI: function which counter needs to be incremented.
1720 // RBX: Inline cache data object. 1717 // RBX: Inline cache data object.
1721 // RDX: Arguments array. 1718 // R10: Arguments descriptor array.
1722 // TOS(0): Return address. 1719 // TOS(0): Return address.
1723 // Inline cache data object structure: 1720 // Inline cache data object structure:
1724 // 0: function-name 1721 // 0: function-name
1725 // 1: N, number of arguments checked. 1722 // 1: N, number of arguments checked.
1726 // 2 .. (length - 1): group of checks, each check containing: 1723 // 2 .. (length - 1): group of checks, each check containing:
1727 // - N classes. 1724 // - N classes.
1728 // - 1 target function. 1725 // - 1 target function.
1729 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1726 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1730 Assembler* assembler) { 1727 Assembler* assembler) {
1731 GenerateOptimizedUsageCounterIncrement(assembler); 1728 GenerateOptimizedUsageCounterIncrement(assembler);
(...skipping 20 matching lines...) Expand all
1752 GenerateNArgsCheckInlineCacheStub(assembler, 1); 1749 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1753 } 1750 }
1754 1751
1755 1752
1756 // Megamorphic call is currently implemented as IC call but through a stub 1753 // Megamorphic call is currently implemented as IC call but through a stub
1757 // that does not check/count function invocations. 1754 // that does not check/count function invocations.
1758 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { 1755 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
1759 GenerateNArgsCheckInlineCacheStub(assembler, 1); 1756 GenerateNArgsCheckInlineCacheStub(assembler, 1);
1760 } 1757 }
1761 1758
1762 // R10: Arguments array. 1759 // R10: Arguments descriptor array.
1763 // TOS(0): return address (Dart code). 1760 // TOS(0): return address (Dart code).
1764 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1761 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1765 const Immediate raw_null = 1762 const Immediate raw_null =
1766 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1763 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1767 AssemblerMacros::EnterStubFrame(assembler); 1764 AssemblerMacros::EnterStubFrame(assembler);
1768 __ pushq(R10); // Preserve arguments descriptor. 1765 __ pushq(R10); // Preserve arguments descriptor.
1769 __ pushq(raw_null); // Room for result. 1766 __ pushq(raw_null); // Room for result.
1770 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); 1767 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
1771 __ popq(RAX); // Code object. 1768 __ popq(RAX); // Code object.
1772 __ popq(R10); // Restore arguments descriptor. 1769 __ popq(R10); // Restore arguments descriptor.
(...skipping 15 matching lines...) Expand all
1788 __ popq(RAX); 1785 __ popq(RAX);
1789 __ LeaveFrame(); 1786 __ LeaveFrame();
1790 1787
1791 __ popq(R11); // discard return address of call to this stub. 1788 __ popq(R11); // discard return address of call to this stub.
1792 __ LeaveFrame(); 1789 __ LeaveFrame();
1793 __ ret(); 1790 __ ret();
1794 } 1791 }
1795 1792
1796 1793
1797 // RBX: Inline cache data array. 1794 // RBX: Inline cache data array.
1798 // R10: Arguments array. 1795 // R10: Arguments descriptor array.
1799 // TOS(0): return address (Dart code). 1796 // TOS(0): return address (Dart code).
1800 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { 1797 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
1801 AssemblerMacros::EnterStubFrame(assembler); 1798 AssemblerMacros::EnterStubFrame(assembler);
1802 __ pushq(RBX); 1799 __ pushq(RBX);
1803 __ pushq(R10); 1800 __ pushq(R10);
1804 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); 1801 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
1805 __ popq(R10); 1802 __ popq(R10);
1806 __ popq(RBX); 1803 __ popq(RBX);
1807 __ LeaveFrame(); 1804 __ LeaveFrame();
1808 1805
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
2163 __ cmpq(left, right); 2160 __ cmpq(left, right);
2164 __ Bind(&done); 2161 __ Bind(&done);
2165 __ popq(right); 2162 __ popq(right);
2166 __ popq(left); 2163 __ popq(left);
2167 __ ret(); 2164 __ ret();
2168 } 2165 }
2169 2166
2170 } // namespace dart 2167 } // namespace dart
2171 2168
2172 #endif // defined TARGET_ARCH_X64 2169 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/dart_entry.cc ('K') | « runtime/vm/stub_code_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698