OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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" |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 // TOS + 2: Last argument of caller. | 379 // TOS + 2: Last argument of caller. |
380 // .... | 380 // .... |
381 // Total number of args is the first Smi in args descriptor array (R10). | 381 // Total number of args is the first Smi in args descriptor array (R10). |
382 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 382 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
383 __ movq(RAX, Address(RSP, RAX, TIMES_4, kWordSize)); // Get receiver. | 383 __ movq(RAX, Address(RSP, RAX, TIMES_4, kWordSize)); // Get receiver. |
384 __ pushq(R10); // Preserve arguments descriptor array. | 384 __ pushq(R10); // Preserve arguments descriptor array. |
385 __ pushq(RAX); // Preserve receiver. | 385 __ pushq(RAX); // Preserve receiver. |
386 __ pushq(RBX); // Preserve ic-data array. | 386 __ pushq(RBX); // Preserve ic-data array. |
387 // First resolve the function to get the function object. | 387 // First resolve the function to get the function object. |
388 | 388 |
389 // Setup space for return value on stack by pushing smi 0. | 389 __ pushq(raw_null); // Setup space on stack for return value. |
390 __ pushq(Immediate(0)); | |
391 __ pushq(RAX); // Push receiver. | 390 __ pushq(RAX); // Push receiver. |
392 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); | 391 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); |
393 __ popq(RAX); // Remove receiver pushed earlier. | 392 __ popq(RAX); // Remove receiver pushed earlier. |
394 __ popq(RBX); // Pop returned code object into RBX. | 393 __ popq(RBX); // Pop returned code object into RBX. |
395 // Pop preserved values | 394 // Pop preserved values |
396 __ popq(R10); // Restore ic-data array. | 395 __ popq(R10); // Restore ic-data array. |
397 __ popq(RAX); // Restore receiver. | 396 __ popq(RAX); // Restore receiver. |
398 __ popq(R13); // Restore arguments descriptor array. | 397 __ popq(R13); // Restore arguments descriptor array. |
399 | 398 |
400 __ cmpq(RBX, raw_null); | 399 __ cmpq(RBX, raw_null); |
(...skipping 14 matching lines...) Expand all Loading... |
415 // RBX: raw_null. | 414 // RBX: raw_null. |
416 // R13: arguments descriptor array. | 415 // R13: arguments descriptor array. |
417 // The target function was not found. | 416 // The target function was not found. |
418 // First check to see if this is a getter function and we are | 417 // First check to see if this is a getter function and we are |
419 // trying to create a closure of an instance function. | 418 // trying to create a closure of an instance function. |
420 // Push values that need to be preserved across runtime call. | 419 // Push values that need to be preserved across runtime call. |
421 __ pushq(RAX); // Preserve receiver. | 420 __ pushq(RAX); // Preserve receiver. |
422 __ pushq(R10); // Preserve ic-data array. | 421 __ pushq(R10); // Preserve ic-data array. |
423 __ pushq(R13); // Preserve arguments descriptor array. | 422 __ pushq(R13); // Preserve arguments descriptor array. |
424 | 423 |
425 __ pushq(Immediate(0)); | 424 __ pushq(raw_null); // Setup space on stack for return value. |
426 __ pushq(RAX); // Push receiver. | 425 __ pushq(RAX); // Push receiver. |
427 __ pushq(R10); // Ic-data array. | 426 __ pushq(R10); // Ic-data array. |
428 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); | 427 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); |
429 __ popq(RAX); | 428 __ popq(RAX); |
430 __ popq(RAX); | 429 __ popq(RAX); |
431 __ popq(RBX); // Get return value into RBX, might be Closure object. | 430 __ popq(RBX); // Get return value into RBX, might be Closure object. |
432 | 431 |
433 // Pop preserved values. | 432 // Pop preserved values. |
434 __ popq(R13); // Restore arguments descriptor array. | 433 __ popq(R13); // Restore arguments descriptor array. |
435 __ popq(R10); // Restore ic-data array. | 434 __ popq(R10); // Restore ic-data array. |
(...skipping 14 matching lines...) Expand all Loading... |
450 // RBX: raw_null. | 449 // RBX: raw_null. |
451 // R13: arguments descriptor array. | 450 // R13: arguments descriptor array. |
452 // This is not the case of an instance so invoke the getter of the | 451 // This is not the case of an instance so invoke the getter of the |
453 // same name and see if we get a closure back which we are then | 452 // same name and see if we get a closure back which we are then |
454 // supposed to invoke. | 453 // supposed to invoke. |
455 // Push values that need to be preserved across runtime call. | 454 // Push values that need to be preserved across runtime call. |
456 __ pushq(RAX); // Preserve receiver. | 455 __ pushq(RAX); // Preserve receiver. |
457 __ pushq(R10); // Preserve ic-data array. | 456 __ pushq(R10); // Preserve ic-data array. |
458 __ pushq(R13); // Preserve arguments descriptor array. | 457 __ pushq(R13); // Preserve arguments descriptor array. |
459 | 458 |
460 __ pushq(Immediate(0)); | 459 __ pushq(raw_null); // Setup space on stack for return value. |
461 __ pushq(RAX); // Push receiver. | 460 __ pushq(RAX); // Push receiver. |
462 __ pushq(R10); // Ic-data array. | 461 __ pushq(R10); // Ic-data array. |
463 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); | 462 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); |
464 __ popq(R10); // Pop argument. | 463 __ popq(R10); // Pop argument. |
465 __ popq(RAX); // Pop argument. | 464 __ popq(RAX); // Pop argument. |
466 __ popq(RBX); // get return value into RBX, might be Closure object. | 465 __ popq(RBX); // get return value into RBX, might be Closure object. |
467 | 466 |
468 // Pop preserved values. | 467 // Pop preserved values. |
469 __ popq(R13); // Restore arguments descriptor array. | 468 __ popq(R13); // Restore arguments descriptor array. |
470 __ popq(R10); // Restore ic-data array. | 469 __ popq(R10); // Restore ic-data array. |
471 __ popq(RAX); // Restore receiver. | 470 __ popq(RAX); // Restore receiver. |
472 | 471 |
473 __ cmpq(RBX, raw_null); | 472 __ cmpq(RBX, raw_null); |
474 Label function_not_found; | 473 Label function_not_found; |
475 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 474 __ j(EQUAL, &function_not_found); |
476 | 475 |
477 // RBX: Closure object. | 476 // RBX: Closure object. |
478 // R13: Arguments descriptor array. | 477 // R13: Arguments descriptor array. |
479 __ pushq(Immediate(0)); // Result from invoking Closure. | 478 __ pushq(raw_null); // Setup space on stack for result from invoking Closure. |
480 __ pushq(RBX); // Closure object. | 479 __ pushq(RBX); // Closure object. |
481 __ pushq(R13); // Arguments descriptor. | 480 __ pushq(R13); // Arguments descriptor. |
482 __ movq(R13, FieldAddress(R13, Array::data_offset())); | 481 __ movq(R13, FieldAddress(R13, Array::data_offset())); |
483 __ SmiUntag(R13); | 482 __ SmiUntag(R13); |
484 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. | 483 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
485 PushArgumentsArray(assembler, (kWordSize * 5)); | 484 PushArgumentsArray(assembler, (kWordSize * 5)); |
486 // Stack layout explaining "(kWordSize * 5)" offset. | 485 // Stack layout explaining "(kWordSize * 5)" offset. |
487 // TOS + 0: Argument array. | 486 // TOS + 0: Argument array. |
488 // TOS + 1: Arguments descriptor array. | 487 // TOS + 1: Arguments descriptor array. |
489 // TOS + 2: Closure object. | 488 // TOS + 2: Closure object. |
(...skipping 15 matching lines...) Expand all Loading... |
505 __ ret(); | 504 __ ret(); |
506 | 505 |
507 __ Bind(&function_not_found); | 506 __ Bind(&function_not_found); |
508 // The target function was not found, so invoke method | 507 // The target function was not found, so invoke method |
509 // "void noSuchMethod(function_name, args_array)". | 508 // "void noSuchMethod(function_name, args_array)". |
510 // RAX: receiver. | 509 // RAX: receiver. |
511 // R10: ic-data array. | 510 // R10: ic-data array. |
512 // RBX: raw_null. | 511 // RBX: raw_null. |
513 // R13: argument descriptor array. | 512 // R13: argument descriptor array. |
514 | 513 |
515 // Setup space for return value on stack by pushing smi 0. | 514 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
516 __ pushq(Immediate(0)); // Result from noSuchMethod. | |
517 __ pushq(RAX); // Receiver. | 515 __ pushq(RAX); // Receiver. |
518 __ pushq(R10); // IC-data array. | 516 __ pushq(R10); // IC-data array. |
519 __ pushq(R13); // Argument descriptor array. | 517 __ pushq(R13); // Argument descriptor array. |
520 __ movq(R13, FieldAddress(R13, Array::data_offset())); | 518 __ movq(R13, FieldAddress(R13, Array::data_offset())); |
521 __ SmiUntag(R13); | 519 __ SmiUntag(R13); |
522 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. | 520 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
523 // See stack layout below explaining "wordSize * 6" offset. | 521 // See stack layout below explaining "wordSize * 6" offset. |
524 PushArgumentsArray(assembler, (kWordSize * 6)); | 522 PushArgumentsArray(assembler, (kWordSize * 6)); |
525 | 523 |
526 // Stack: | 524 // Stack: |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
646 | 644 |
647 // Done allocating and initializing the array. | 645 // Done allocating and initializing the array. |
648 // RAX: new object. | 646 // RAX: new object. |
649 __ ret(); | 647 __ ret(); |
650 } | 648 } |
651 | 649 |
652 // Unable to allocate the array using the fast inline code, just call | 650 // Unable to allocate the array using the fast inline code, just call |
653 // into the runtime. | 651 // into the runtime. |
654 __ Bind(&slow_case); | 652 __ Bind(&slow_case); |
655 __ EnterFrame(0); | 653 __ EnterFrame(0); |
656 __ pushq(raw_null); // Push Null object for return value. | 654 __ pushq(raw_null); // Setup space on stack for return value. |
657 __ pushq(R10); // Array length as Smi. | 655 __ pushq(R10); // Array length as Smi. |
658 __ pushq(RBX); // Element type. | 656 __ pushq(RBX); // Element type. |
659 __ pushq(raw_null); // Null instantiator. | 657 __ pushq(raw_null); // Null instantiator. |
660 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); | 658 __ CallRuntimeFromStub(kAllocateArrayRuntimeEntry); |
661 __ popq(RAX); // Pop instantiator. | 659 __ popq(RAX); // Pop instantiator. |
662 __ popq(RAX); // Pop element type argument. | 660 __ popq(RAX); // Pop element type argument. |
663 __ popq(R10); // Pop array length argument. | 661 __ popq(R10); // Pop array length argument. |
664 __ popq(RAX); // Pop return value from return slot. | 662 __ popq(RAX); // Pop return value from return slot. |
665 __ LeaveFrame(); | 663 __ LeaveFrame(); |
666 __ ret(); | 664 __ ret(); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 // RBX and RDX are destroyed. | 794 // RBX and RDX are destroyed. |
797 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 795 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
798 const Immediate raw_null = | 796 const Immediate raw_null = |
799 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 797 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
800 if (false) { | 798 if (false) { |
801 // TODO(regis): Implement fast inline allocation of contexts. | 799 // TODO(regis): Implement fast inline allocation of contexts. |
802 __ Unimplemented("AllocateContext stub - inline allocation"); | 800 __ Unimplemented("AllocateContext stub - inline allocation"); |
803 } | 801 } |
804 // Create the stub frame. | 802 // Create the stub frame. |
805 __ EnterFrame(0); | 803 __ EnterFrame(0); |
806 __ pushq(raw_null); // Make space for the return value. | 804 __ pushq(raw_null); // Setup space on stack for the return value. |
807 __ SmiTag(RDX); | 805 __ SmiTag(RDX); |
808 __ pushq(RDX); // Push number of context variables. | 806 __ pushq(RDX); // Push number of context variables. |
809 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. | 807 __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context. |
810 __ popq(RAX); // Pop number of context variables argument. | 808 __ popq(RAX); // Pop number of context variables argument. |
811 __ popq(RAX); // Pop the new context object. | 809 __ popq(RAX); // Pop the new context object. |
812 // RAX: new object | 810 // RAX: new object |
813 // Restore the frame pointer. | 811 // Restore the frame pointer. |
814 __ LeaveFrame(); | 812 __ LeaveFrame(); |
815 __ ret(); | 813 __ ret(); |
816 } | 814 } |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 __ ret(); | 979 __ ret(); |
982 | 980 |
983 __ Bind(&slow_case); | 981 __ Bind(&slow_case); |
984 } | 982 } |
985 if (is_cls_parameterized) { | 983 if (is_cls_parameterized) { |
986 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); | 984 __ movq(RAX, Address(RSP, kObjectTypeArgumentsOffset)); |
987 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); | 985 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
988 } | 986 } |
989 // Create a stub frame. | 987 // Create a stub frame. |
990 __ EnterFrame(0); | 988 __ EnterFrame(0); |
991 const Object& new_object = Object::ZoneHandle(); | 989 __ pushq(raw_null); // Setup space on stack for return value. |
992 __ PushObject(new_object); // Push Null object for return value. | |
993 __ PushObject(cls); // Push class of object to be allocated. | 990 __ PushObject(cls); // Push class of object to be allocated. |
994 if (is_cls_parameterized) { | 991 if (is_cls_parameterized) { |
995 __ pushq(RAX); // Push type arguments of object to be allocated. | 992 __ pushq(RAX); // Push type arguments of object to be allocated. |
996 __ pushq(RDX); // Push type arguments of instantiator. | 993 __ pushq(RDX); // Push type arguments of instantiator. |
997 } else { | 994 } else { |
998 __ pushq(raw_null); // Push null type arguments. | 995 __ pushq(raw_null); // Push null type arguments. |
999 __ pushq(raw_null); // Push null instantiator. | 996 __ pushq(raw_null); // Push null instantiator. |
1000 } | 997 } |
1001 __ CallRuntimeFromStub(kAllocateObjectRuntimeEntry); // Allocate object. | 998 __ CallRuntimeFromStub(kAllocateObjectRuntimeEntry); // Allocate object. |
1002 __ popq(RAX); // Pop argument (instantiator). | 999 __ popq(RAX); // Pop argument (instantiator). |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 __ Unimplemented("AllocateClosure stub - inline allocation"); | 1033 __ Unimplemented("AllocateClosure stub - inline allocation"); |
1037 } | 1034 } |
1038 if (has_type_arguments) { | 1035 if (has_type_arguments) { |
1039 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); | 1036 __ movq(RCX, Address(RSP, kTypeArgumentsOffset)); |
1040 } | 1037 } |
1041 if (is_implicit_instance_closure) { | 1038 if (is_implicit_instance_closure) { |
1042 __ movq(RAX, Address(RSP, kReceiverOffset)); | 1039 __ movq(RAX, Address(RSP, kReceiverOffset)); |
1043 } | 1040 } |
1044 // Create the stub frame. | 1041 // Create the stub frame. |
1045 __ EnterFrame(0); | 1042 __ EnterFrame(0); |
1046 __ pushq(raw_null); // Make space for the return value. | 1043 __ pushq(raw_null); // Setup space on stack for the return value. |
1047 __ PushObject(func); | 1044 __ PushObject(func); |
1048 if (is_implicit_static_closure) { | 1045 if (is_implicit_static_closure) { |
1049 __ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); | 1046 __ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); |
1050 } else { | 1047 } else { |
1051 if (is_implicit_instance_closure) { | 1048 if (is_implicit_instance_closure) { |
1052 __ pushq(RAX); // Receiver. | 1049 __ pushq(RAX); // Receiver. |
1053 } | 1050 } |
1054 if (has_type_arguments) { | 1051 if (has_type_arguments) { |
1055 __ pushq(RCX); // Push type arguments of closure to be allocated. | 1052 __ pushq(RCX); // Push type arguments of closure to be allocated. |
1056 } else { | 1053 } else { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 __ call(&get_class); | 1141 __ call(&get_class); |
1145 __ cmpq(RAX, R13); // Match? | 1142 __ cmpq(RAX, R13); // Match? |
1146 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1143 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
1147 // Check second. | 1144 // Check second. |
1148 __ movq(R13, Address(R12, kWordSize)); // Get class from IC data to check. | 1145 __ movq(R13, Address(R12, kWordSize)); // Get class from IC data to check. |
1149 // Get next argument. | 1146 // Get next argument. |
1150 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1147 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
1151 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi. | 1148 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi. |
1152 __ call(&get_class); | 1149 __ call(&get_class); |
1153 __ cmpq(RAX, R13); // Match? | 1150 __ cmpq(RAX, R13); // Match? |
1154 __ j(EQUAL, &found, Assembler::kNearJump); | 1151 __ j(EQUAL, &found); |
1155 __ Bind(&no_match); | 1152 __ Bind(&no_match); |
1156 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. | 1153 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. |
1157 __ cmpq(R13, raw_null); // Done? | 1154 __ cmpq(R13, raw_null); // Done? |
1158 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1155 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
1159 } | 1156 } |
1160 | 1157 |
1161 __ Bind(&ic_miss); | 1158 __ Bind(&ic_miss); |
1162 // Get receiver, again. | 1159 // Get receiver, again. |
1163 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1160 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
1164 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1161 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
1165 __ EnterFrame(0); | 1162 __ EnterFrame(0); |
1166 // Setup space for return value on stack by pushing smi 0. | |
1167 __ pushq(R10); // Preserve arguments array. | 1163 __ pushq(R10); // Preserve arguments array. |
1168 __ pushq(RBX); // Preserve IC data array | 1164 __ pushq(RBX); // Preserve IC data array |
1169 __ pushq(Immediate(0)); // Space for result (target code object). | 1165 __ pushq(raw_null); // Setup space on stack for result (target code object). |
1170 __ movq(R10, FieldAddress(R10, Array::data_offset())); | 1166 __ movq(R10, FieldAddress(R10, Array::data_offset())); |
1171 // Push call arguments. | 1167 // Push call arguments. |
1172 for (intptr_t i = 0; i < num_args; i++) { | 1168 for (intptr_t i = 0; i < num_args; i++) { |
1173 __ movq(R10, Address(RAX, -kWordSize * i)); | 1169 __ movq(R10, Address(RAX, -kWordSize * i)); |
1174 __ pushq(R10); | 1170 __ pushq(R10); |
1175 } | 1171 } |
1176 if (num_args == 1) { | 1172 if (num_args == 1) { |
1177 __ CallRuntimeFromStub(kInlineCacheMissHandlerOneArgRuntimeEntry); | 1173 __ CallRuntimeFromStub(kInlineCacheMissHandlerOneArgRuntimeEntry); |
1178 } else if (num_args == 2) { | 1174 } else if (num_args == 2) { |
1179 __ CallRuntimeFromStub(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | 1175 __ CallRuntimeFromStub(kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 } | 1243 } |
1248 | 1244 |
1249 | 1245 |
1250 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1246 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1251 __ Unimplemented("BreakpointDynamic stub"); | 1247 __ Unimplemented("BreakpointDynamic stub"); |
1252 } | 1248 } |
1253 | 1249 |
1254 } // namespace dart | 1250 } // namespace dart |
1255 | 1251 |
1256 #endif // defined TARGET_ARCH_X64 | 1252 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |