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

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
« no previous file with comments | « runtime/vm/raw_object.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 159 }
160 160
161 161
162 // Input parameters: 162 // Input parameters:
163 // RSP : points to return address. 163 // RSP : points to return address.
164 // RSP + 8 : address of return value. 164 // RSP + 8 : address of return value.
165 // RAX : address of first argument in argument array. 165 // RAX : address of first argument in argument array.
166 // RAX - 8*R10 + 8 : address of last argument in argument array. 166 // RAX - 8*R10 + 8 : address of last argument in argument array.
167 // RBX : address of the native function to call. 167 // RBX : address of the native function to call.
168 // R10 : number of arguments to the call. 168 // R10 : number of arguments to the call.
169 // Uses R8.
170 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) { 169 void StubCode::GenerateCallNativeCFunctionStub(Assembler* assembler) {
171 const intptr_t native_args_struct_offset = 0; 170 const intptr_t native_args_struct_offset = 0;
172 const intptr_t isolate_offset = 171 const intptr_t isolate_offset =
173 NativeArguments::isolate_offset() + native_args_struct_offset; 172 NativeArguments::isolate_offset() + native_args_struct_offset;
174 const intptr_t argc_offset = 173 const intptr_t argc_offset =
175 NativeArguments::argc_offset() + native_args_struct_offset; 174 NativeArguments::argc_offset() + native_args_struct_offset;
176 const intptr_t argv_offset = 175 const intptr_t argv_offset =
177 NativeArguments::argv_offset() + native_args_struct_offset; 176 NativeArguments::argv_offset() + native_args_struct_offset;
178 const intptr_t retval_offset = 177 const intptr_t retval_offset =
179 NativeArguments::retval_offset() + native_args_struct_offset; 178 NativeArguments::retval_offset() + native_args_struct_offset;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 // Remove the stub frame as we are about to jump to the dart function. 267 // Remove the stub frame as we are about to jump to the dart function.
269 __ LeaveFrame(); 268 __ LeaveFrame();
270 __ movq(RAX, FieldAddress(RBX, Function::code_offset())); 269 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
271 270
272 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); 271 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
273 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 272 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
274 __ jmp(RBX); 273 __ jmp(RBX);
275 } 274 }
276 275
277 276
277 // Called when number of invocations exceeds
278 // --optimization_invocation_threshold.
279 // RAX: target function.
280 // R10: arguments descriptor array (num_args is first Smi element).
278 void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) { 281 void StubCode::GenerateOptimizeInvokedFunctionStub(Assembler* assembler) {
279 __ Unimplemented("OptimizeInvokedFunction stub"); 282 __ Untested("OptimizeInvokedFunction stub");
283 __ EnterFrame(0);
284 __ pushq(R10); // Preserve arguments descriptor array.
285 __ pushq(RAX); // Preserve target function.
286 __ pushq(RAX); // Target function.
287 __ CallRuntimeFromStub(kOptimizeInvokedFunctionRuntimeEntry);
288 __ popq(RAX); // discard argument.
289 __ popq(RAX); // Restore function.
290 __ popq(R10); // Restore arguments descriptor array.
291 __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
292 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
293 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
294 __ LeaveFrame();
295 __ jmp(RAX);
296 __ int3();
280 } 297 }
281 298
282 299
300 // Called from a static call only when an invalid code has been entered
301 // (invalid because its function was optimized or deoptimized).
302 // RBX: function object.
303 // R10: arguments descriptor array (num_args is first Smi element).
283 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 304 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
284 __ Unimplemented("FixCallersTarget stub"); 305 __ Untested("FixCallersTarget stub");
306 __ EnterFrame(0);
307 __ pushq(R10); // Preserve arguments descriptor array.
308 __ pushq(RBX); // Preserve target function.
309 __ pushq(RBX); // Target function.
310 __ CallRuntimeFromStub(kFixCallersTargetRuntimeEntry);
311 __ popq(RAX); // discard argument.
312 __ popq(RAX); // Restore function.
313 __ popq(R10); // Restore arguments descriptor array.
314 __ movq(RAX, FieldAddress(RAX, Function::code_offset()));
315 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
316 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
317 __ LeaveFrame();
318 __ jmp(RAX);
319 __ int3();
285 } 320 }
286 321
287 322
288 // Lookup for [function-name, arg count] in 'functions_map_'. 323 // Lookup for [function-name, arg count] in 'functions_map_'.
289 // Input parameters (to be treated as read only, unless calling to target!): 324 // Input parameters (to be treated as read only, unless calling to target!):
290 // RBX: ic-data array. 325 // RBX: ic-data array.
291 // R10: arguments descriptor array (num_args is first Smi element). 326 // R10: arguments descriptor array (num_args is first Smi element).
292 // Stack: return address, arguments. 327 // Stack: return address, arguments.
293 // If the lookup succeeds we jump to the target method from here, otherwise 328 // If the lookup succeeds we jump to the target method from here, otherwise
294 // we continue in code generated by the caller of 'MegamorphicLookup'. 329 // we continue in code generated by the caller of 'MegamorphicLookup'.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 __ Bind(&next_iteration); 398 __ Bind(&next_iteration);
364 __ AddImmediate(R12, Immediate(FunctionsCache::kNumEntries * kWordSize)); 399 __ AddImmediate(R12, Immediate(FunctionsCache::kNumEntries * kWordSize));
365 __ jmp(&loop, Assembler::kNearJump); 400 __ jmp(&loop, Assembler::kNearJump);
366 401
367 __ Bind(&not_found); 402 __ Bind(&not_found);
368 } 403 }
369 404
370 405
371 // Input parameters: 406 // Input parameters:
372 // R13: argument count, may be zero. 407 // R13: argument count, may be zero.
373 // Uses RAX, RBX, R10, R12.
374 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) { 408 static void PushArgumentsArray(Assembler* assembler, intptr_t arg_offset) {
375 const Immediate raw_null = 409 const Immediate raw_null =
376 Immediate(reinterpret_cast<intptr_t>(Object::null())); 410 Immediate(reinterpret_cast<intptr_t>(Object::null()));
377 411
378 // Allocate array to store arguments of caller. 412 // Allocate array to store arguments of caller.
379 __ movq(R10, R13); // Arguments array length. 413 __ movq(R10, R13); // Arguments array length.
380 __ SmiTag(R10); // Convert to Smi. 414 __ SmiTag(R10); // Convert to Smi.
381 __ movq(RBX, raw_null); // Null element type for raw Array. 415 __ movq(RBX, raw_null); // Null element type for raw Array.
382 __ call(&StubCode::AllocateArrayLabel()); 416 __ call(&StubCode::AllocateArrayLabel());
383 __ SmiUntag(R10); 417 __ SmiUntag(R10);
(...skipping 14 matching lines...) Expand all
398 __ j(POSITIVE, &loop, Assembler::kNearJump); 432 __ j(POSITIVE, &loop, Assembler::kNearJump);
399 } 433 }
400 434
401 435
402 // Input parameters: 436 // Input parameters:
403 // RBX: ic-data array. 437 // RBX: ic-data array.
404 // R10: arguments descriptor array (num_args is first Smi element). 438 // R10: arguments descriptor array (num_args is first Smi element).
405 // Note: The receiver object is the first argument to the function being 439 // Note: The receiver object is the first argument to the function being
406 // called, the stub accesses the receiver from this location directly 440 // called, the stub accesses the receiver from this location directly
407 // when trying to resolve the call. 441 // when trying to resolve the call.
408 // Uses R13.
409 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { 442 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
410 const Immediate raw_null = 443 const Immediate raw_null =
411 Immediate(reinterpret_cast<intptr_t>(Object::null())); 444 Immediate(reinterpret_cast<intptr_t>(Object::null()));
412 445
413 MegamorphicLookup(assembler); 446 MegamorphicLookup(assembler);
414 // Lookup in function_table_ failed, resolve, compile and enter function 447 // Lookup in function_table_ failed, resolve, compile and enter function
415 // into function_table_. 448 // into function_table_.
416 449
417 // Create a stub frame as we are pushing some objects on the stack before 450 // Create a stub frame as we are pushing some objects on the stack before
418 // calling into the runtime. 451 // calling into the runtime.
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 __ popq(RAX); 619 __ popq(RAX);
587 __ popq(RAX); // Get result into RAX. 620 __ popq(RAX); // Get result into RAX.
588 621
589 // Remove the stub frame as we are about to return. 622 // Remove the stub frame as we are about to return.
590 __ LeaveFrame(); 623 __ LeaveFrame();
591 __ ret(); 624 __ ret();
592 } 625 }
593 626
594 627
595 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 628 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
596 __ Unimplemented("Deoptimize stub"); 629 __ Untested("Deoptimize stub");
630 __ EnterFrame(0);
631 // RAX: deoptimization reason id.
632 // Stack at this point:
633 // TOS + 0: Saved EBP of function frame that will be deoptimized. <== EBP
634 // TOS + 1: Deoptimization point (return address), will be patched.
635 // TOS + 2: top-of-stack at deoptimization point (all arguments on stack).
636 __ pushq(RAX);
637 __ CallRuntimeFromStub(kDeoptimizeRuntimeEntry);
638 __ popq(RAX);
639 __ LeaveFrame();
640 __ ret();
597 } 641 }
598 642
599 643
600 // Called for inline allocation of arrays. 644 // Called for inline allocation of arrays.
601 // Input parameters: 645 // Input parameters:
602 // R10 : Array length as Smi. 646 // R10 : Array length as Smi.
603 // RBX : array element type (either NULL or an instantiated type). 647 // RBX : array element type (either NULL or an instantiated type).
604 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. 648 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
605 // The newly allocated object is returned in RAX. 649 // The newly allocated object is returned in RAX.
606 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 650 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); 713 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset()));
670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); 714 __ movq(RBX, Address(RBX, Isolate::object_store_offset()));
671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); 715 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset()));
672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); 716 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX);
673 // Calculate the size tag. 717 // Calculate the size tag.
674 // RAX: new object start as a tagged pointer. 718 // RAX: new object start as a tagged pointer.
675 // R12: new object end address. 719 // R12: new object end address.
676 // R10: Array length as Smi. 720 // R10: Array length as Smi.
677 { 721 {
678 Label size_tag_overflow, done; 722 Label size_tag_overflow, done;
679 __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi. 723 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi.
680 ASSERT(kSmiTagShift == 1); 724 ASSERT(kSmiTagShift == 1);
681 __ andq(RBX, Immediate(-kObjectAlignment)); 725 __ andq(RBX, Immediate(-kObjectAlignment));
682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); 726 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag));
683 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); 727 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
684 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); 728 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2));
685 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); 729 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX);
686 __ jmp(&done); 730 __ jmp(&done);
687 731
688 __ Bind(&size_tag_overflow); 732 __ Bind(&size_tag_overflow);
689 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); 733 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0));
690 __ Bind(&done); 734 __ Bind(&done);
691 } 735 }
692 736
693 // Initialize all array elements to raw_null. 737 // Initialize all array elements to raw_null.
694 // RAX: new object start as a tagged pointer. 738 // RAX: new object start as a tagged pointer.
695 // R12: new object end address. 739 // R12: new object end address.
740 __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
696 // RBX: iterator which initially points to the start of the variable 741 // RBX: iterator which initially points to the start of the variable
697 // data area to be initialized. 742 // data area to be initialized.
698 __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
699 Label done; 743 Label done;
700 Label init_loop; 744 Label init_loop;
701 __ Bind(&init_loop); 745 __ Bind(&init_loop);
702 __ cmpq(RBX, R12); 746 __ cmpq(RBX, R12);
703 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 747 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
704 __ movq(Address(RBX, 0), raw_null); 748 __ movq(Address(RBX, 0), raw_null);
705 __ addq(RBX, Immediate(kWordSize)); 749 __ addq(RBX, Immediate(kWordSize));
706 __ jmp(&init_loop, Assembler::kNearJump); 750 __ jmp(&init_loop, Assembler::kNearJump);
707 __ Bind(&done); 751 __ Bind(&done);
708 752
(...skipping 14 matching lines...) Expand all
723 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); 767 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry);
724 __ popq(RAX); // Pop instantiator. 768 __ popq(RAX); // Pop instantiator.
725 __ popq(RAX); // Pop element type argument. 769 __ popq(RAX); // Pop element type argument.
726 __ popq(R10); // Pop array length argument. 770 __ popq(R10); // Pop array length argument.
727 __ popq(RAX); // Pop return value from return slot. 771 __ popq(RAX); // Pop return value from return slot.
728 __ LeaveFrame(); 772 __ LeaveFrame();
729 __ ret(); 773 __ ret();
730 } 774 }
731 775
732 776
777 // Input parameters:
778 // R10: Arguments descriptor array (num_args is first Smi element, closure
779 // object is not included in num_args).
780 // Note: The closure object is pushed before the first argument to the function
781 // being called, the stub accesses the closure from this location directly
782 // when setting up the context and resolving the entry point.
733 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 783 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
734 __ Unimplemented("CallClosureFunction stub"); 784 const Immediate raw_null =
785 Immediate(reinterpret_cast<intptr_t>(Object::null()));
786
787 // Total number of args is the first Smi in args descriptor array (R10).
788 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args.
789 // Load closure object in R13.
790 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi.
791
792 // Verify that R13 is a closure by checking its class.
793 Label not_closure;
794 __ cmpq(R13, raw_null);
795 // Not a closure, but null object.
796 __ j(EQUAL, &not_closure, Assembler::kNearJump);
797 __ testq(R13, Immediate(kSmiTagMask));
798 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi.
799 // Verify that the class of the object is a closure class by checking that
800 // class.signature_function() is not null.
801 __ movq(RAX, FieldAddress(R13, Object::class_offset()));
802 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset()));
803 __ cmpq(RAX, raw_null);
804 // Actual class is not a closure class.
805 __ j(EQUAL, &not_closure, Assembler::kNearJump);
806
807 // RAX is just the signature function. Load the actual closure function.
808 __ movq(RBX, FieldAddress(R13, Closure::function_offset()));
809
810 // Load closure context in CTX; note that CTX has already been preserved.
811 __ movq(CTX, FieldAddress(R13, Closure::context_offset()));
812
813 // Load closure function code in RAX.
814 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
815 __ cmpq(RAX, raw_null);
816 Label function_compiled;
817 __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump);
818
819 // Create a stub frame as we are pushing some objects on the stack before
820 // calling into the runtime.
821 __ EnterFrame(0);
822
823 __ pushq(R10); // Preserve arguments descriptor array.
824 __ pushq(RBX); // Preserve read-only function object argument.
825 __ CallRuntimeFromStub(kCompileFunctionRuntimeEntry);
826 __ popq(RBX); // Restore read-only function object argument in RBX.
827 __ popq(R10); // Restore arguments descriptor array.
828 // Restore RAX.
829 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
830
831 // Remove the stub frame as we are about to jump to the closure function.
832 __ LeaveFrame();
833
834 __ Bind(&function_compiled);
835 // RAX: Code.
836 // RBX: Function.
837 // R10: Arguments descriptor array (num_args is first Smi element).
838
839 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
840 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
841 __ jmp(RBX);
842
843 __ Bind(&not_closure);
844 // Call runtime to report that a closure call was attempted on a non-closure
845 // object, passing the non-closure object and its arguments array.
846 // R13: non-closure object.
847 // R10: arguments descriptor array (num_args is first Smi element, closure
848 // object is not included in num_args).
849
850 // Create a stub frame as we are pushing some objects on the stack before
851 // calling into the runtime.
852 __ EnterFrame(0);
853
854 __ pushq(raw_null); // Setup space on stack for result from error reporting.
855 __ pushq(R13); // Non-closure object.
856 // Total number of args is the first Smi in args descriptor array (R10).
857 __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args.
858 __ SmiUntag(R13);
859 // See stack layout below explaining "wordSize * 4" offset.
860 PushArgumentsArray(assembler, (kWordSize * 4));
861
862 // Stack:
863 // TOS + 0: Argument array.
864 // TOS + 1: Non-closure object.
865 // TOS + 2: Place for result from reporting the error.
866 // TOS + 3: Saved RBP of previous frame. <== RBP
867 // TOS + 4: Dart code return address
868 // TOS + 5: Last argument of caller.
869 // ....
870 __ CallRuntimeFromStub(kReportObjectNotClosureRuntimeEntry);
871 __ Stop("runtime call throws an exception");
735 } 872 }
736 873
737 874
738 // Called when invoking Dart code from C++ (VM code). 875 // Called when invoking Dart code from C++ (VM code).
739 // Input parameters: 876 // Input parameters:
740 // RSP : points to return address. 877 // RSP : points to return address.
741 // RDI : entrypoint of the Dart function to call. 878 // RDI : entrypoint of the Dart function to call.
742 // RSI : arguments descriptor array. 879 // RSI : arguments descriptor array.
743 // RDX : pointer to the argument array. 880 // RDX : pointer to the argument array.
744 // RCX : new context containing the current isolate pointer. 881 // RCX : new context containing the current isolate pointer.
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 983
847 // Restore the frame pointer. 984 // Restore the frame pointer.
848 __ LeaveFrame(); 985 __ LeaveFrame();
849 986
850 __ ret(); 987 __ ret();
851 } 988 }
852 989
853 990
854 // Called for inline allocation of contexts. 991 // Called for inline allocation of contexts.
855 // Input: 992 // Input:
856 // RDX: number of context variables. 993 // R10: number of context variables.
857 // Output: 994 // Output:
858 // RAX: new allocated RawContext object. 995 // RAX: new allocated RawContext object.
859 // RBX and RDX are destroyed.
860 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 996 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
861 const Immediate raw_null = 997 const Immediate raw_null =
862 Immediate(reinterpret_cast<intptr_t>(Object::null())); 998 Immediate(reinterpret_cast<intptr_t>(Object::null()));
863 if (false) { 999 if (FLAG_inline_alloc) {
864 // TODO(regis): Implement fast inline allocation of contexts. 1000 const Class& context_class = Class::ZoneHandle(Object::context_class());
865 __ Unimplemented("AllocateContext stub - inline allocation"); 1001 Label slow_case;
1002 Heap* heap = Isolate::Current()->heap();
1003 // First compute the rounded instance size.
1004 // R10: number of context variables.
1005 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
1006 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
1007 __ andq(R13, Immediate(-kObjectAlignment));
1008
1009 // Now allocate the object.
1010 // R10: number of context variables.
1011 __ movq(RAX, Immediate(heap->TopAddress()));
1012 __ movq(RAX, Address(RAX, 0));
1013 __ addq(R13, RAX);
1014 // Check if the allocation fits into the remaining space.
1015 // RAX: potential new object.
1016 // R13: potential next object start.
1017 // R10: number of context variables.
1018 __ movq(RDI, Immediate(heap->EndAddress()));
1019 __ cmpq(R13, Address(RDI, 0));
1020 if (FLAG_use_slow_path) {
1021 __ jmp(&slow_case);
1022 } else {
1023 __ j(ABOVE_EQUAL, &slow_case);
1024 }
1025
1026 // Successfully allocated the object, now update top to point to
1027 // next object start and initialize the object.
1028 // RAX: new object.
1029 // R13: next object start.
1030 // R10: number of context variables.
1031 __ movq(RDI, Immediate(heap->TopAddress()));
1032 __ movq(Address(RDI, 0), R13);
1033 __ addq(RAX, Immediate(kHeapObjectTag));
1034
1035 // Initialize the class field in the context object.
1036 // RAX: new object.
1037 // R10: number of context variables.
1038 __ LoadObject(R13, context_class); // Load up class field of context.
1039 __ StoreIntoObject(RAX,
1040 FieldAddress(RAX, Context::class_offset()),
1041 R13);
1042 // Calculate the size tag.
1043 // RAX: new object.
1044 // R10: number of context variables.
1045 {
1046 Label size_tag_overflow, done;
1047 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
1048 __ andq(R13, Immediate(-kObjectAlignment));
1049 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag));
1050 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
1051 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2));
1052 __ movq(FieldAddress(RAX, Context::tags_offset()), R13); // Tags.
1053 __ jmp(&done);
1054
1055 __ Bind(&size_tag_overflow);
1056 // Set overflow size tag value.
1057 __ movq(FieldAddress(RAX, Context::tags_offset()), Immediate(0));
1058 __ Bind(&done);
1059 }
1060
1061 // Setup up number of context variables field.
1062 // RAX: new object.
1063 // R10: number of context variables as integer value (not object).
1064 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
1065
1066 // Setup isolate field.
1067 // Load Isolate pointer from Context structure into R13.
1068 // RAX: new object.
1069 // R10: number of context variables.
1070 __ movq(R13, FieldAddress(CTX, Context::isolate_offset()));
1071 // R13: Isolate, not an object.
1072 __ movq(FieldAddress(RAX, Context::isolate_offset()), R13);
1073
1074 const Immediate raw_null =
1075 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1076 // Setup the parent field.
1077 // RAX: new object.
1078 // R10: number of context variables.
1079 __ movq(FieldAddress(RAX, Context::parent_offset()), raw_null);
1080
1081 // Initialize the context variables.
1082 // RAX: new object.
1083 // R10: number of context variables.
1084 {
1085 Label loop, entry;
1086 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
1087
1088 __ jmp(&entry, Assembler::kNearJump);
1089 __ Bind(&loop);
1090 __ decq(R10);
1091 __ movq(Address(R13, R10, TIMES_8, 0), raw_null);
1092 __ Bind(&entry);
1093 __ cmpq(R10, Immediate(0));
1094 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1095 }
1096
1097 // Done allocating and initializing the context.
1098 // RAX: new object.
1099 __ ret();
1100
1101 __ Bind(&slow_case);
866 } 1102 }
867 // Create the stub frame. 1103 // Create a stub frame.
868 __ EnterFrame(0); 1104 __ EnterFrame(0);
869 __ pushq(raw_null); // Setup space on stack for the return value. 1105 __ pushq(raw_null); // Setup space on stack for the return value.
870 __ SmiTag(RDX); 1106 __ SmiTag(R10);
871 __ pushq(RDX); // Push number of context variables. 1107 __ pushq(R10); // Push number of context variables.
872 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. 1108 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context.
873 __ popq(RAX); // Pop number of context variables argument. 1109 __ popq(RAX); // Pop number of context variables argument.
874 __ popq(RAX); // Pop the new context object. 1110 __ popq(RAX); // Pop the new context object.
875 // RAX: new object 1111 // RAX: new object
876 // Restore the frame pointer. 1112 // Restore the frame pointer.
877 __ LeaveFrame(); 1113 __ LeaveFrame();
878 __ ret(); 1114 __ ret();
879 } 1115 }
880 1116
881 1117
882
883
884 // Called for inline allocation of objects. 1118 // Called for inline allocation of objects.
885 // Input parameters: 1119 // Input parameters:
886 // RSP + 16 : type arguments object (only if class is parameterized). 1120 // RSP + 16 : type arguments object (only if class is parameterized).
887 // RSP + 8 : type arguments of instantiator (only if class is parameterized). 1121 // RSP + 8 : type arguments of instantiator (only if class is parameterized).
888 // RSP : points to return address. 1122 // RSP : points to return address.
889 // Uses RAX, RBX, RCX, RDX, RDI as temporary registers.
890 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1123 void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
891 const Class& cls) { 1124 const Class& cls) {
892 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; 1125 const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize;
893 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; 1126 const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize;
894 const Immediate raw_null = 1127 const Immediate raw_null =
895 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1128 Immediate(reinterpret_cast<intptr_t>(Object::null()));
896 // The generated code is different if the class is parameterized. 1129 // The generated code is different if the class is parameterized.
897 const bool is_cls_parameterized = 1130 const bool is_cls_parameterized =
898 cls.type_arguments_instance_field_offset() != Class::kNoTypeArguments; 1131 cls.type_arguments_instance_field_offset() != Class::kNoTypeArguments;
899 // kInlineInstanceSize is a constant used as a threshold for determining 1132 // kInlineInstanceSize is a constant used as a threshold for determining
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 } 1309 }
1077 1310
1078 1311
1079 // Called for inline allocation of closures. 1312 // Called for inline allocation of closures.
1080 // Input parameters: 1313 // Input parameters:
1081 // If the signature class is not parameterized, the receiver, if any, will be 1314 // If the signature class is not parameterized, the receiver, if any, will be
1082 // at RSP + 8 instead of RSP + 16, since no type arguments are passed. 1315 // at RSP + 8 instead of RSP + 16, since no type arguments are passed.
1083 // RSP + 16 (or RSP + 8): receiver (only if implicit instance closure). 1316 // RSP + 16 (or RSP + 8): receiver (only if implicit instance closure).
1084 // RSP + 8 : type arguments object (only if signature class is parameterized). 1317 // RSP + 8 : type arguments object (only if signature class is parameterized).
1085 // RSP : points to return address. 1318 // RSP : points to return address.
1086 // Uses RAX, RCX as temporary registers.
1087 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, 1319 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler,
1088 const Function& func) { 1320 const Function& func) {
1089 const Immediate raw_null = 1321 const Immediate raw_null =
1090 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1322 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1091 ASSERT(func.IsClosureFunction()); 1323 ASSERT(func.IsClosureFunction());
1092 const bool is_implicit_static_closure = 1324 const bool is_implicit_static_closure =
1093 func.IsImplicitStaticClosureFunction(); 1325 func.IsImplicitStaticClosureFunction();
1094 const bool is_implicit_instance_closure = 1326 const bool is_implicit_instance_closure =
1095 func.IsImplicitInstanceClosureFunction(); 1327 func.IsImplicitInstanceClosureFunction();
1096 const Class& cls = Class::ZoneHandle(func.signature_class()); 1328 const Class& cls = Class::ZoneHandle(func.signature_class());
1097 const bool has_type_arguments = cls.HasTypeArguments(); 1329 const bool has_type_arguments = cls.HasTypeArguments();
1098 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 1330 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
1099 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize; 1331 const intptr_t kReceiverOffset = (has_type_arguments ? 2 : 1) * kWordSize;
1100 if (false) { 1332 const intptr_t closure_size = Closure::InstanceSize();
1101 // TODO(regis): Implement inline context allocation. 1333 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver.
1102 __ Unimplemented("AllocateClosure stub - inline allocation"); 1334 if (FLAG_inline_alloc &&
1335 PageSpace::IsPageAllocatableSize(closure_size + context_size)) {
1336 Label slow_case;
1337 Heap* heap = Isolate::Current()->heap();
1338 __ movq(RAX, Immediate(heap->TopAddress()));
1339 __ movq(RAX, Address(RAX, 0));
1340 __ leaq(R13, Address(RAX, closure_size));
1341 if (is_implicit_instance_closure) {
1342 __ movq(RBX, R13); // RBX: new context address.
1343 __ addq(R13, Immediate(context_size));
1344 }
1345 // Check if the allocation fits into the remaining space.
1346 // RAX: potential new closure object.
1347 // RBX: potential new context object (only if is_implicit_closure).
1348 // R13: potential next object start.
1349 __ movq(RDI, Immediate(heap->EndAddress()));
1350 __ cmpq(R13, Address(RDI, 0));
1351 if (FLAG_use_slow_path) {
1352 __ jmp(&slow_case);
1353 } else {
1354 __ j(ABOVE_EQUAL, &slow_case);
1355 }
1356
1357 // Successfully allocated the object, now update top to point to
1358 // next object start and initialize the object.
1359 __ movq(RDI, Immediate(heap->TopAddress()));
1360 __ movq(Address(RDI, 0), R13);
1361
1362 // Initialize the class field in the object.
1363 // RAX: new closure object.
1364 // RBX: new context object (only if is_implicit_closure).
1365 __ LoadObject(R10, cls); // Load signature class of closure.
1366 __ movq(Address(RAX, Closure::class_offset()), R10);
1367 // Set the tags.
1368 __ movq(Address(RAX, Closure::tags_offset()),
1369 Immediate(RawObject::SizeTag::encode(closure_size)));
1370
1371 // Initialize the function field in the object.
1372 // RAX: new closure object.
1373 // RBX: new context object (only if is_implicit_closure).
1374 // R13: next object start.
1375 __ LoadObject(R10, func); // Load function of closure to be allocated.
1376 __ movq(Address(RAX, Closure::function_offset()), R10);
1377
1378 // Setup the context for this closure.
1379 if (is_implicit_static_closure) {
1380 ObjectStore* object_store = Isolate::Current()->object_store();
1381 ASSERT(object_store != NULL);
1382 const Context& empty_context =
1383 Context::ZoneHandle(object_store->empty_context());
1384 __ LoadObject(R10, empty_context);
1385 __ movq(Address(RAX, Closure::context_offset()), R10);
1386 } else if (is_implicit_instance_closure) {
1387 // Initialize the new context capturing the receiver.
1388
1389 // Set the class field to the Context class.
1390 __ LoadObject(R13, Class::ZoneHandle(Object::context_class()));
1391 __ movq(Address(RBX, Context::class_offset()), R13);
1392 // Set the tags.
1393 __ movq(Address(RBX, Context::tags_offset()),
1394 Immediate(RawObject::SizeTag::encode(context_size)));
1395
1396 // Set number of variables field to 1 (for captured receiver).
1397 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1));
1398
1399 // Set isolate field to isolate of current context.
1400 __ movq(R10, FieldAddress(CTX, Context::isolate_offset()));
1401 __ movq(Address(RBX, Context::isolate_offset()), R10);
1402
1403 // Set the parent field to null.
1404 __ movq(Address(RBX, Context::parent_offset()), raw_null);
1405
1406 // Initialize the context variable to the receiver.
1407 __ movq(R10, Address(RSP, kReceiverOffset));
1408 __ movq(Address(RBX, Context::variable_offset(0)), R10);
1409
1410 // Set the newly allocated context in the newly allocated closure.
1411 __ addq(RBX, Immediate(kHeapObjectTag));
1412 __ movq(Address(RAX, Closure::context_offset()), RBX);
1413 } else {
1414 __ movq(Address(RAX, Closure::context_offset()), CTX);
1415 }
1416
1417 // Set the type arguments field in the newly allocated closure.
1418 if (has_type_arguments) {
1419 ASSERT(!is_implicit_static_closure);
1420 // Use the passed-in type arguments.
1421 __ movq(R10, Address(RSP, kTypeArgumentsOffset));
1422 __ movq(Address(RAX, Closure::type_arguments_offset()), R10);
1423 } else {
1424 // Set to null.
1425 __ movq(Address(RAX, Closure::type_arguments_offset()), raw_null);
1426 }
1427
1428 __ movq(Address(RAX, Closure::smrck_offset()), raw_null);
1429
1430 // Done allocating and initializing the instance.
1431 // RAX: new object.
1432 __ addq(RAX, Immediate(kHeapObjectTag));
1433 __ ret();
1434
1435 __ Bind(&slow_case);
1103 } 1436 }
1104 if (has_type_arguments) { 1437 if (has_type_arguments) {
1105 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); 1438 __ movq(RCX, Address(RSP, kTypeArgumentsOffset));
1106 } 1439 }
1107 if (is_implicit_instance_closure) { 1440 if (is_implicit_instance_closure) {
1108 __ movq(RAX, Address(RSP, kReceiverOffset)); 1441 __ movq(RAX, Address(RSP, kReceiverOffset));
1109 } 1442 }
1110 // Create the stub frame. 1443 // Create the stub frame.
1111 __ EnterFrame(0); 1444 __ EnterFrame(0);
1112 __ pushq(raw_null); // Setup space on stack for the return value. 1445 __ pushq(raw_null); // Setup space on stack for the return value.
(...skipping 21 matching lines...) Expand all
1134 } 1467 }
1135 __ popq(RAX); // Pop the function object. 1468 __ popq(RAX); // Pop the function object.
1136 __ popq(RAX); // Pop the result. 1469 __ popq(RAX); // Pop the result.
1137 // RAX: New closure object. 1470 // RAX: New closure object.
1138 // Restore the calling frame. 1471 // Restore the calling frame.
1139 __ LeaveFrame(); 1472 __ LeaveFrame();
1140 __ ret(); 1473 __ ret();
1141 } 1474 }
1142 1475
1143 1476
1477 // Called for invoking noSuchMethod function from the entry code of a dart
1478 // function after an error in passed named arguments is detected.
1479 // Input parameters:
1480 // RBP : points to previous frame pointer.
1481 // RBP + 8 : points to return address.
1482 // RBP + 16 : address of last argument (arg n-1).
1483 // RBP + 16 + 8*(n-1) : address of first argument (arg 0).
1484 // RBX : ic-data array.
1485 // R10 : arguments descriptor array.
1144 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1486 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1145 __ Unimplemented("CallNoSuchMethodFunction stub"); 1487 // The target function was not found, so invoke method
1488 // "void noSuchMethod(function_name, Array arguments)".
1489 // TODO(regis): For now, we simply pass the actual arguments, both positional
1490 // and named, as the argument array. This is not correct if out-of-order
1491 // named arguments were passed.
1492 // The signature of the "noSuchMethod" method has to change from
1493 // noSuchMethod(String name, Array arguments) to something like
1494 // noSuchMethod(InvocationMirror call).
1495 // Also, the class NoSuchMethodException has to be modified accordingly.
1496 // Total number of args is the first Smi in args descriptor array (R10).
1497 const Immediate raw_null =
1498 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1499 __ movq(R13, FieldAddress(R10, Array::data_offset()));
1500 __ SmiUntag(R13);
1501 __ movq(RAX, Address(RBP, R13, TIMES_8, kWordSize)); // Get receiver.
1502
1503 __ EnterFrame(0);
1504 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod.
1505 __ pushq(RAX); // Receiver.
1506 __ pushq(RBX); // IC data array.
1507 __ pushq(R10); // Arguments descriptor array.
1508 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver.
1509 // See stack layout below explaining "wordSize * 8" offset.
1510 PushArgumentsArray(assembler, (kWordSize * 8));
1511
1512 // Stack:
1513 // TOS + 0: Argument array.
1514 // TOS + 1: Arguments descriptor array.
1515 // TOS + 2: Ic-data array.
1516 // TOS + 3: Receiver.
1517 // TOS + 4: Place for result from noSuchMethod.
1518 // TOS + 5: Saved RBP of previous frame. <== RBP
1519 // TOS + 6: Dart callee (or stub) code return address
1520 // TOS + 7: Saved RBP of dart caller frame.
1521 // TOS + 8: Dart caller code return address
1522 // TOS + 9: Last argument of caller.
1523 // ....
1524 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry);
1525 // Remove arguments.
1526 __ popq(RAX);
1527 __ popq(RAX);
1528 __ popq(RAX);
1529 __ popq(RAX);
1530 __ popq(RAX); // Get result into RAX.
1531
1532 // Remove the stub frame as we are about to return.
1533 __ LeaveFrame();
1534 __ ret();
1146 } 1535 }
1147 1536
1148 1537
1538
1149 // Generate inline cache check for 'num_args'. 1539 // Generate inline cache check for 'num_args'.
1150 // RBX: Inline cache data array. 1540 // RBX: Inline cache data array.
1151 // R10: Arguments array. 1541 // R10: Arguments array.
1152 // TOS(0): return address 1542 // TOS(0): return address
1153 // Control flow: 1543 // Control flow:
1154 // - If receiver is null -> jump to IC miss. 1544 // - If receiver is null -> jump to IC miss.
1155 // - If receiver is Smi -> load Smi class. 1545 // - If receiver is Smi -> load Smi class.
1156 // - If receiver is not-Smi -> load receiver's class. 1546 // - If receiver is not-Smi -> load receiver's class.
1157 // - Check if 'num_args' (including receiver) match any IC data group. 1547 // - Check if 'num_args' (including receiver) match any IC data group.
1158 // - Match found -> jump to target. 1548 // - Match found -> jump to target.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1690 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1301 return GenerateNArgsCheckInlineCacheStub(assembler, 1); 1691 return GenerateNArgsCheckInlineCacheStub(assembler, 1);
1302 } 1692 }
1303 1693
1304 1694
1305 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1695 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1306 return GenerateNArgsCheckInlineCacheStub(assembler, 2); 1696 return GenerateNArgsCheckInlineCacheStub(assembler, 2);
1307 } 1697 }
1308 1698
1309 1699
1700 // RBX: Function object.
1701 // R10: Arguments array.
1702 // TOS(0): return address (Dart code).
1310 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1703 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1311 __ Unimplemented("BreakpointStatic stub"); 1704 __ Untested("BreakpointStatic stub");
1705 __ EnterFrame(0);
1706 __ pushq(R10);
1707 __ pushq(RBX);
1708 __ CallRuntimeFromStub(kBreakpointStaticHandlerRuntimeEntry);
1709 __ popq(RBX);
1710 __ popq(R10);
1711 __ LeaveFrame();
1712
1713 // Now call the static function. The breakpoint handler function
1714 // ensures that the call target is compiled.
1715 __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
1716 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
1717 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1718 __ jmp(RBX);
1312 } 1719 }
1313 1720
1314 1721
1722 // RBX: Inline cache data array.
1723 // R10: Arguments array.
1724 // TOS(0): return address (Dart code).
1315 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { 1725 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
1316 __ Unimplemented("BreakpointDynamic stub"); 1726 __ Untested("BreakpointDynamic stub");
1727 __ EnterFrame(0);
1728 __ pushq(RBX);
1729 __ pushq(R10);
1730 __ CallRuntimeFromStub(kBreakpointDynamicHandlerRuntimeEntry);
1731 __ popq(R10);
1732 __ popq(RBX);
1733 __ LeaveFrame();
1734 // Now call the dynamic function.
1735 __ jmp(&StubCode::OneArgCheckInlineCacheLabel());
1317 } 1736 }
1318 1737
1319 } // namespace dart 1738 } // namespace dart
1320 1739
1321 #endif // defined TARGET_ARCH_X64 1740 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/raw_object.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698