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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 // Mark that the thread is executing Dart code. | 89 // Mark that the thread is executing Dart code. |
90 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); | 90 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); |
91 | 91 |
92 // Reset exit frame information in Isolate structure. | 92 // Reset exit frame information in Isolate structure. |
93 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 93 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
94 | 94 |
95 __ LeaveStubFrame(); | 95 __ LeaveStubFrame(); |
96 __ ret(); | 96 __ ret(); |
97 } | 97 } |
98 | 98 |
99 | |
100 // Print the stop message. | 99 // Print the stop message. |
101 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { | 100 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { |
102 OS::Print("Stop message: %s\n", message); | 101 OS::Print("Stop message: %s\n", message); |
103 } | 102 } |
104 END_LEAF_RUNTIME_ENTRY | 103 END_LEAF_RUNTIME_ENTRY |
105 | 104 |
106 | |
107 // Input parameters: | 105 // Input parameters: |
108 // RSP : points to return address. | 106 // RSP : points to return address. |
109 // RDI : stop message (const char*). | 107 // RDI : stop message (const char*). |
110 // Must preserve all registers. | 108 // Must preserve all registers. |
111 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { | 109 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { |
112 __ EnterCallRuntimeFrame(0); | 110 __ EnterCallRuntimeFrame(0); |
113 // Call the runtime leaf function. RDI already contains the parameter. | 111 // Call the runtime leaf function. RDI already contains the parameter. |
114 #if defined(_WIN64) | 112 #if defined(_WIN64) |
115 __ movq(CallingConventions::kArg1Reg, RDI); | 113 __ movq(CallingConventions::kArg1Reg, RDI); |
116 #endif | 114 #endif |
117 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); | 115 __ CallRuntime(kPrintStopMessageRuntimeEntry, 1); |
118 __ LeaveCallRuntimeFrame(); | 116 __ LeaveCallRuntimeFrame(); |
119 __ ret(); | 117 __ ret(); |
120 } | 118 } |
121 | 119 |
122 | |
123 // Input parameters: | 120 // Input parameters: |
124 // RSP : points to return address. | 121 // RSP : points to return address. |
125 // RSP + 8 : address of return value. | 122 // RSP + 8 : address of return value. |
126 // RAX : address of first argument in argument array. | 123 // RAX : address of first argument in argument array. |
127 // RBX : address of the native function to call. | 124 // RBX : address of the native function to call. |
128 // R10 : argc_tag including number of arguments and function kind. | 125 // R10 : argc_tag including number of arguments and function kind. |
129 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, | 126 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, |
130 Address wrapper_address) { | 127 Address wrapper_address) { |
131 const intptr_t native_args_struct_offset = 0; | 128 const intptr_t native_args_struct_offset = 0; |
132 const intptr_t thread_offset = | 129 const intptr_t thread_offset = |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 // Mark that the thread is executing Dart code. | 182 // Mark that the thread is executing Dart code. |
186 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); | 183 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); |
187 | 184 |
188 // Reset exit frame information in Isolate structure. | 185 // Reset exit frame information in Isolate structure. |
189 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 186 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
190 | 187 |
191 __ LeaveStubFrame(); | 188 __ LeaveStubFrame(); |
192 __ ret(); | 189 __ ret(); |
193 } | 190 } |
194 | 191 |
195 | |
196 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { | 192 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { |
197 GenerateCallNativeWithWrapperStub( | 193 GenerateCallNativeWithWrapperStub( |
198 assembler, | 194 assembler, |
199 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset())); | 195 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset())); |
200 } | 196 } |
201 | 197 |
202 | |
203 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { | 198 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { |
204 GenerateCallNativeWithWrapperStub( | 199 GenerateCallNativeWithWrapperStub( |
205 assembler, | 200 assembler, |
206 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset())); | 201 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset())); |
207 } | 202 } |
208 | 203 |
209 | |
210 // Input parameters: | 204 // Input parameters: |
211 // RSP : points to return address. | 205 // RSP : points to return address. |
212 // RSP + 8 : address of return value. | 206 // RSP + 8 : address of return value. |
213 // RAX : address of first argument in argument array. | 207 // RAX : address of first argument in argument array. |
214 // RBX : address of the native function to call. | 208 // RBX : address of the native function to call. |
215 // R10 : argc_tag including number of arguments and function kind. | 209 // R10 : argc_tag including number of arguments and function kind. |
216 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { | 210 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { |
217 const intptr_t native_args_struct_offset = 0; | 211 const intptr_t native_args_struct_offset = 0; |
218 const intptr_t thread_offset = | 212 const intptr_t thread_offset = |
219 NativeArguments::thread_offset() + native_args_struct_offset; | 213 NativeArguments::thread_offset() + native_args_struct_offset; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 // Mark that the thread is executing Dart code. | 261 // Mark that the thread is executing Dart code. |
268 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); | 262 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); |
269 | 263 |
270 // Reset exit frame information in Isolate structure. | 264 // Reset exit frame information in Isolate structure. |
271 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 265 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
272 | 266 |
273 __ LeaveStubFrame(); | 267 __ LeaveStubFrame(); |
274 __ ret(); | 268 __ ret(); |
275 } | 269 } |
276 | 270 |
277 | |
278 // Input parameters: | 271 // Input parameters: |
279 // R10: arguments descriptor array. | 272 // R10: arguments descriptor array. |
280 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { | 273 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { |
281 __ EnterStubFrame(); | 274 __ EnterStubFrame(); |
282 __ pushq(R10); // Preserve arguments descriptor array. | 275 __ pushq(R10); // Preserve arguments descriptor array. |
283 // Setup space on stack for return value. | 276 // Setup space on stack for return value. |
284 __ pushq(Immediate(0)); | 277 __ pushq(Immediate(0)); |
285 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); | 278 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); |
286 __ popq(CODE_REG); // Get Code object result. | 279 __ popq(CODE_REG); // Get Code object result. |
287 __ popq(R10); // Restore arguments descriptor array. | 280 __ popq(R10); // Restore arguments descriptor array. |
288 // Remove the stub frame as we are about to jump to the dart function. | 281 // Remove the stub frame as we are about to jump to the dart function. |
289 __ LeaveStubFrame(); | 282 __ LeaveStubFrame(); |
290 | 283 |
291 __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 284 __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
292 __ jmp(RBX); | 285 __ jmp(RBX); |
293 } | 286 } |
294 | 287 |
295 | |
296 // Called from a static call only when an invalid code has been entered | 288 // Called from a static call only when an invalid code has been entered |
297 // (invalid because its function was optimized or deoptimized). | 289 // (invalid because its function was optimized or deoptimized). |
298 // R10: arguments descriptor array. | 290 // R10: arguments descriptor array. |
299 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { | 291 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { |
300 // Load code pointer to this stub from the thread: | 292 // Load code pointer to this stub from the thread: |
301 // The one that is passed in, is not correct - it points to the code object | 293 // The one that is passed in, is not correct - it points to the code object |
302 // that needs to be replaced. | 294 // that needs to be replaced. |
303 __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); | 295 __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); |
304 __ EnterStubFrame(); | 296 __ EnterStubFrame(); |
305 __ pushq(R10); // Preserve arguments descriptor array. | 297 __ pushq(R10); // Preserve arguments descriptor array. |
306 // Setup space on stack for return value. | 298 // Setup space on stack for return value. |
307 __ pushq(Immediate(0)); | 299 __ pushq(Immediate(0)); |
308 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); | 300 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); |
309 __ popq(CODE_REG); // Get Code object. | 301 __ popq(CODE_REG); // Get Code object. |
310 __ popq(R10); // Restore arguments descriptor array. | 302 __ popq(R10); // Restore arguments descriptor array. |
311 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 303 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
312 __ LeaveStubFrame(); | 304 __ LeaveStubFrame(); |
313 __ jmp(RAX); | 305 __ jmp(RAX); |
314 __ int3(); | 306 __ int3(); |
315 } | 307 } |
316 | 308 |
317 | |
318 // Called from object allocate instruction when the allocation stub has been | 309 // Called from object allocate instruction when the allocation stub has been |
319 // disabled. | 310 // disabled. |
320 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { | 311 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { |
321 // Load code pointer to this stub from the thread: | 312 // Load code pointer to this stub from the thread: |
322 // The one that is passed in, is not correct - it points to the code object | 313 // The one that is passed in, is not correct - it points to the code object |
323 // that needs to be replaced. | 314 // that needs to be replaced. |
324 __ movq(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); | 315 __ movq(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); |
325 __ EnterStubFrame(); | 316 __ EnterStubFrame(); |
326 // Setup space on stack for return value. | 317 // Setup space on stack for return value. |
327 __ pushq(Immediate(0)); | 318 __ pushq(Immediate(0)); |
328 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); | 319 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); |
329 __ popq(CODE_REG); // Get Code object. | 320 __ popq(CODE_REG); // Get Code object. |
330 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 321 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
331 __ LeaveStubFrame(); | 322 __ LeaveStubFrame(); |
332 __ jmp(RAX); | 323 __ jmp(RAX); |
333 __ int3(); | 324 __ int3(); |
334 } | 325 } |
335 | 326 |
336 | |
337 // Input parameters: | 327 // Input parameters: |
338 // R10: smi-tagged argument count, may be zero. | 328 // R10: smi-tagged argument count, may be zero. |
339 // RBP[kParamEndSlotFromFp + 1]: last argument. | 329 // RBP[kParamEndSlotFromFp + 1]: last argument. |
340 static void PushArgumentsArray(Assembler* assembler) { | 330 static void PushArgumentsArray(Assembler* assembler) { |
341 __ LoadObject(R12, Object::null_object()); | 331 __ LoadObject(R12, Object::null_object()); |
342 // Allocate array to store arguments of caller. | 332 // Allocate array to store arguments of caller. |
343 __ movq(RBX, R12); // Null element type for raw Array. | 333 __ movq(RBX, R12); // Null element type for raw Array. |
344 __ Call(*StubCode::AllocateArray_entry()); | 334 __ Call(*StubCode::AllocateArray_entry()); |
345 __ SmiUntag(R10); | 335 __ SmiUntag(R10); |
346 // RAX: newly allocated array. | 336 // RAX: newly allocated array. |
(...skipping 14 matching lines...) Expand all Loading... |
361 __ movq(RDI, Address(R12, 0)); | 351 __ movq(RDI, Address(R12, 0)); |
362 // Generational barrier is needed, array is not necessarily in new space. | 352 // Generational barrier is needed, array is not necessarily in new space. |
363 __ StoreIntoObject(RAX, Address(RBX, 0), RDI); | 353 __ StoreIntoObject(RAX, Address(RBX, 0), RDI); |
364 __ addq(RBX, Immediate(kWordSize)); | 354 __ addq(RBX, Immediate(kWordSize)); |
365 __ subq(R12, Immediate(kWordSize)); | 355 __ subq(R12, Immediate(kWordSize)); |
366 __ Bind(&loop_condition); | 356 __ Bind(&loop_condition); |
367 __ decq(R10); | 357 __ decq(R10); |
368 __ j(POSITIVE, &loop, Assembler::kNearJump); | 358 __ j(POSITIVE, &loop, Assembler::kNearJump); |
369 } | 359 } |
370 | 360 |
371 | |
372 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. | 361 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. |
373 // This stub translates optimized frame into unoptimized frame. The optimized | 362 // This stub translates optimized frame into unoptimized frame. The optimized |
374 // frame can contain values in registers and on stack, the unoptimized | 363 // frame can contain values in registers and on stack, the unoptimized |
375 // frame contains all values on stack. | 364 // frame contains all values on stack. |
376 // Deoptimization occurs in following steps: | 365 // Deoptimization occurs in following steps: |
377 // - Push all registers that can contain values. | 366 // - Push all registers that can contain values. |
378 // - Call C routine to copy the stack and saved registers into temporary buffer. | 367 // - Call C routine to copy the stack and saved registers into temporary buffer. |
379 // - Adjust caller's frame to correct unoptimized frame size. | 368 // - Adjust caller's frame to correct unoptimized frame size. |
380 // - Fill the unoptimized frame. | 369 // - Fill the unoptimized frame. |
381 // - Materialize objects that require allocation (e.g. Double instances). | 370 // - Materialize objects that require allocation (e.g. Double instances). |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 __ popq(RAX); // Restore exception. | 498 __ popq(RAX); // Restore exception. |
510 } | 499 } |
511 __ LeaveStubFrame(); | 500 __ LeaveStubFrame(); |
512 | 501 |
513 __ popq(RCX); // Pop return address. | 502 __ popq(RCX); // Pop return address. |
514 __ addq(RSP, RBX); // Remove materialization arguments. | 503 __ addq(RSP, RBX); // Remove materialization arguments. |
515 __ pushq(RCX); // Push return address. | 504 __ pushq(RCX); // Push return address. |
516 // The caller is responsible for emitting the return instruction. | 505 // The caller is responsible for emitting the return instruction. |
517 } | 506 } |
518 | 507 |
519 | |
520 // RAX: result, must be preserved | 508 // RAX: result, must be preserved |
521 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { | 509 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { |
522 // Push zap value instead of CODE_REG for lazy deopt. | 510 // Push zap value instead of CODE_REG for lazy deopt. |
523 __ pushq(Immediate(kZapCodeReg)); | 511 __ pushq(Immediate(kZapCodeReg)); |
524 // Return address for "call" to deopt stub. | 512 // Return address for "call" to deopt stub. |
525 __ pushq(Immediate(kZapReturnAddress)); | 513 __ pushq(Immediate(kZapReturnAddress)); |
526 __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); | 514 __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); |
527 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); | 515 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); |
528 __ ret(); | 516 __ ret(); |
529 } | 517 } |
530 | 518 |
531 | |
532 // RAX: exception, must be preserved | 519 // RAX: exception, must be preserved |
533 // RDX: stacktrace, must be preserved | 520 // RDX: stacktrace, must be preserved |
534 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { | 521 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { |
535 // Push zap value instead of CODE_REG for lazy deopt. | 522 // Push zap value instead of CODE_REG for lazy deopt. |
536 __ pushq(Immediate(kZapCodeReg)); | 523 __ pushq(Immediate(kZapCodeReg)); |
537 // Return address for "call" to deopt stub. | 524 // Return address for "call" to deopt stub. |
538 __ pushq(Immediate(kZapReturnAddress)); | 525 __ pushq(Immediate(kZapReturnAddress)); |
539 __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); | 526 __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); |
540 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); | 527 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); |
541 __ ret(); | 528 __ ret(); |
542 } | 529 } |
543 | 530 |
544 | |
545 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 531 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
546 GenerateDeoptimizationSequence(assembler, kEagerDeopt); | 532 GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
547 __ ret(); | 533 __ ret(); |
548 } | 534 } |
549 | 535 |
550 | |
551 static void GenerateDispatcherCode(Assembler* assembler, | 536 static void GenerateDispatcherCode(Assembler* assembler, |
552 Label* call_target_function) { | 537 Label* call_target_function) { |
553 __ Comment("NoSuchMethodDispatch"); | 538 __ Comment("NoSuchMethodDispatch"); |
554 // When lazily generated invocation dispatchers are disabled, the | 539 // When lazily generated invocation dispatchers are disabled, the |
555 // miss-handler may return null. | 540 // miss-handler may return null. |
556 __ CompareObject(RAX, Object::null_object()); | 541 __ CompareObject(RAX, Object::null_object()); |
557 __ j(NOT_EQUAL, call_target_function); | 542 __ j(NOT_EQUAL, call_target_function); |
558 __ EnterStubFrame(); | 543 __ EnterStubFrame(); |
559 // Load the receiver. | 544 // Load the receiver. |
560 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 545 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
(...skipping 16 matching lines...) Expand all Loading... |
577 // R10: Smi-tagged arguments array length. | 562 // R10: Smi-tagged arguments array length. |
578 PushArgumentsArray(assembler); | 563 PushArgumentsArray(assembler); |
579 const intptr_t kNumArgs = 4; | 564 const intptr_t kNumArgs = 4; |
580 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | 565 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); |
581 __ Drop(4); | 566 __ Drop(4); |
582 __ popq(RAX); // Return value. | 567 __ popq(RAX); // Return value. |
583 __ LeaveStubFrame(); | 568 __ LeaveStubFrame(); |
584 __ ret(); | 569 __ ret(); |
585 } | 570 } |
586 | 571 |
587 | |
588 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { | 572 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { |
589 __ EnterStubFrame(); | 573 __ EnterStubFrame(); |
590 // Load the receiver into RAX. The argument count in the arguments | 574 // Load the receiver into RAX. The argument count in the arguments |
591 // descriptor in R10 is a smi. | 575 // descriptor in R10 is a smi. |
592 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 576 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
593 // Three words (saved pp, saved fp, stub's pc marker) | 577 // Three words (saved pp, saved fp, stub's pc marker) |
594 // in the stack above the return address. | 578 // in the stack above the return address. |
595 __ movq(RAX, | 579 __ movq(RAX, |
596 Address(RSP, RAX, TIMES_4, kSavedAboveReturnAddress * kWordSize)); | 580 Address(RSP, RAX, TIMES_4, kSavedAboveReturnAddress * kWordSize)); |
597 // Preserve IC data and arguments descriptor. | 581 // Preserve IC data and arguments descriptor. |
(...skipping 18 matching lines...) Expand all Loading... |
616 if (!FLAG_lazy_dispatchers) { | 600 if (!FLAG_lazy_dispatchers) { |
617 Label call_target_function; | 601 Label call_target_function; |
618 GenerateDispatcherCode(assembler, &call_target_function); | 602 GenerateDispatcherCode(assembler, &call_target_function); |
619 __ Bind(&call_target_function); | 603 __ Bind(&call_target_function); |
620 } | 604 } |
621 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 605 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
622 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 606 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
623 __ jmp(RCX); | 607 __ jmp(RCX); |
624 } | 608 } |
625 | 609 |
626 | |
627 // Called for inline allocation of arrays. | 610 // Called for inline allocation of arrays. |
628 // Input parameters: | 611 // Input parameters: |
629 // R10 : Array length as Smi. | 612 // R10 : Array length as Smi. |
630 // RBX : array element type (either NULL or an instantiated type). | 613 // RBX : array element type (either NULL or an instantiated type). |
631 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 614 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
632 // The newly allocated object is returned in RAX. | 615 // The newly allocated object is returned in RAX. |
633 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 616 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
634 Label slow_case; | 617 Label slow_case; |
635 // Compute the size to be allocated, it is based on the array length | 618 // Compute the size to be allocated, it is based on the array length |
636 // and is computed as: | 619 // and is computed as: |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 __ pushq(R10); // Array length as Smi. | 732 __ pushq(R10); // Array length as Smi. |
750 __ pushq(RBX); // Element type. | 733 __ pushq(RBX); // Element type. |
751 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); | 734 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); |
752 __ popq(RAX); // Pop element type argument. | 735 __ popq(RAX); // Pop element type argument. |
753 __ popq(R10); // Pop array length argument. | 736 __ popq(R10); // Pop array length argument. |
754 __ popq(RAX); // Pop return value from return slot. | 737 __ popq(RAX); // Pop return value from return slot. |
755 __ LeaveStubFrame(); | 738 __ LeaveStubFrame(); |
756 __ ret(); | 739 __ ret(); |
757 } | 740 } |
758 | 741 |
759 | |
760 // Called when invoking Dart code from C++ (VM code). | 742 // Called when invoking Dart code from C++ (VM code). |
761 // Input parameters: | 743 // Input parameters: |
762 // RSP : points to return address. | 744 // RSP : points to return address. |
763 // RDI : target code | 745 // RDI : target code |
764 // RSI : arguments descriptor array. | 746 // RSI : arguments descriptor array. |
765 // RDX : arguments array. | 747 // RDX : arguments array. |
766 // RCX : current thread. | 748 // RCX : current thread. |
767 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { | 749 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { |
768 // Save frame pointer coming in. | 750 // Save frame pointer coming in. |
769 __ EnterFrame(0); | 751 __ EnterFrame(0); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, | 863 __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters, |
882 CallingConventions::kCalleeSaveXmmRegisters); | 864 CallingConventions::kCalleeSaveXmmRegisters); |
883 __ set_constant_pool_allowed(false); | 865 __ set_constant_pool_allowed(false); |
884 | 866 |
885 // Restore the frame pointer. | 867 // Restore the frame pointer. |
886 __ LeaveFrame(); | 868 __ LeaveFrame(); |
887 | 869 |
888 __ ret(); | 870 __ ret(); |
889 } | 871 } |
890 | 872 |
891 | |
892 // Called for inline allocation of contexts. | 873 // Called for inline allocation of contexts. |
893 // Input: | 874 // Input: |
894 // R10: number of context variables. | 875 // R10: number of context variables. |
895 // Output: | 876 // Output: |
896 // RAX: new allocated RawContext object. | 877 // RAX: new allocated RawContext object. |
897 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { | 878 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { |
898 __ LoadObject(R9, Object::null_object()); | 879 __ LoadObject(R9, Object::null_object()); |
899 if (FLAG_inline_alloc) { | 880 if (FLAG_inline_alloc) { |
900 Label slow_case; | 881 Label slow_case; |
901 // First compute the rounded instance size. | 882 // First compute the rounded instance size. |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 __ pushq(R10); // Push number of context variables. | 992 __ pushq(R10); // Push number of context variables. |
1012 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. | 993 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. |
1013 __ popq(RAX); // Pop number of context variables argument. | 994 __ popq(RAX); // Pop number of context variables argument. |
1014 __ popq(RAX); // Pop the new context object. | 995 __ popq(RAX); // Pop the new context object. |
1015 // RAX: new object | 996 // RAX: new object |
1016 // Restore the frame pointer. | 997 // Restore the frame pointer. |
1017 __ LeaveStubFrame(); | 998 __ LeaveStubFrame(); |
1018 __ ret(); | 999 __ ret(); |
1019 } | 1000 } |
1020 | 1001 |
1021 | |
1022 // Helper stub to implement Assembler::StoreIntoObject. | 1002 // Helper stub to implement Assembler::StoreIntoObject. |
1023 // Input parameters: | 1003 // Input parameters: |
1024 // RDX: Address being stored | 1004 // RDX: Address being stored |
1025 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { | 1005 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { |
1026 // Save registers being destroyed. | 1006 // Save registers being destroyed. |
1027 __ pushq(RAX); | 1007 __ pushq(RAX); |
1028 __ pushq(RCX); | 1008 __ pushq(RCX); |
1029 | 1009 |
1030 Label add_to_buffer; | 1010 Label add_to_buffer; |
1031 // Check whether this object has already been remembered. Skip adding to the | 1011 // Check whether this object has already been remembered. Skip adding to the |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1076 // Handle overflow: Call the runtime leaf function. | 1056 // Handle overflow: Call the runtime leaf function. |
1077 __ Bind(&L); | 1057 __ Bind(&L); |
1078 // Setup frame, push callee-saved registers. | 1058 // Setup frame, push callee-saved registers. |
1079 __ EnterCallRuntimeFrame(0); | 1059 __ EnterCallRuntimeFrame(0); |
1080 __ movq(CallingConventions::kArg1Reg, THR); | 1060 __ movq(CallingConventions::kArg1Reg, THR); |
1081 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); | 1061 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); |
1082 __ LeaveCallRuntimeFrame(); | 1062 __ LeaveCallRuntimeFrame(); |
1083 __ ret(); | 1063 __ ret(); |
1084 } | 1064 } |
1085 | 1065 |
1086 | |
1087 // Called for inline allocation of objects. | 1066 // Called for inline allocation of objects. |
1088 // Input parameters: | 1067 // Input parameters: |
1089 // RSP + 8 : type arguments object (only if class is parameterized). | 1068 // RSP + 8 : type arguments object (only if class is parameterized). |
1090 // RSP : points to return address. | 1069 // RSP : points to return address. |
1091 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, | 1070 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, |
1092 const Class& cls) { | 1071 const Class& cls) { |
1093 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; | 1072 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; |
1094 // The generated code is different if the class is parameterized. | 1073 // The generated code is different if the class is parameterized. |
1095 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; | 1074 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; |
1096 ASSERT(!is_cls_parameterized || | 1075 ASSERT(!is_cls_parameterized || |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. | 1183 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. |
1205 __ popq(RAX); // Pop argument (type arguments of object). | 1184 __ popq(RAX); // Pop argument (type arguments of object). |
1206 __ popq(RAX); // Pop argument (class of object). | 1185 __ popq(RAX); // Pop argument (class of object). |
1207 __ popq(RAX); // Pop result (newly allocated object). | 1186 __ popq(RAX); // Pop result (newly allocated object). |
1208 // RAX: new object | 1187 // RAX: new object |
1209 // Restore the frame pointer. | 1188 // Restore the frame pointer. |
1210 __ LeaveStubFrame(); | 1189 __ LeaveStubFrame(); |
1211 __ ret(); | 1190 __ ret(); |
1212 } | 1191 } |
1213 | 1192 |
1214 | |
1215 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function | 1193 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function |
1216 // from the entry code of a dart function after an error in passed argument | 1194 // from the entry code of a dart function after an error in passed argument |
1217 // name or number is detected. | 1195 // name or number is detected. |
1218 // Input parameters: | 1196 // Input parameters: |
1219 // RSP : points to return address. | 1197 // RSP : points to return address. |
1220 // RSP + 8 : address of last argument. | 1198 // RSP + 8 : address of last argument. |
1221 // R10 : arguments descriptor array. | 1199 // R10 : arguments descriptor array. |
1222 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { | 1200 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { |
1223 __ EnterStubFrame(); | 1201 __ EnterStubFrame(); |
1224 | 1202 |
(...skipping 16 matching lines...) Expand all Loading... |
1241 | 1219 |
1242 // R10: Smi-tagged arguments array length. | 1220 // R10: Smi-tagged arguments array length. |
1243 PushArgumentsArray(assembler); | 1221 PushArgumentsArray(assembler); |
1244 | 1222 |
1245 const intptr_t kNumArgs = 3; | 1223 const intptr_t kNumArgs = 3; |
1246 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); | 1224 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); |
1247 // noSuchMethod on closures always throws an error, so it will never return. | 1225 // noSuchMethod on closures always throws an error, so it will never return. |
1248 __ int3(); | 1226 __ int3(); |
1249 } | 1227 } |
1250 | 1228 |
1251 | |
1252 // Cannot use function object from ICData as it may be the inlined | 1229 // Cannot use function object from ICData as it may be the inlined |
1253 // function and not the top-scope function. | 1230 // function and not the top-scope function. |
1254 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1231 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1255 Register ic_reg = RBX; | 1232 Register ic_reg = RBX; |
1256 Register func_reg = RDI; | 1233 Register func_reg = RDI; |
1257 if (FLAG_trace_optimized_ic_calls) { | 1234 if (FLAG_trace_optimized_ic_calls) { |
1258 __ EnterStubFrame(); | 1235 __ EnterStubFrame(); |
1259 __ pushq(func_reg); // Preserve | 1236 __ pushq(func_reg); // Preserve |
1260 __ pushq(ic_reg); // Preserve. | 1237 __ pushq(ic_reg); // Preserve. |
1261 __ pushq(ic_reg); // Argument. | 1238 __ pushq(ic_reg); // Argument. |
1262 __ pushq(func_reg); // Argument. | 1239 __ pushq(func_reg); // Argument. |
1263 __ CallRuntime(kTraceICCallRuntimeEntry, 2); | 1240 __ CallRuntime(kTraceICCallRuntimeEntry, 2); |
1264 __ popq(RAX); // Discard argument; | 1241 __ popq(RAX); // Discard argument; |
1265 __ popq(RAX); // Discard argument; | 1242 __ popq(RAX); // Discard argument; |
1266 __ popq(ic_reg); // Restore. | 1243 __ popq(ic_reg); // Restore. |
1267 __ popq(func_reg); // Restore. | 1244 __ popq(func_reg); // Restore. |
1268 __ LeaveStubFrame(); | 1245 __ LeaveStubFrame(); |
1269 } | 1246 } |
1270 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1247 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
1271 } | 1248 } |
1272 | 1249 |
1273 | |
1274 // Loads function into 'temp_reg', preserves 'ic_reg'. | 1250 // Loads function into 'temp_reg', preserves 'ic_reg'. |
1275 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1251 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
1276 Register temp_reg) { | 1252 Register temp_reg) { |
1277 if (FLAG_optimization_counter_threshold >= 0) { | 1253 if (FLAG_optimization_counter_threshold >= 0) { |
1278 Register ic_reg = RBX; | 1254 Register ic_reg = RBX; |
1279 Register func_reg = temp_reg; | 1255 Register func_reg = temp_reg; |
1280 ASSERT(ic_reg != func_reg); | 1256 ASSERT(ic_reg != func_reg); |
1281 __ Comment("Increment function counter"); | 1257 __ Comment("Increment function counter"); |
1282 __ movq(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); | 1258 __ movq(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); |
1283 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1259 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
1284 } | 1260 } |
1285 } | 1261 } |
1286 | 1262 |
1287 | |
1288 // Note: RBX must be preserved. | 1263 // Note: RBX must be preserved. |
1289 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1264 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
1290 // must have been primed with a Smi/Smi check that will be used for counting | 1265 // must have been primed with a Smi/Smi check that will be used for counting |
1291 // the invocations. | 1266 // the invocations. |
1292 static void EmitFastSmiOp(Assembler* assembler, | 1267 static void EmitFastSmiOp(Assembler* assembler, |
1293 Token::Kind kind, | 1268 Token::Kind kind, |
1294 intptr_t num_args, | 1269 intptr_t num_args, |
1295 Label* not_smi_or_overflow) { | 1270 Label* not_smi_or_overflow) { |
1296 __ Comment("Fast Smi op"); | 1271 __ Comment("Fast Smi op"); |
1297 ASSERT(num_args == 2); | 1272 ASSERT(num_args == 2); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 | 1323 |
1349 if (FLAG_optimization_counter_threshold >= 0) { | 1324 if (FLAG_optimization_counter_threshold >= 0) { |
1350 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1325 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1351 // Update counter, ignore overflow. | 1326 // Update counter, ignore overflow. |
1352 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); | 1327 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); |
1353 } | 1328 } |
1354 | 1329 |
1355 __ ret(); | 1330 __ ret(); |
1356 } | 1331 } |
1357 | 1332 |
1358 | |
1359 // Generate inline cache check for 'num_args'. | 1333 // Generate inline cache check for 'num_args'. |
1360 // RBX: Inline cache data object. | 1334 // RBX: Inline cache data object. |
1361 // TOS(0): return address | 1335 // TOS(0): return address |
1362 // Control flow: | 1336 // Control flow: |
1363 // - If receiver is null -> jump to IC miss. | 1337 // - If receiver is null -> jump to IC miss. |
1364 // - If receiver is Smi -> load Smi class. | 1338 // - If receiver is Smi -> load Smi class. |
1365 // - If receiver is not-Smi -> load receiver's class. | 1339 // - If receiver is not-Smi -> load receiver's class. |
1366 // - Check if 'num_args' (including receiver) match any IC data group. | 1340 // - Check if 'num_args' (including receiver) match any IC data group. |
1367 // - Match found -> jump to target. | 1341 // - Match found -> jump to target. |
1368 // - Match not found -> jump to IC miss. | 1342 // - Match not found -> jump to IC miss. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 __ EnterStubFrame(); | 1490 __ EnterStubFrame(); |
1517 __ pushq(RBX); | 1491 __ pushq(RBX); |
1518 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1492 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1519 __ popq(RBX); | 1493 __ popq(RBX); |
1520 __ RestoreCodePointer(); | 1494 __ RestoreCodePointer(); |
1521 __ LeaveStubFrame(); | 1495 __ LeaveStubFrame(); |
1522 __ jmp(&done_stepping); | 1496 __ jmp(&done_stepping); |
1523 } | 1497 } |
1524 } | 1498 } |
1525 | 1499 |
1526 | |
1527 // Use inline cache data array to invoke the target or continue in inline | 1500 // Use inline cache data array to invoke the target or continue in inline |
1528 // cache miss handler. Stub for 1-argument check (receiver class). | 1501 // cache miss handler. Stub for 1-argument check (receiver class). |
1529 // RBX: Inline cache data object. | 1502 // RBX: Inline cache data object. |
1530 // TOS(0): Return address. | 1503 // TOS(0): Return address. |
1531 // Inline cache data object structure: | 1504 // Inline cache data object structure: |
1532 // 0: function-name | 1505 // 0: function-name |
1533 // 1: N, number of arguments checked. | 1506 // 1: N, number of arguments checked. |
1534 // 2 .. (length - 1): group of checks, each check containing: | 1507 // 2 .. (length - 1): group of checks, each check containing: |
1535 // - N classes. | 1508 // - N classes. |
1536 // - 1 target function. | 1509 // - 1 target function. |
1537 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1510 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1538 GenerateUsageCounterIncrement(assembler, RCX); | 1511 GenerateUsageCounterIncrement(assembler, RCX); |
1539 GenerateNArgsCheckInlineCacheStub( | 1512 GenerateNArgsCheckInlineCacheStub( |
1540 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1513 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1541 } | 1514 } |
1542 | 1515 |
1543 | |
1544 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1516 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1545 GenerateUsageCounterIncrement(assembler, RCX); | 1517 GenerateUsageCounterIncrement(assembler, RCX); |
1546 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1518 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1547 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1519 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1548 Token::kILLEGAL); | 1520 Token::kILLEGAL); |
1549 } | 1521 } |
1550 | 1522 |
1551 | |
1552 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1523 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
1553 GenerateUsageCounterIncrement(assembler, RCX); | 1524 GenerateUsageCounterIncrement(assembler, RCX); |
1554 GenerateNArgsCheckInlineCacheStub( | 1525 GenerateNArgsCheckInlineCacheStub( |
1555 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); | 1526 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); |
1556 } | 1527 } |
1557 | 1528 |
1558 | |
1559 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1529 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
1560 GenerateUsageCounterIncrement(assembler, RCX); | 1530 GenerateUsageCounterIncrement(assembler, RCX); |
1561 GenerateNArgsCheckInlineCacheStub( | 1531 GenerateNArgsCheckInlineCacheStub( |
1562 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); | 1532 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); |
1563 } | 1533 } |
1564 | 1534 |
1565 | |
1566 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1535 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
1567 GenerateUsageCounterIncrement(assembler, RCX); | 1536 GenerateUsageCounterIncrement(assembler, RCX); |
1568 GenerateNArgsCheckInlineCacheStub( | 1537 GenerateNArgsCheckInlineCacheStub( |
1569 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); | 1538 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); |
1570 } | 1539 } |
1571 | 1540 |
1572 | |
1573 // Use inline cache data array to invoke the target or continue in inline | 1541 // Use inline cache data array to invoke the target or continue in inline |
1574 // cache miss handler. Stub for 1-argument check (receiver class). | 1542 // cache miss handler. Stub for 1-argument check (receiver class). |
1575 // RDI: function which counter needs to be incremented. | 1543 // RDI: function which counter needs to be incremented. |
1576 // RBX: Inline cache data object. | 1544 // RBX: Inline cache data object. |
1577 // TOS(0): Return address. | 1545 // TOS(0): Return address. |
1578 // Inline cache data object structure: | 1546 // Inline cache data object structure: |
1579 // 0: function-name | 1547 // 0: function-name |
1580 // 1: N, number of arguments checked. | 1548 // 1: N, number of arguments checked. |
1581 // 2 .. (length - 1): group of checks, each check containing: | 1549 // 2 .. (length - 1): group of checks, each check containing: |
1582 // - N classes. | 1550 // - N classes. |
1583 // - 1 target function. | 1551 // - 1 target function. |
1584 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1552 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1585 Assembler* assembler) { | 1553 Assembler* assembler) { |
1586 GenerateOptimizedUsageCounterIncrement(assembler); | 1554 GenerateOptimizedUsageCounterIncrement(assembler); |
1587 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1555 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1588 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1556 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1589 Token::kILLEGAL, true /* optimized */); | 1557 Token::kILLEGAL, true /* optimized */); |
1590 } | 1558 } |
1591 | 1559 |
1592 | |
1593 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1560 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
1594 Assembler* assembler) { | 1561 Assembler* assembler) { |
1595 GenerateOptimizedUsageCounterIncrement(assembler); | 1562 GenerateOptimizedUsageCounterIncrement(assembler); |
1596 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1563 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1597 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1564 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1598 Token::kILLEGAL, true /* optimized */); | 1565 Token::kILLEGAL, true /* optimized */); |
1599 } | 1566 } |
1600 | 1567 |
1601 | |
1602 // Intermediary stub between a static call and its target. ICData contains | 1568 // Intermediary stub between a static call and its target. ICData contains |
1603 // the target function and the call count. | 1569 // the target function and the call count. |
1604 // RBX: ICData | 1570 // RBX: ICData |
1605 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1571 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1606 GenerateUsageCounterIncrement(assembler, RCX); | 1572 GenerateUsageCounterIncrement(assembler, RCX); |
1607 #if defined(DEBUG) | 1573 #if defined(DEBUG) |
1608 { | 1574 { |
1609 Label ok; | 1575 Label ok; |
1610 // Check that the IC data array has NumArgsTested() == 0. | 1576 // Check that the IC data array has NumArgsTested() == 0. |
1611 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1577 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1661 __ EnterStubFrame(); | 1627 __ EnterStubFrame(); |
1662 __ pushq(RBX); // Preserve IC data object. | 1628 __ pushq(RBX); // Preserve IC data object. |
1663 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1629 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1664 __ popq(RBX); | 1630 __ popq(RBX); |
1665 __ RestoreCodePointer(); | 1631 __ RestoreCodePointer(); |
1666 __ LeaveStubFrame(); | 1632 __ LeaveStubFrame(); |
1667 __ jmp(&done_stepping, Assembler::kNearJump); | 1633 __ jmp(&done_stepping, Assembler::kNearJump); |
1668 } | 1634 } |
1669 } | 1635 } |
1670 | 1636 |
1671 | |
1672 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1637 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1673 GenerateUsageCounterIncrement(assembler, RCX); | 1638 GenerateUsageCounterIncrement(assembler, RCX); |
1674 GenerateNArgsCheckInlineCacheStub( | 1639 GenerateNArgsCheckInlineCacheStub( |
1675 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1640 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1676 } | 1641 } |
1677 | 1642 |
1678 | |
1679 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1643 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1680 GenerateUsageCounterIncrement(assembler, RCX); | 1644 GenerateUsageCounterIncrement(assembler, RCX); |
1681 GenerateNArgsCheckInlineCacheStub( | 1645 GenerateNArgsCheckInlineCacheStub( |
1682 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); | 1646 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); |
1683 } | 1647 } |
1684 | 1648 |
1685 | |
1686 // Stub for compiling a function and jumping to the compiled code. | 1649 // Stub for compiling a function and jumping to the compiled code. |
1687 // RCX: IC-Data (for methods). | 1650 // RCX: IC-Data (for methods). |
1688 // R10: Arguments descriptor. | 1651 // R10: Arguments descriptor. |
1689 // RAX: Function. | 1652 // RAX: Function. |
1690 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1653 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
1691 __ EnterStubFrame(); | 1654 __ EnterStubFrame(); |
1692 __ pushq(R10); // Preserve arguments descriptor array. | 1655 __ pushq(R10); // Preserve arguments descriptor array. |
1693 __ pushq(RBX); // Preserve IC data object. | 1656 __ pushq(RBX); // Preserve IC data object. |
1694 __ pushq(RAX); // Pass function. | 1657 __ pushq(RAX); // Pass function. |
1695 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); | 1658 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); |
1696 __ popq(RAX); // Restore function. | 1659 __ popq(RAX); // Restore function. |
1697 __ popq(RBX); // Restore IC data array. | 1660 __ popq(RBX); // Restore IC data array. |
1698 __ popq(R10); // Restore arguments descriptor array. | 1661 __ popq(R10); // Restore arguments descriptor array. |
1699 __ LeaveStubFrame(); | 1662 __ LeaveStubFrame(); |
1700 | 1663 |
1701 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 1664 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
1702 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset())); | 1665 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset())); |
1703 __ jmp(RAX); | 1666 __ jmp(RAX); |
1704 } | 1667 } |
1705 | 1668 |
1706 | |
1707 // RBX: Contains an ICData. | 1669 // RBX: Contains an ICData. |
1708 // TOS(0): return address (Dart code). | 1670 // TOS(0): return address (Dart code). |
1709 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { | 1671 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { |
1710 __ EnterStubFrame(); | 1672 __ EnterStubFrame(); |
1711 __ pushq(RBX); // Preserve IC data. | 1673 __ pushq(RBX); // Preserve IC data. |
1712 __ pushq(Immediate(0)); // Result slot. | 1674 __ pushq(Immediate(0)); // Result slot. |
1713 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1675 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1714 __ popq(CODE_REG); // Original stub. | 1676 __ popq(CODE_REG); // Original stub. |
1715 __ popq(RBX); // Restore IC data. | 1677 __ popq(RBX); // Restore IC data. |
1716 __ LeaveStubFrame(); | 1678 __ LeaveStubFrame(); |
1717 | 1679 |
1718 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 1680 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
1719 __ jmp(RAX); // Jump to original stub. | 1681 __ jmp(RAX); // Jump to original stub. |
1720 } | 1682 } |
1721 | 1683 |
1722 | |
1723 // TOS(0): return address (Dart code). | 1684 // TOS(0): return address (Dart code). |
1724 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { | 1685 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { |
1725 __ EnterStubFrame(); | 1686 __ EnterStubFrame(); |
1726 __ pushq(Immediate(0)); // Result slot. | 1687 __ pushq(Immediate(0)); // Result slot. |
1727 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1688 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
1728 __ popq(CODE_REG); // Original stub. | 1689 __ popq(CODE_REG); // Original stub. |
1729 __ LeaveStubFrame(); | 1690 __ LeaveStubFrame(); |
1730 | 1691 |
1731 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 1692 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
1732 __ jmp(RAX); // Jump to original stub. | 1693 __ jmp(RAX); // Jump to original stub. |
1733 } | 1694 } |
1734 | 1695 |
1735 | |
1736 // Called only from unoptimized code. | 1696 // Called only from unoptimized code. |
1737 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1697 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
1738 // Check single stepping. | 1698 // Check single stepping. |
1739 Label stepping, done_stepping; | 1699 Label stepping, done_stepping; |
1740 __ LoadIsolate(RAX); | 1700 __ LoadIsolate(RAX); |
1741 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1701 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
1742 __ cmpq(RAX, Immediate(0)); | 1702 __ cmpq(RAX, Immediate(0)); |
1743 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); | 1703 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
1744 __ Bind(&done_stepping); | 1704 __ Bind(&done_stepping); |
1745 __ ret(); | 1705 __ ret(); |
1746 | 1706 |
1747 __ Bind(&stepping); | 1707 __ Bind(&stepping); |
1748 __ EnterStubFrame(); | 1708 __ EnterStubFrame(); |
1749 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1709 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1750 __ LeaveStubFrame(); | 1710 __ LeaveStubFrame(); |
1751 __ jmp(&done_stepping, Assembler::kNearJump); | 1711 __ jmp(&done_stepping, Assembler::kNearJump); |
1752 } | 1712 } |
1753 | 1713 |
1754 | |
1755 // Used to check class and type arguments. Arguments passed on stack: | 1714 // Used to check class and type arguments. Arguments passed on stack: |
1756 // TOS + 0: return address. | 1715 // TOS + 0: return address. |
1757 // TOS + 1: function type arguments (only if n == 4, can be raw_null). | 1716 // TOS + 1: function type arguments (only if n == 4, can be raw_null). |
1758 // TOS + 2: instantiator type arguments (only if n == 4, can be raw_null). | 1717 // TOS + 2: instantiator type arguments (only if n == 4, can be raw_null). |
1759 // TOS + 3: instance. | 1718 // TOS + 3: instance. |
1760 // TOS + 4: SubtypeTestCache. | 1719 // TOS + 4: SubtypeTestCache. |
1761 // Result in RCX: null -> not found, otherwise result (true or false). | 1720 // Result in RCX: null -> not found, otherwise result (true or false). |
1762 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1721 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
1763 ASSERT((n == 1) || (n == 2) || (n == 4)); | 1722 ASSERT((n == 1) || (n == 2) || (n == 4)); |
1764 const intptr_t kFunctionTypeArgumentsInBytes = 1 * kWordSize; | 1723 const intptr_t kFunctionTypeArgumentsInBytes = 1 * kWordSize; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 // Fall through to not found. | 1795 // Fall through to not found. |
1837 __ Bind(¬_found); | 1796 __ Bind(¬_found); |
1838 __ movq(RCX, R9); | 1797 __ movq(RCX, R9); |
1839 __ ret(); | 1798 __ ret(); |
1840 | 1799 |
1841 __ Bind(&found); | 1800 __ Bind(&found); |
1842 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); | 1801 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); |
1843 __ ret(); | 1802 __ ret(); |
1844 } | 1803 } |
1845 | 1804 |
1846 | |
1847 // Used to check class and type arguments. Arguments passed on stack: | 1805 // Used to check class and type arguments. Arguments passed on stack: |
1848 // TOS + 0: return address. | 1806 // TOS + 0: return address. |
1849 // TOS + 1: raw_null. | 1807 // TOS + 1: raw_null. |
1850 // TOS + 2: raw_null. | 1808 // TOS + 2: raw_null. |
1851 // TOS + 3: instance. | 1809 // TOS + 3: instance. |
1852 // TOS + 4: SubtypeTestCache. | 1810 // TOS + 4: SubtypeTestCache. |
1853 // Result in RCX: null -> not found, otherwise result (true or false). | 1811 // Result in RCX: null -> not found, otherwise result (true or false). |
1854 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { | 1812 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { |
1855 GenerateSubtypeNTestCacheStub(assembler, 1); | 1813 GenerateSubtypeNTestCacheStub(assembler, 1); |
1856 } | 1814 } |
1857 | 1815 |
1858 | |
1859 // Used to check class and type arguments. Arguments passed on stack: | 1816 // Used to check class and type arguments. Arguments passed on stack: |
1860 // TOS + 0: return address. | 1817 // TOS + 0: return address. |
1861 // TOS + 1: raw_null. | 1818 // TOS + 1: raw_null. |
1862 // TOS + 2: raw_null. | 1819 // TOS + 2: raw_null. |
1863 // TOS + 3: instance. | 1820 // TOS + 3: instance. |
1864 // TOS + 4: SubtypeTestCache. | 1821 // TOS + 4: SubtypeTestCache. |
1865 // Result in RCX: null -> not found, otherwise result (true or false). | 1822 // Result in RCX: null -> not found, otherwise result (true or false). |
1866 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { | 1823 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { |
1867 GenerateSubtypeNTestCacheStub(assembler, 2); | 1824 GenerateSubtypeNTestCacheStub(assembler, 2); |
1868 } | 1825 } |
1869 | 1826 |
1870 | |
1871 // Used to check class and type arguments. Arguments passed on stack: | 1827 // Used to check class and type arguments. Arguments passed on stack: |
1872 // TOS + 0: return address. | 1828 // TOS + 0: return address. |
1873 // TOS + 1: function type arguments (can be raw_null). | 1829 // TOS + 1: function type arguments (can be raw_null). |
1874 // TOS + 2: instantiator type arguments (can be raw_null). | 1830 // TOS + 2: instantiator type arguments (can be raw_null). |
1875 // TOS + 3: instance. | 1831 // TOS + 3: instance. |
1876 // TOS + 4: SubtypeTestCache. | 1832 // TOS + 4: SubtypeTestCache. |
1877 // Result in RCX: null -> not found, otherwise result (true or false). | 1833 // Result in RCX: null -> not found, otherwise result (true or false). |
1878 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { | 1834 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { |
1879 GenerateSubtypeNTestCacheStub(assembler, 4); | 1835 GenerateSubtypeNTestCacheStub(assembler, 4); |
1880 } | 1836 } |
1881 | 1837 |
1882 | |
1883 // Return the current stack pointer address, used to stack alignment | 1838 // Return the current stack pointer address, used to stack alignment |
1884 // checks. | 1839 // checks. |
1885 // TOS + 0: return address | 1840 // TOS + 0: return address |
1886 // Result in RAX. | 1841 // Result in RAX. |
1887 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { | 1842 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { |
1888 __ leaq(RAX, Address(RSP, kWordSize)); | 1843 __ leaq(RAX, Address(RSP, kWordSize)); |
1889 __ ret(); | 1844 __ ret(); |
1890 } | 1845 } |
1891 | 1846 |
1892 | |
1893 // Jump to a frame on the call stack. | 1847 // Jump to a frame on the call stack. |
1894 // TOS + 0: return address | 1848 // TOS + 0: return address |
1895 // Arg1: program counter | 1849 // Arg1: program counter |
1896 // Arg2: stack pointer | 1850 // Arg2: stack pointer |
1897 // Arg3: frame_pointer | 1851 // Arg3: frame_pointer |
1898 // Arg4: thread | 1852 // Arg4: thread |
1899 // No Result. | 1853 // No Result. |
1900 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { | 1854 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { |
1901 __ movq(THR, CallingConventions::kArg4Reg); | 1855 __ movq(THR, CallingConventions::kArg4Reg); |
1902 __ movq(RBP, CallingConventions::kArg3Reg); | 1856 __ movq(RBP, CallingConventions::kArg3Reg); |
1903 __ movq(RSP, CallingConventions::kArg2Reg); | 1857 __ movq(RSP, CallingConventions::kArg2Reg); |
1904 // Set the tag. | 1858 // Set the tag. |
1905 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); | 1859 __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId)); |
1906 // Clear top exit frame. | 1860 // Clear top exit frame. |
1907 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); | 1861 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0)); |
1908 // Restore the pool pointer. | 1862 // Restore the pool pointer. |
1909 __ RestoreCodePointer(); | 1863 __ RestoreCodePointer(); |
1910 __ LoadPoolPointer(PP); | 1864 __ LoadPoolPointer(PP); |
1911 __ jmp(CallingConventions::kArg1Reg); // Jump to program counter. | 1865 __ jmp(CallingConventions::kArg1Reg); // Jump to program counter. |
1912 } | 1866 } |
1913 | 1867 |
1914 | |
1915 // Run an exception handler. Execution comes from JumpToFrame stub. | 1868 // Run an exception handler. Execution comes from JumpToFrame stub. |
1916 // | 1869 // |
1917 // The arguments are stored in the Thread object. | 1870 // The arguments are stored in the Thread object. |
1918 // No result. | 1871 // No result. |
1919 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { | 1872 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { |
1920 ASSERT(kExceptionObjectReg == RAX); | 1873 ASSERT(kExceptionObjectReg == RAX); |
1921 ASSERT(kStackTraceObjectReg == RDX); | 1874 ASSERT(kStackTraceObjectReg == RDX); |
1922 __ movq(CallingConventions::kArg1Reg, | 1875 __ movq(CallingConventions::kArg1Reg, |
1923 Address(THR, Thread::resume_pc_offset())); | 1876 Address(THR, Thread::resume_pc_offset())); |
1924 | 1877 |
1925 // Load the exception from the current thread. | 1878 // Load the exception from the current thread. |
1926 Address exception_addr(THR, Thread::active_exception_offset()); | 1879 Address exception_addr(THR, Thread::active_exception_offset()); |
1927 __ movq(kExceptionObjectReg, exception_addr); | 1880 __ movq(kExceptionObjectReg, exception_addr); |
1928 __ movq(exception_addr, Immediate(0)); | 1881 __ movq(exception_addr, Immediate(0)); |
1929 | 1882 |
1930 // Load the stacktrace from the current thread. | 1883 // Load the stacktrace from the current thread. |
1931 Address stacktrace_addr(THR, Thread::active_stacktrace_offset()); | 1884 Address stacktrace_addr(THR, Thread::active_stacktrace_offset()); |
1932 __ movq(kStackTraceObjectReg, stacktrace_addr); | 1885 __ movq(kStackTraceObjectReg, stacktrace_addr); |
1933 __ movq(stacktrace_addr, Immediate(0)); | 1886 __ movq(stacktrace_addr, Immediate(0)); |
1934 | 1887 |
1935 __ jmp(CallingConventions::kArg1Reg); // Jump to continuation point. | 1888 __ jmp(CallingConventions::kArg1Reg); // Jump to continuation point. |
1936 } | 1889 } |
1937 | 1890 |
1938 | |
1939 // Deoptimize a frame on the call stack before rewinding. | 1891 // Deoptimize a frame on the call stack before rewinding. |
1940 // The arguments are stored in the Thread object. | 1892 // The arguments are stored in the Thread object. |
1941 // No result. | 1893 // No result. |
1942 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { | 1894 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { |
1943 // Push zap value instead of CODE_REG. | 1895 // Push zap value instead of CODE_REG. |
1944 __ pushq(Immediate(kZapCodeReg)); | 1896 __ pushq(Immediate(kZapCodeReg)); |
1945 | 1897 |
1946 // Push the deopt pc. | 1898 // Push the deopt pc. |
1947 __ pushq(Address(THR, Thread::resume_pc_offset())); | 1899 __ pushq(Address(THR, Thread::resume_pc_offset())); |
1948 GenerateDeoptimizationSequence(assembler, kEagerDeopt); | 1900 GenerateDeoptimizationSequence(assembler, kEagerDeopt); |
1949 | 1901 |
1950 // After we have deoptimized, jump to the correct frame. | 1902 // After we have deoptimized, jump to the correct frame. |
1951 __ EnterStubFrame(); | 1903 __ EnterStubFrame(); |
1952 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); | 1904 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); |
1953 __ LeaveStubFrame(); | 1905 __ LeaveStubFrame(); |
1954 __ int3(); | 1906 __ int3(); |
1955 } | 1907 } |
1956 | 1908 |
1957 | |
1958 // Calls to the runtime to optimize the given function. | 1909 // Calls to the runtime to optimize the given function. |
1959 // RDI: function to be reoptimized. | 1910 // RDI: function to be reoptimized. |
1960 // R10: argument descriptor (preserved). | 1911 // R10: argument descriptor (preserved). |
1961 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { | 1912 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { |
1962 __ EnterStubFrame(); | 1913 __ EnterStubFrame(); |
1963 __ pushq(R10); // Preserve args descriptor. | 1914 __ pushq(R10); // Preserve args descriptor. |
1964 __ pushq(Immediate(0)); // Result slot. | 1915 __ pushq(Immediate(0)); // Result slot. |
1965 __ pushq(RDI); // Arg0: function to optimize | 1916 __ pushq(RDI); // Arg0: function to optimize |
1966 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); | 1917 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); |
1967 __ popq(RAX); // Discard argument. | 1918 __ popq(RAX); // Discard argument. |
1968 __ popq(RAX); // Get Code object. | 1919 __ popq(RAX); // Get Code object. |
1969 __ popq(R10); // Restore argument descriptor. | 1920 __ popq(R10); // Restore argument descriptor. |
1970 __ LeaveStubFrame(); | 1921 __ LeaveStubFrame(); |
1971 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 1922 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
1972 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 1923 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
1973 __ jmp(RCX); | 1924 __ jmp(RCX); |
1974 __ int3(); | 1925 __ int3(); |
1975 } | 1926 } |
1976 | 1927 |
1977 | |
1978 // Does identical check (object references are equal or not equal) with special | 1928 // Does identical check (object references are equal or not equal) with special |
1979 // checks for boxed numbers. | 1929 // checks for boxed numbers. |
1980 // Left and right are pushed on stack. | 1930 // Left and right are pushed on stack. |
1981 // Return ZF set. | 1931 // Return ZF set. |
1982 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint | 1932 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint |
1983 // cannot contain a value that fits in Mint or Smi. | 1933 // cannot contain a value that fits in Mint or Smi. |
1984 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, | 1934 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, |
1985 const Register left, | 1935 const Register left, |
1986 const Register right) { | 1936 const Register right) { |
1987 Label reference_compare, done, check_mint, check_bigint; | 1937 Label reference_compare, done, check_mint, check_bigint; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2024 // Result in RAX, 0 means equal. | 1974 // Result in RAX, 0 means equal. |
2025 __ LeaveStubFrame(); | 1975 __ LeaveStubFrame(); |
2026 __ cmpq(RAX, Immediate(0)); | 1976 __ cmpq(RAX, Immediate(0)); |
2027 __ jmp(&done); | 1977 __ jmp(&done); |
2028 | 1978 |
2029 __ Bind(&reference_compare); | 1979 __ Bind(&reference_compare); |
2030 __ cmpq(left, right); | 1980 __ cmpq(left, right); |
2031 __ Bind(&done); | 1981 __ Bind(&done); |
2032 } | 1982 } |
2033 | 1983 |
2034 | |
2035 // Called only from unoptimized code. All relevant registers have been saved. | 1984 // Called only from unoptimized code. All relevant registers have been saved. |
2036 // TOS + 0: return address | 1985 // TOS + 0: return address |
2037 // TOS + 1: right argument. | 1986 // TOS + 1: right argument. |
2038 // TOS + 2: left argument. | 1987 // TOS + 2: left argument. |
2039 // Returns ZF set. | 1988 // Returns ZF set. |
2040 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1989 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
2041 Assembler* assembler) { | 1990 Assembler* assembler) { |
2042 // Check single stepping. | 1991 // Check single stepping. |
2043 Label stepping, done_stepping; | 1992 Label stepping, done_stepping; |
2044 if (FLAG_support_debugger) { | 1993 if (FLAG_support_debugger) { |
(...skipping 15 matching lines...) Expand all Loading... |
2060 if (FLAG_support_debugger) { | 2009 if (FLAG_support_debugger) { |
2061 __ Bind(&stepping); | 2010 __ Bind(&stepping); |
2062 __ EnterStubFrame(); | 2011 __ EnterStubFrame(); |
2063 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2012 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2064 __ RestoreCodePointer(); | 2013 __ RestoreCodePointer(); |
2065 __ LeaveStubFrame(); | 2014 __ LeaveStubFrame(); |
2066 __ jmp(&done_stepping); | 2015 __ jmp(&done_stepping); |
2067 } | 2016 } |
2068 } | 2017 } |
2069 | 2018 |
2070 | |
2071 // Called from optimized code only. | 2019 // Called from optimized code only. |
2072 // TOS + 0: return address | 2020 // TOS + 0: return address |
2073 // TOS + 1: right argument. | 2021 // TOS + 1: right argument. |
2074 // TOS + 2: left argument. | 2022 // TOS + 2: left argument. |
2075 // Returns ZF set. | 2023 // Returns ZF set. |
2076 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2024 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
2077 Assembler* assembler) { | 2025 Assembler* assembler) { |
2078 const Register left = RAX; | 2026 const Register left = RAX; |
2079 const Register right = RDX; | 2027 const Register right = RDX; |
2080 | 2028 |
2081 __ movq(left, Address(RSP, 2 * kWordSize)); | 2029 __ movq(left, Address(RSP, 2 * kWordSize)); |
2082 __ movq(right, Address(RSP, 1 * kWordSize)); | 2030 __ movq(right, Address(RSP, 1 * kWordSize)); |
2083 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2031 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2084 __ ret(); | 2032 __ ret(); |
2085 } | 2033 } |
2086 | 2034 |
2087 | |
2088 // Called from megamorphic calls. | 2035 // Called from megamorphic calls. |
2089 // RDI: receiver | 2036 // RDI: receiver |
2090 // RBX: MegamorphicCache (preserved) | 2037 // RBX: MegamorphicCache (preserved) |
2091 // Passed to target: | 2038 // Passed to target: |
2092 // CODE_REG: target Code | 2039 // CODE_REG: target Code |
2093 // R10: arguments descriptor | 2040 // R10: arguments descriptor |
2094 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 2041 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
2095 // Jump if receiver is a smi. | 2042 // Jump if receiver is a smi. |
2096 Label smi_case; | 2043 Label smi_case; |
2097 __ testq(RDI, Immediate(kSmiTagMask)); | 2044 __ testq(RDI, Immediate(kSmiTagMask)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2148 // Try next entry in the table. | 2095 // Try next entry in the table. |
2149 __ AddImmediate(RCX, Immediate(Smi::RawValue(1))); | 2096 __ AddImmediate(RCX, Immediate(Smi::RawValue(1))); |
2150 __ jmp(&loop); | 2097 __ jmp(&loop); |
2151 | 2098 |
2152 // Load cid for the Smi case. | 2099 // Load cid for the Smi case. |
2153 __ Bind(&smi_case); | 2100 __ Bind(&smi_case); |
2154 __ movq(RAX, Immediate(kSmiCid)); | 2101 __ movq(RAX, Immediate(kSmiCid)); |
2155 __ jmp(&cid_loaded); | 2102 __ jmp(&cid_loaded); |
2156 } | 2103 } |
2157 | 2104 |
2158 | |
2159 // Called from switchable IC calls. | 2105 // Called from switchable IC calls. |
2160 // RDI: receiver | 2106 // RDI: receiver |
2161 // RBX: ICData (preserved) | 2107 // RBX: ICData (preserved) |
2162 // Passed to target: | 2108 // Passed to target: |
2163 // CODE_REG: target Code object | 2109 // CODE_REG: target Code object |
2164 // R10: arguments descriptor | 2110 // R10: arguments descriptor |
2165 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { | 2111 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { |
2166 Label loop, found, miss; | 2112 Label loop, found, miss; |
2167 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); | 2113 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); |
2168 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 2114 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
(...skipping 22 matching lines...) Expand all Loading... |
2191 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 2137 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
2192 __ jmp(RCX); | 2138 __ jmp(RCX); |
2193 | 2139 |
2194 __ Bind(&miss); | 2140 __ Bind(&miss); |
2195 __ LoadIsolate(RAX); | 2141 __ LoadIsolate(RAX); |
2196 __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset())); | 2142 __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset())); |
2197 __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2143 __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
2198 __ jmp(RCX); | 2144 __ jmp(RCX); |
2199 } | 2145 } |
2200 | 2146 |
2201 | |
2202 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { | 2147 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { |
2203 Label loop, found, miss; | 2148 Label loop, found, miss; |
2204 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); | 2149 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); |
2205 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 2150 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
2206 __ leaq(R13, FieldAddress(R13, Array::data_offset())); | 2151 __ leaq(R13, FieldAddress(R13, Array::data_offset())); |
2207 // R13: first IC entry | 2152 // R13: first IC entry |
2208 __ LoadTaggedClassIdMayBeSmi(RAX, RDI); | 2153 __ LoadTaggedClassIdMayBeSmi(RAX, RDI); |
2209 // RAX: receiver cid as Smi | 2154 // RAX: receiver cid as Smi |
2210 | 2155 |
2211 __ Bind(&loop); | 2156 __ Bind(&loop); |
(...skipping 16 matching lines...) Expand all Loading... |
2228 __ movq(CODE_REG, Address(R13, code_offset)); | 2173 __ movq(CODE_REG, Address(R13, code_offset)); |
2229 __ jmp(RCX); | 2174 __ jmp(RCX); |
2230 | 2175 |
2231 __ Bind(&miss); | 2176 __ Bind(&miss); |
2232 __ LoadIsolate(RAX); | 2177 __ LoadIsolate(RAX); |
2233 __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset())); | 2178 __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset())); |
2234 __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2179 __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
2235 __ jmp(RCX); | 2180 __ jmp(RCX); |
2236 } | 2181 } |
2237 | 2182 |
2238 | |
2239 // RDI: receiver | 2183 // RDI: receiver |
2240 // RBX: UnlinkedCall | 2184 // RBX: UnlinkedCall |
2241 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { | 2185 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { |
2242 __ EnterStubFrame(); | 2186 __ EnterStubFrame(); |
2243 __ pushq(RDI); // Preserve receiver. | 2187 __ pushq(RDI); // Preserve receiver. |
2244 | 2188 |
2245 __ pushq(Immediate(0)); // Result slot. | 2189 __ pushq(Immediate(0)); // Result slot. |
2246 __ pushq(RDI); // Arg0: Receiver | 2190 __ pushq(RDI); // Arg0: Receiver |
2247 __ pushq(RBX); // Arg1: UnlinkedCall | 2191 __ pushq(RBX); // Arg1: UnlinkedCall |
2248 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2); | 2192 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2); |
2249 __ popq(RBX); | 2193 __ popq(RBX); |
2250 __ popq(RBX); | 2194 __ popq(RBX); |
2251 __ popq(RBX); // result = IC | 2195 __ popq(RBX); // result = IC |
2252 | 2196 |
2253 __ popq(RDI); // Restore receiver. | 2197 __ popq(RDI); // Restore receiver. |
2254 __ LeaveStubFrame(); | 2198 __ LeaveStubFrame(); |
2255 | 2199 |
2256 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2200 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
2257 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2201 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
2258 __ jmp(RCX); | 2202 __ jmp(RCX); |
2259 } | 2203 } |
2260 | 2204 |
2261 | |
2262 // Called from switchable IC calls. | 2205 // Called from switchable IC calls. |
2263 // RDI: receiver | 2206 // RDI: receiver |
2264 // RBX: SingleTargetCache | 2207 // RBX: SingleTargetCache |
2265 // Passed to target:: | 2208 // Passed to target:: |
2266 // CODE_REG: target Code object | 2209 // CODE_REG: target Code object |
2267 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { | 2210 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { |
2268 Label miss; | 2211 Label miss; |
2269 __ LoadClassIdMayBeSmi(RAX, RDI); | 2212 __ LoadClassIdMayBeSmi(RAX, RDI); |
2270 __ movzxw(R9, FieldAddress(RBX, SingleTargetCache::lower_limit_offset())); | 2213 __ movzxw(R9, FieldAddress(RBX, SingleTargetCache::lower_limit_offset())); |
2271 __ movzxw(R10, FieldAddress(RBX, SingleTargetCache::upper_limit_offset())); | 2214 __ movzxw(R10, FieldAddress(RBX, SingleTargetCache::upper_limit_offset())); |
(...skipping 16 matching lines...) Expand all Loading... |
2288 __ popq(RBX); // result = IC | 2231 __ popq(RBX); // result = IC |
2289 | 2232 |
2290 __ popq(RDI); // Restore receiver. | 2233 __ popq(RDI); // Restore receiver. |
2291 __ LeaveStubFrame(); | 2234 __ LeaveStubFrame(); |
2292 | 2235 |
2293 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2236 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
2294 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2237 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
2295 __ jmp(RCX); | 2238 __ jmp(RCX); |
2296 } | 2239 } |
2297 | 2240 |
2298 | |
2299 // Called from the monomorphic checked entry. | 2241 // Called from the monomorphic checked entry. |
2300 // RDI: receiver | 2242 // RDI: receiver |
2301 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { | 2243 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { |
2302 __ movq(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset())); | 2244 __ movq(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset())); |
2303 __ EnterStubFrame(); | 2245 __ EnterStubFrame(); |
2304 __ pushq(RDI); // Preserve receiver. | 2246 __ pushq(RDI); // Preserve receiver. |
2305 | 2247 |
2306 __ pushq(Immediate(0)); // Result slot. | 2248 __ pushq(Immediate(0)); // Result slot. |
2307 __ pushq(RDI); // Arg0: Receiver | 2249 __ pushq(RDI); // Arg0: Receiver |
2308 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1); | 2250 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1); |
2309 __ popq(RBX); | 2251 __ popq(RBX); |
2310 __ popq(RBX); // result = IC | 2252 __ popq(RBX); // result = IC |
2311 | 2253 |
2312 __ popq(RDI); // Restore receiver. | 2254 __ popq(RDI); // Restore receiver. |
2313 __ LeaveStubFrame(); | 2255 __ LeaveStubFrame(); |
2314 | 2256 |
2315 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); | 2257 __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); |
2316 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); | 2258 __ movq(RCX, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); |
2317 __ jmp(RCX); | 2259 __ jmp(RCX); |
2318 } | 2260 } |
2319 | 2261 |
2320 | |
2321 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2262 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
2322 __ int3(); | 2263 __ int3(); |
2323 } | 2264 } |
2324 | 2265 |
2325 | |
2326 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2266 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
2327 __ int3(); | 2267 __ int3(); |
2328 } | 2268 } |
2329 | 2269 |
2330 } // namespace dart | 2270 } // namespace dart |
2331 | 2271 |
2332 #endif // defined TARGET_ARCH_X64 | 2272 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |