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