| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. | 76 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. |
| 77 __ call(RBX); | 77 __ call(RBX); |
| 78 | 78 |
| 79 // Reset exit frame information in Isolate structure. | 79 // Reset exit frame information in Isolate structure. |
| 80 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 80 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 81 | 81 |
| 82 // Load Context pointer from Isolate structure into RBX. | 82 // Load Context pointer from Isolate structure into RBX. |
| 83 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); | 83 __ movq(RBX, Address(CTX, Isolate::top_context_offset())); |
| 84 | 84 |
| 85 // Reset Context pointer in Isolate structure. | 85 // Reset Context pointer in Isolate structure. |
| 86 __ LoadObject(R12, Object::Handle(), PP); | 86 __ LoadObject(R12, Object::null_object(), PP); |
| 87 __ movq(Address(CTX, Isolate::top_context_offset()), R12); | 87 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| 88 | 88 |
| 89 // Cache Context pointer into CTX while executing Dart code. | 89 // Cache Context pointer into CTX while executing Dart code. |
| 90 __ movq(CTX, RBX); | 90 __ movq(CTX, RBX); |
| 91 | 91 |
| 92 __ LeaveFrame(); | 92 __ LeaveFrame(); |
| 93 __ ret(); | 93 __ ret(); |
| 94 } | 94 } |
| 95 | 95 |
| 96 | 96 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 __ movq(RSI, RBX); // Pass pointer to function entrypoint. | 164 __ movq(RSI, RBX); // Pass pointer to function entrypoint. |
| 165 __ call(&NativeEntry::NativeCallWrapperLabel()); | 165 __ call(&NativeEntry::NativeCallWrapperLabel()); |
| 166 | 166 |
| 167 // Reset exit frame information in Isolate structure. | 167 // Reset exit frame information in Isolate structure. |
| 168 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 168 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 169 | 169 |
| 170 // Load Context pointer from Isolate structure into R8. | 170 // Load Context pointer from Isolate structure into R8. |
| 171 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 171 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| 172 | 172 |
| 173 // Reset Context pointer in Isolate structure. | 173 // Reset Context pointer in Isolate structure. |
| 174 __ LoadObject(R12, Object::Handle(), PP); | 174 __ LoadObject(R12, Object::null_object(), PP); |
| 175 __ movq(Address(CTX, Isolate::top_context_offset()), R12); | 175 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| 176 | 176 |
| 177 // Cache Context pointer into CTX while executing Dart code. | 177 // Cache Context pointer into CTX while executing Dart code. |
| 178 __ movq(CTX, R8); | 178 __ movq(CTX, R8); |
| 179 | 179 |
| 180 __ LeaveFrame(); | 180 __ LeaveFrame(); |
| 181 __ ret(); | 181 __ ret(); |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. | 231 __ movq(RDI, RSP); // Pass the pointer to the NativeArguments. |
| 232 __ call(RBX); | 232 __ call(RBX); |
| 233 | 233 |
| 234 // Reset exit frame information in Isolate structure. | 234 // Reset exit frame information in Isolate structure. |
| 235 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 235 __ movq(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 236 | 236 |
| 237 // Load Context pointer from Isolate structure into R8. | 237 // Load Context pointer from Isolate structure into R8. |
| 238 __ movq(R8, Address(CTX, Isolate::top_context_offset())); | 238 __ movq(R8, Address(CTX, Isolate::top_context_offset())); |
| 239 | 239 |
| 240 // Reset Context pointer in Isolate structure. | 240 // Reset Context pointer in Isolate structure. |
| 241 __ LoadObject(R12, Object::Handle(), PP); | 241 __ LoadObject(R12, Object::null_object(), PP); |
| 242 __ movq(Address(CTX, Isolate::top_context_offset()), R12); | 242 __ movq(Address(CTX, Isolate::top_context_offset()), R12); |
| 243 | 243 |
| 244 // Cache Context pointer into CTX while executing Dart code. | 244 // Cache Context pointer into CTX while executing Dart code. |
| 245 __ movq(CTX, R8); | 245 __ movq(CTX, R8); |
| 246 | 246 |
| 247 __ LeaveFrame(); | 247 __ LeaveFrame(); |
| 248 __ ret(); | 248 __ ret(); |
| 249 } | 249 } |
| 250 | 250 |
| 251 | 251 |
| 252 // Input parameters: | 252 // Input parameters: |
| 253 // R10: arguments descriptor array. | 253 // R10: arguments descriptor array. |
| 254 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 254 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
| 255 __ EnterStubFrame(); | 255 __ EnterStubFrame(); |
| 256 __ pushq(R10); // Preserve arguments descriptor array. | 256 __ pushq(R10); // Preserve arguments descriptor array. |
| 257 // Setup space on stack for return value. | 257 // Setup space on stack for return value. |
| 258 __ PushObject(Object::Handle()); | 258 __ PushObject(Object::null_object()); |
| 259 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 259 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
| 260 __ popq(RAX); // Get Code object result. | 260 __ popq(RAX); // Get Code object result. |
| 261 __ popq(R10); // Restore arguments descriptor array. | 261 __ popq(R10); // Restore arguments descriptor array. |
| 262 // Remove the stub frame as we are about to jump to the dart function. | 262 // Remove the stub frame as we are about to jump to the dart function. |
| 263 __ LeaveFrame(); | 263 __ LeaveFrame(); |
| 264 | 264 |
| 265 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); | 265 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); |
| 266 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 266 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 267 __ jmp(RBX); | 267 __ jmp(RBX); |
| 268 } | 268 } |
| 269 | 269 |
| 270 | 270 |
| 271 // Called from a static call only when an invalid code has been entered | 271 // Called from a static call only when an invalid code has been entered |
| 272 // (invalid because its function was optimized or deoptimized). | 272 // (invalid because its function was optimized or deoptimized). |
| 273 // R10: arguments descriptor array. | 273 // R10: arguments descriptor array. |
| 274 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 274 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
| 275 __ EnterStubFrame(); | 275 __ EnterStubFrame(); |
| 276 __ pushq(R10); // Preserve arguments descriptor array. | 276 __ pushq(R10); // Preserve arguments descriptor array. |
| 277 // Setup space on stack for return value. | 277 // Setup space on stack for return value. |
| 278 __ PushObject(Object::Handle()); | 278 __ PushObject(Object::null_object()); |
| 279 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 279 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
| 280 __ popq(RAX); // Get Code object. | 280 __ popq(RAX); // Get Code object. |
| 281 __ popq(R10); // Restore arguments descriptor array. | 281 __ popq(R10); // Restore arguments descriptor array. |
| 282 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 282 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 283 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 283 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 284 __ LeaveFrame(); | 284 __ LeaveFrame(); |
| 285 __ jmp(RAX); | 285 __ jmp(RAX); |
| 286 __ int3(); | 286 __ int3(); |
| 287 } | 287 } |
| 288 | 288 |
| 289 | 289 |
| 290 // Input parameters: | 290 // Input parameters: |
| 291 // R10: smi-tagged argument count, may be zero. | 291 // R10: smi-tagged argument count, may be zero. |
| 292 // RBP[kParamEndSlotFromFp + 1]: last argument. | 292 // RBP[kParamEndSlotFromFp + 1]: last argument. |
| 293 static void PushArgumentsArray(Assembler* assembler) { | 293 static void PushArgumentsArray(Assembler* assembler) { |
| 294 __ LoadObject(R12, Object::Handle(), PP); | 294 __ LoadObject(R12, Object::null_object(), PP); |
| 295 // Allocate array to store arguments of caller. | 295 // Allocate array to store arguments of caller. |
| 296 __ movq(RBX, R12); // Null element type for raw Array. | 296 __ movq(RBX, R12); // Null element type for raw Array. |
| 297 __ call(&StubCode::AllocateArrayLabel()); | 297 __ call(&StubCode::AllocateArrayLabel()); |
| 298 __ SmiUntag(R10); | 298 __ SmiUntag(R10); |
| 299 // RAX: newly allocated array. | 299 // RAX: newly allocated array. |
| 300 // R10: length of the array (was preserved by the stub). | 300 // R10: length of the array (was preserved by the stub). |
| 301 __ pushq(RAX); // Array is in RAX and on top of stack. | 301 __ pushq(RAX); // Array is in RAX and on top of stack. |
| 302 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); | 302 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); |
| 303 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 303 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
| 304 // R12: address of first argument on stack. | 304 // R12: address of first argument on stack. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 317 | 317 |
| 318 | 318 |
| 319 // Input parameters: | 319 // Input parameters: |
| 320 // RBX: ic-data. | 320 // RBX: ic-data. |
| 321 // R10: arguments descriptor array. | 321 // R10: arguments descriptor array. |
| 322 // Note: The receiver object is the first argument to the function being | 322 // Note: The receiver object is the first argument to the function being |
| 323 // called, the stub accesses the receiver from this location directly | 323 // called, the stub accesses the receiver from this location directly |
| 324 // when trying to resolve the call. | 324 // when trying to resolve the call. |
| 325 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { | 325 void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { |
| 326 __ EnterStubFrameWithPP(); | 326 __ EnterStubFrameWithPP(); |
| 327 __ PushObject(Object::Handle()); // Space for the return value. | 327 __ PushObject(Object::null_object()); // Space for the return value. |
| 328 | 328 |
| 329 // Push the receiver as an argument. Load the smi-tagged argument | 329 // Push the receiver as an argument. Load the smi-tagged argument |
| 330 // count into R13 to index the receiver in the stack. There are | 330 // count into R13 to index the receiver in the stack. There are |
| 331 // four words (null, stub's pc marker, saved pp, saved fp) above the return | 331 // four words (null, stub's pc marker, saved pp, saved fp) above the return |
| 332 // address. | 332 // address. |
| 333 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 333 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 334 __ pushq(Address(RSP, R13, TIMES_4, (4 * kWordSize))); | 334 __ pushq(Address(RSP, R13, TIMES_4, (4 * kWordSize))); |
| 335 | 335 |
| 336 __ pushq(RBX); // Pass IC data object. | 336 __ pushq(RBX); // Pass IC data object. |
| 337 __ pushq(R10); // Pass arguments descriptor array. | 337 __ pushq(R10); // Pass arguments descriptor array. |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 497 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 498 // Three words (saved pp, saved fp, stub's pc marker) | 498 // Three words (saved pp, saved fp, stub's pc marker) |
| 499 // in the stack above the return address. | 499 // in the stack above the return address. |
| 500 __ movq(RAX, Address(RSP, RAX, TIMES_4, | 500 __ movq(RAX, Address(RSP, RAX, TIMES_4, |
| 501 kSavedAboveReturnAddress * kWordSize)); | 501 kSavedAboveReturnAddress * kWordSize)); |
| 502 // Preserve IC data and arguments descriptor. | 502 // Preserve IC data and arguments descriptor. |
| 503 __ pushq(RBX); | 503 __ pushq(RBX); |
| 504 __ pushq(R10); | 504 __ pushq(R10); |
| 505 | 505 |
| 506 // Space for the result of the runtime call. | 506 // Space for the result of the runtime call. |
| 507 __ PushObject(Object::Handle()); | 507 __ PushObject(Object::null_object()); |
| 508 __ pushq(RAX); // Receiver. | 508 __ pushq(RAX); // Receiver. |
| 509 __ pushq(RBX); // IC data. | 509 __ pushq(RBX); // IC data. |
| 510 __ pushq(R10); // Arguments descriptor. | 510 __ pushq(R10); // Arguments descriptor. |
| 511 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); | 511 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); |
| 512 // Discard arguments. | 512 // Discard arguments. |
| 513 __ popq(RAX); | 513 __ popq(RAX); |
| 514 __ popq(RAX); | 514 __ popq(RAX); |
| 515 __ popq(RAX); | 515 __ popq(RAX); |
| 516 __ popq(RAX); // Return value from the runtime call (instructions). | 516 __ popq(RAX); // Return value from the runtime call (instructions). |
| 517 __ popq(R10); // Restore arguments descriptor. | 517 __ popq(R10); // Restore arguments descriptor. |
| 518 __ popq(RBX); // Restore IC data. | 518 __ popq(RBX); // Restore IC data. |
| 519 __ LeaveFrameWithPP(); | 519 __ LeaveFrameWithPP(); |
| 520 | 520 |
| 521 Label lookup; | 521 Label lookup; |
| 522 __ CompareObject(RAX, Object::Handle()); | 522 __ CompareObject(RAX, Object::null_object()); |
| 523 __ j(EQUAL, &lookup, Assembler::kNearJump); | 523 __ j(EQUAL, &lookup, Assembler::kNearJump); |
| 524 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 524 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 525 __ jmp(RAX); | 525 __ jmp(RAX); |
| 526 | 526 |
| 527 __ Bind(&lookup); | 527 __ Bind(&lookup); |
| 528 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 528 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 529 } | 529 } |
| 530 | 530 |
| 531 | 531 |
| 532 // Called for inline allocation of arrays. | 532 // Called for inline allocation of arrays. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | 618 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); |
| 619 } | 619 } |
| 620 | 620 |
| 621 // Initialize all array elements to raw_null. | 621 // Initialize all array elements to raw_null. |
| 622 // RAX: new object start as a tagged pointer. | 622 // RAX: new object start as a tagged pointer. |
| 623 // R12: new object end address. | 623 // R12: new object end address. |
| 624 // R10: Array length as Smi. | 624 // R10: Array length as Smi. |
| 625 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 625 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
| 626 // RBX: iterator which initially points to the start of the variable | 626 // RBX: iterator which initially points to the start of the variable |
| 627 // data area to be initialized. | 627 // data area to be initialized. |
| 628 __ LoadObject(R13, Object::Handle(), PP); | 628 __ LoadObject(R13, Object::null_object(), PP); |
| 629 Label done; | 629 Label done; |
| 630 Label init_loop; | 630 Label init_loop; |
| 631 __ Bind(&init_loop); | 631 __ Bind(&init_loop); |
| 632 __ cmpq(RBX, R12); | 632 __ cmpq(RBX, R12); |
| 633 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 633 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 634 // TODO(cshapiro): StoreIntoObjectNoBarrier | 634 // TODO(cshapiro): StoreIntoObjectNoBarrier |
| 635 __ movq(Address(RBX, 0), R13); | 635 __ movq(Address(RBX, 0), R13); |
| 636 __ addq(RBX, Immediate(kWordSize)); | 636 __ addq(RBX, Immediate(kWordSize)); |
| 637 __ jmp(&init_loop, Assembler::kNearJump); | 637 __ jmp(&init_loop, Assembler::kNearJump); |
| 638 __ Bind(&done); | 638 __ Bind(&done); |
| 639 | 639 |
| 640 // Done allocating and initializing the array. | 640 // Done allocating and initializing the array. |
| 641 // RAX: new object. | 641 // RAX: new object. |
| 642 // R10: Array length as Smi (preserved for the caller.) | 642 // R10: Array length as Smi (preserved for the caller.) |
| 643 __ ret(); | 643 __ ret(); |
| 644 } | 644 } |
| 645 | 645 |
| 646 // Unable to allocate the array using the fast inline code, just call | 646 // Unable to allocate the array using the fast inline code, just call |
| 647 // into the runtime. | 647 // into the runtime. |
| 648 __ Bind(&slow_case); | 648 __ Bind(&slow_case); |
| 649 // Create a stub frame as we are pushing some objects on the stack before | 649 // Create a stub frame as we are pushing some objects on the stack before |
| 650 // calling into the runtime. | 650 // calling into the runtime. |
| 651 __ EnterStubFrame(); | 651 __ EnterStubFrame(); |
| 652 // Setup space on stack for return value. | 652 // Setup space on stack for return value. |
| 653 __ PushObject(Object::Handle()); | 653 __ PushObject(Object::null_object()); |
| 654 __ pushq(R10); // Array length as Smi. | 654 __ pushq(R10); // Array length as Smi. |
| 655 __ pushq(RBX); // Element type. | 655 __ pushq(RBX); // Element type. |
| 656 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 656 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
| 657 __ popq(RAX); // Pop element type argument. | 657 __ popq(RAX); // Pop element type argument. |
| 658 __ popq(R10); // Pop array length argument. | 658 __ popq(R10); // Pop array length argument. |
| 659 __ popq(RAX); // Pop return value from return slot. | 659 __ popq(RAX); // Pop return value from return slot. |
| 660 __ LeaveFrame(); | 660 __ LeaveFrame(); |
| 661 __ ret(); | 661 __ ret(); |
| 662 } | 662 } |
| 663 | 663 |
| 664 | 664 |
| 665 // Input parameters: | 665 // Input parameters: |
| 666 // R10: Arguments descriptor array. | 666 // R10: Arguments descriptor array. |
| 667 // Note: The closure object is the first argument to the function being | 667 // Note: The closure object is the first argument to the function being |
| 668 // called, the stub accesses the closure from this location directly | 668 // called, the stub accesses the closure from this location directly |
| 669 // when trying to resolve the call. | 669 // when trying to resolve the call. |
| 670 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { | 670 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { |
| 671 // Load num_args. | 671 // Load num_args. |
| 672 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 672 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 673 // Load closure object in R13. | 673 // Load closure object in R13. |
| 674 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. | 674 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX is a Smi. |
| 675 | 675 |
| 676 __ LoadObject(R12, Object::Handle(), PP); | 676 __ LoadObject(R12, Object::null_object(), PP); |
| 677 | 677 |
| 678 // Verify that R13 is a closure by checking its class. | 678 // Verify that R13 is a closure by checking its class. |
| 679 Label not_closure; | 679 Label not_closure; |
| 680 __ cmpq(R13, R12); | 680 __ cmpq(R13, R12); |
| 681 // Not a closure, but null object. | 681 // Not a closure, but null object. |
| 682 __ j(EQUAL, ¬_closure); | 682 __ j(EQUAL, ¬_closure); |
| 683 __ testq(R13, Immediate(kSmiTagMask)); | 683 __ testq(R13, Immediate(kSmiTagMask)); |
| 684 __ j(ZERO, ¬_closure); // Not a closure, but a smi. | 684 __ j(ZERO, ¬_closure); // Not a closure, but a smi. |
| 685 // Verify that the class of the object is a closure class by checking that | 685 // Verify that the class of the object is a closure class by checking that |
| 686 // class.signature_function() is not null. | 686 // class.signature_function() is not null. |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 __ ret(); | 878 __ ret(); |
| 879 } | 879 } |
| 880 | 880 |
| 881 | 881 |
| 882 // Called for inline allocation of contexts. | 882 // Called for inline allocation of contexts. |
| 883 // Input: | 883 // Input: |
| 884 // R10: number of context variables. | 884 // R10: number of context variables. |
| 885 // Output: | 885 // Output: |
| 886 // RAX: new allocated RawContext object. | 886 // RAX: new allocated RawContext object. |
| 887 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 887 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
| 888 __ LoadObject(R12, Object::Handle(), PP); | 888 __ LoadObject(R12, Object::null_object(), PP); |
| 889 if (FLAG_inline_alloc) { | 889 if (FLAG_inline_alloc) { |
| 890 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 890 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 891 Label slow_case; | 891 Label slow_case; |
| 892 Heap* heap = Isolate::Current()->heap(); | 892 Heap* heap = Isolate::Current()->heap(); |
| 893 // First compute the rounded instance size. | 893 // First compute the rounded instance size. |
| 894 // R10: number of context variables. | 894 // R10: number of context variables. |
| 895 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); | 895 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); |
| 896 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 896 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 897 __ andq(R13, Immediate(-kObjectAlignment)); | 897 __ andq(R13, Immediate(-kObjectAlignment)); |
| 898 | 898 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 const bool is_cls_parameterized = cls.HasTypeArguments(); | 1077 const bool is_cls_parameterized = cls.HasTypeArguments(); |
| 1078 ASSERT(!cls.HasTypeArguments() || | 1078 ASSERT(!cls.HasTypeArguments() || |
| 1079 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); | 1079 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); |
| 1080 // kInlineInstanceSize is a constant used as a threshold for determining | 1080 // kInlineInstanceSize is a constant used as a threshold for determining |
| 1081 // when the object initialization should be done as a loop or as | 1081 // when the object initialization should be done as a loop or as |
| 1082 // straight line code. | 1082 // straight line code. |
| 1083 const int kInlineInstanceSize = 12; // In words. | 1083 const int kInlineInstanceSize = 12; // In words. |
| 1084 const intptr_t instance_size = cls.instance_size(); | 1084 const intptr_t instance_size = cls.instance_size(); |
| 1085 ASSERT(instance_size > 0); | 1085 ASSERT(instance_size > 0); |
| 1086 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); | 1086 const intptr_t type_args_size = InstantiatedTypeArguments::InstanceSize(); |
| 1087 __ LoadObject(R12, Object::Handle(), PP); | 1087 __ LoadObject(R12, Object::null_object(), PP); |
| 1088 if (FLAG_inline_alloc && | 1088 if (FLAG_inline_alloc && |
| 1089 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { | 1089 Heap::IsAllocatableInNewSpace(instance_size + type_args_size)) { |
| 1090 Label slow_case; | 1090 Label slow_case; |
| 1091 Heap* heap = Isolate::Current()->heap(); | 1091 Heap* heap = Isolate::Current()->heap(); |
| 1092 __ movq(RAX, Immediate(heap->TopAddress())); | 1092 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1093 __ movq(RAX, Address(RAX, 0)); | 1093 __ movq(RAX, Address(RAX, 0)); |
| 1094 __ leaq(RBX, Address(RAX, instance_size)); | 1094 __ leaq(RBX, Address(RAX, instance_size)); |
| 1095 if (is_cls_parameterized) { | 1095 if (is_cls_parameterized) { |
| 1096 __ movq(RCX, RBX); | 1096 __ movq(RCX, RBX); |
| 1097 // A new InstantiatedTypeArguments object only needs to be allocated if | 1097 // A new InstantiatedTypeArguments object only needs to be allocated if |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1244 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, | 1244 void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| 1245 const Function& func) { | 1245 const Function& func) { |
| 1246 ASSERT(func.IsClosureFunction()); | 1246 ASSERT(func.IsClosureFunction()); |
| 1247 ASSERT(!func.IsImplicitStaticClosureFunction()); | 1247 ASSERT(!func.IsImplicitStaticClosureFunction()); |
| 1248 const bool is_implicit_instance_closure = | 1248 const bool is_implicit_instance_closure = |
| 1249 func.IsImplicitInstanceClosureFunction(); | 1249 func.IsImplicitInstanceClosureFunction(); |
| 1250 const Class& cls = Class::ZoneHandle(func.signature_class()); | 1250 const Class& cls = Class::ZoneHandle(func.signature_class()); |
| 1251 const bool has_type_arguments = cls.HasTypeArguments(); | 1251 const bool has_type_arguments = cls.HasTypeArguments(); |
| 1252 | 1252 |
| 1253 __ EnterStubFrameWithPP(); // Uses pool pointer to refer to function. | 1253 __ EnterStubFrameWithPP(); // Uses pool pointer to refer to function. |
| 1254 __ LoadObject(R12, Object::Handle(), PP); | 1254 __ LoadObject(R12, Object::null_object(), PP); |
| 1255 const intptr_t kTypeArgumentsOffset = 4 * kWordSize; | 1255 const intptr_t kTypeArgumentsOffset = 4 * kWordSize; |
| 1256 const intptr_t kReceiverOffset = 5 * kWordSize; | 1256 const intptr_t kReceiverOffset = 5 * kWordSize; |
| 1257 const intptr_t closure_size = Closure::InstanceSize(); | 1257 const intptr_t closure_size = Closure::InstanceSize(); |
| 1258 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. | 1258 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
| 1259 if (FLAG_inline_alloc && | 1259 if (FLAG_inline_alloc && |
| 1260 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { | 1260 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { |
| 1261 Label slow_case; | 1261 Label slow_case; |
| 1262 Heap* heap = Isolate::Current()->heap(); | 1262 Heap* heap = Isolate::Current()->heap(); |
| 1263 __ movq(RAX, Immediate(heap->TopAddress())); | 1263 __ movq(RAX, Immediate(heap->TopAddress())); |
| 1264 __ movq(RAX, Address(RAX, 0)); | 1264 __ movq(RAX, Address(RAX, 0)); |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 // RSP + 8 : address of last argument. | 1387 // RSP + 8 : address of last argument. |
| 1388 // RBX : ic-data. | 1388 // RBX : ic-data. |
| 1389 // R10 : arguments descriptor array. | 1389 // R10 : arguments descriptor array. |
| 1390 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1390 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1391 __ EnterStubFrame(); | 1391 __ EnterStubFrame(); |
| 1392 | 1392 |
| 1393 // Load the receiver. | 1393 // Load the receiver. |
| 1394 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1394 __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 1395 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); | 1395 __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize)); |
| 1396 | 1396 |
| 1397 __ LoadObject(R12, Object::Handle(), PP); | 1397 __ LoadObject(R12, Object::null_object(), PP); |
| 1398 __ pushq(R12); // Setup space on stack for result from noSuchMethod. | 1398 __ pushq(R12); // Setup space on stack for result from noSuchMethod. |
| 1399 __ pushq(RAX); // Receiver. | 1399 __ pushq(RAX); // Receiver. |
| 1400 __ pushq(RBX); // IC data array. | 1400 __ pushq(RBX); // IC data array. |
| 1401 __ pushq(R10); // Arguments descriptor array. | 1401 __ pushq(R10); // Arguments descriptor array. |
| 1402 | 1402 |
| 1403 __ movq(R10, R13); // Smi-tagged arguments array length. | 1403 __ movq(R10, R13); // Smi-tagged arguments array length. |
| 1404 PushArgumentsArray(assembler); | 1404 PushArgumentsArray(assembler); |
| 1405 | 1405 |
| 1406 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry, 4); | 1406 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry, 4); |
| 1407 | 1407 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 | 1536 |
| 1537 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1537 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1538 __ addq(R12, Immediate(entry_size)); // Next entry. | 1538 __ addq(R12, Immediate(entry_size)); // Next entry. |
| 1539 __ movq(R13, Address(R12, 0)); // Next class ID. | 1539 __ movq(R13, Address(R12, 0)); // Next class ID. |
| 1540 | 1540 |
| 1541 __ Bind(&test); | 1541 __ Bind(&test); |
| 1542 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1542 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1543 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1543 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1544 | 1544 |
| 1545 // IC miss. | 1545 // IC miss. |
| 1546 __ LoadObject(R12, Object::Handle(), PP); | 1546 __ LoadObject(R12, Object::null_object(), PP); |
| 1547 // Compute address of arguments (first read number of arguments from | 1547 // Compute address of arguments (first read number of arguments from |
| 1548 // arguments descriptor array and then compute address on the stack). | 1548 // arguments descriptor array and then compute address on the stack). |
| 1549 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1549 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 1550 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1550 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
| 1551 __ EnterStubFrame(); | 1551 __ EnterStubFrame(); |
| 1552 __ pushq(R10); // Preserve arguments descriptor array. | 1552 __ pushq(R10); // Preserve arguments descriptor array. |
| 1553 __ pushq(RBX); // Preserve IC data object. | 1553 __ pushq(RBX); // Preserve IC data object. |
| 1554 __ pushq(R12); // Setup space on stack for result (target code object). | 1554 __ pushq(R12); // Setup space on stack for result (target code object). |
| 1555 // Push call arguments. | 1555 // Push call arguments. |
| 1556 for (intptr_t i = 0; i < num_args; i++) { | 1556 for (intptr_t i = 0; i < num_args; i++) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1731 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); | 1731 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); |
| 1732 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); | 1732 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); |
| 1733 __ movq(Address(R12, count_offset), | 1733 __ movq(Address(R12, count_offset), |
| 1734 Immediate(Smi::RawValue(Smi::kMaxValue))); | 1734 Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1735 __ Bind(&increment_done); | 1735 __ Bind(&increment_done); |
| 1736 | 1736 |
| 1737 Label target_is_compiled; | 1737 Label target_is_compiled; |
| 1738 // Get function and call it, if possible. | 1738 // Get function and call it, if possible. |
| 1739 __ movq(R13, Address(R12, target_offset)); | 1739 __ movq(R13, Address(R12, target_offset)); |
| 1740 __ movq(RAX, FieldAddress(R13, Function::code_offset())); | 1740 __ movq(RAX, FieldAddress(R13, Function::code_offset())); |
| 1741 __ LoadObject(R12, Object::Handle(), PP); | 1741 __ LoadObject(R12, Object::null_object(), PP); |
| 1742 __ cmpq(RAX, R12); | 1742 __ cmpq(RAX, R12); |
| 1743 __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); | 1743 __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump); |
| 1744 | 1744 |
| 1745 __ EnterStubFrame(); | 1745 __ EnterStubFrame(); |
| 1746 __ pushq(R13); // Preserve target function. | 1746 __ pushq(R13); // Preserve target function. |
| 1747 __ pushq(RBX); // Preserve IC data object. | 1747 __ pushq(RBX); // Preserve IC data object. |
| 1748 __ pushq(R13); // Pass function. | 1748 __ pushq(R13); // Pass function. |
| 1749 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1749 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
| 1750 __ popq(RAX); // Discard argument. | 1750 __ popq(RAX); // Discard argument. |
| 1751 __ popq(RBX); // Restore IC data object. | 1751 __ popq(RBX); // Restore IC data object. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1772 | 1772 |
| 1773 // RBX, R10: May contain arguments to runtime stub. | 1773 // RBX, R10: May contain arguments to runtime stub. |
| 1774 // TOS(0): return address (Dart code). | 1774 // TOS(0): return address (Dart code). |
| 1775 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1775 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1776 __ EnterStubFrame(); | 1776 __ EnterStubFrame(); |
| 1777 // Preserve runtime args. | 1777 // Preserve runtime args. |
| 1778 __ pushq(RBX); | 1778 __ pushq(RBX); |
| 1779 __ pushq(R10); | 1779 __ pushq(R10); |
| 1780 // Room for result. Debugger stub returns address of the | 1780 // Room for result. Debugger stub returns address of the |
| 1781 // unpatched runtime stub. | 1781 // unpatched runtime stub. |
| 1782 __ LoadObject(R12, Object::Handle(), PP); | 1782 __ LoadObject(R12, Object::null_object(), PP); |
| 1783 __ pushq(R12); // Room for result. | 1783 __ pushq(R12); // Room for result. |
| 1784 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1784 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| 1785 __ popq(RAX); // Address of original. | 1785 __ popq(RAX); // Address of original. |
| 1786 __ popq(R10); // Restore arguments. | 1786 __ popq(R10); // Restore arguments. |
| 1787 __ popq(RBX); | 1787 __ popq(RBX); |
| 1788 __ LeaveFrame(); | 1788 __ LeaveFrame(); |
| 1789 __ jmp(RAX); // Jump to original stub. | 1789 __ jmp(RAX); // Jump to original stub. |
| 1790 } | 1790 } |
| 1791 | 1791 |
| 1792 | 1792 |
| 1793 // RBX: ICData (unoptimized static call) | 1793 // RBX: ICData (unoptimized static call) |
| 1794 // TOS(0): return address (Dart code). | 1794 // TOS(0): return address (Dart code). |
| 1795 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1795 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1796 __ EnterStubFrame(); | 1796 __ EnterStubFrame(); |
| 1797 __ LoadObject(R12, Object::Handle(), PP); | 1797 __ LoadObject(R12, Object::null_object(), PP); |
| 1798 __ pushq(RBX); // Preserve IC data for unoptimized call. | 1798 __ pushq(RBX); // Preserve IC data for unoptimized call. |
| 1799 __ pushq(R12); // Room for result. | 1799 __ pushq(R12); // Room for result. |
| 1800 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); | 1800 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry, 0); |
| 1801 __ popq(RAX); // Code object. | 1801 __ popq(RAX); // Code object. |
| 1802 __ popq(RBX); // Restore IC data. | 1802 __ popq(RBX); // Restore IC data. |
| 1803 __ LeaveFrame(); | 1803 __ LeaveFrame(); |
| 1804 | 1804 |
| 1805 // Load arguments descriptor into R10. | 1805 // Load arguments descriptor into R10. |
| 1806 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1806 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
| 1807 // Now call the static function. The breakpoint handler function | 1807 // Now call the static function. The breakpoint handler function |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1859 // TOS + 1: instantiator type arguments (can be NULL). | 1859 // TOS + 1: instantiator type arguments (can be NULL). |
| 1860 // TOS + 2: instance. | 1860 // TOS + 2: instance. |
| 1861 // TOS + 3: SubtypeTestCache. | 1861 // TOS + 3: SubtypeTestCache. |
| 1862 // Result in RCX: null -> not found, otherwise result (true or false). | 1862 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1863 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1863 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1864 ASSERT((1 <= n) && (n <= 3)); | 1864 ASSERT((1 <= n) && (n <= 3)); |
| 1865 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1865 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1866 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1866 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1867 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1867 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1868 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1868 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
| 1869 __ LoadObject(R12, Object::Handle(), PP); | 1869 __ LoadObject(R12, Object::null_object(), PP); |
| 1870 if (n > 1) { | 1870 if (n > 1) { |
| 1871 __ LoadClass(R10, RAX); | 1871 __ LoadClass(R10, RAX); |
| 1872 // Compute instance type arguments into R13. | 1872 // Compute instance type arguments into R13. |
| 1873 Label has_no_type_arguments; | 1873 Label has_no_type_arguments; |
| 1874 __ movq(R13, R12); | 1874 __ movq(R13, R12); |
| 1875 __ movq(RDI, FieldAddress(R10, | 1875 __ movq(RDI, FieldAddress(R10, |
| 1876 Class::type_arguments_field_offset_in_words_offset())); | 1876 Class::type_arguments_field_offset_in_words_offset())); |
| 1877 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); | 1877 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); |
| 1878 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1878 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
| 1879 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); | 1879 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2087 __ LeaveFrame(); | 2087 __ LeaveFrame(); |
| 2088 | 2088 |
| 2089 __ jmp(&compute_result, Assembler::kNearJump); | 2089 __ jmp(&compute_result, Assembler::kNearJump); |
| 2090 } | 2090 } |
| 2091 | 2091 |
| 2092 // Calls to the runtime to optimize the given function. | 2092 // Calls to the runtime to optimize the given function. |
| 2093 // RDI: function to be reoptimized. | 2093 // RDI: function to be reoptimized. |
| 2094 // R10: argument descriptor (preserved). | 2094 // R10: argument descriptor (preserved). |
| 2095 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 2095 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
| 2096 __ EnterStubFrameWithPP(); | 2096 __ EnterStubFrameWithPP(); |
| 2097 __ LoadObject(R12, Object::Handle(), PP); | 2097 __ LoadObject(R12, Object::null_object(), PP); |
| 2098 __ pushq(R10); | 2098 __ pushq(R10); |
| 2099 __ pushq(R12); // Setup space on stack for return value. | 2099 __ pushq(R12); // Setup space on stack for return value. |
| 2100 __ pushq(RDI); | 2100 __ pushq(RDI); |
| 2101 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 2101 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
| 2102 __ popq(RAX); // Disard argument. | 2102 __ popq(RAX); // Disard argument. |
| 2103 __ popq(RAX); // Get Code object. | 2103 __ popq(RAX); // Get Code object. |
| 2104 __ popq(R10); // Restore argument descriptor. | 2104 __ popq(R10); // Restore argument descriptor. |
| 2105 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 2105 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 2106 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 2106 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 2107 __ LeaveFrameWithPP(); | 2107 __ LeaveFrameWithPP(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2220 __ movq(right, Address(RSP, 3 * kWordSize)); | 2220 __ movq(right, Address(RSP, 3 * kWordSize)); |
| 2221 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2221 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 2222 __ popq(right); | 2222 __ popq(right); |
| 2223 __ popq(left); | 2223 __ popq(left); |
| 2224 __ ret(); | 2224 __ ret(); |
| 2225 } | 2225 } |
| 2226 | 2226 |
| 2227 } // namespace dart | 2227 } // namespace dart |
| 2228 | 2228 |
| 2229 #endif // defined TARGET_ARCH_X64 | 2229 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |