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

Side by Side Diff: runtime/vm/stub_code_x64.cc

Issue 1343373003: Revert "VM: New calling convention for generated code." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code_mips.cc ('k') | runtime/vm/thread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 __ subq(RSP, Immediate(sizeof(NativeArguments))); 72 __ subq(RSP, Immediate(sizeof(NativeArguments)));
73 if (OS::ActivationFrameAlignment() > 1) { 73 if (OS::ActivationFrameAlignment() > 1) {
74 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 74 __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
75 } 75 }
76 76
77 // Pass NativeArguments structure by value and call runtime. 77 // Pass NativeArguments structure by value and call runtime.
78 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs. 78 __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs.
79 // There are no runtime calls to closures, so we do not need to set the tag 79 // There are no runtime calls to closures, so we do not need to set the tag
80 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 80 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
81 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments. 81 __ movq(Address(RSP, argc_tag_offset), R10); // Set argc in NativeArguments.
82 // Compute argv. 82 __ leaq(RAX, Address(RBP, R10, TIMES_8, 1 * kWordSize)); // Compute argv.
83 __ leaq(RAX, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
84 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments. 83 __ movq(Address(RSP, argv_offset), RAX); // Set argv in NativeArguments.
85 __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument. 84 __ addq(RAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument.
86 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments. 85 __ movq(Address(RSP, retval_offset), RAX); // Set retval in NativeArguments.
87 #if defined(_WIN64) 86 #if defined(_WIN64)
88 ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit); 87 ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit);
89 __ movq(CallingConventions::kArg1Reg, RSP); 88 __ movq(CallingConventions::kArg1Reg, RSP);
90 #endif 89 #endif
91 __ CallCFunction(RBX); 90 __ CallCFunction(RBX);
92 91
93 // Mark that the isolate is executing Dart code. 92 // Mark that the isolate is executing Dart code.
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 273
275 274
276 // Input parameters: 275 // Input parameters:
277 // R10: arguments descriptor array. 276 // R10: arguments descriptor array.
278 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 277 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
279 __ EnterStubFrame(); 278 __ EnterStubFrame();
280 __ pushq(R10); // Preserve arguments descriptor array. 279 __ pushq(R10); // Preserve arguments descriptor array.
281 // Setup space on stack for return value. 280 // Setup space on stack for return value.
282 __ PushObject(Object::null_object()); 281 __ PushObject(Object::null_object());
283 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 282 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
284 __ popq(CODE_REG); // Get Code object result. 283 __ popq(RAX); // Get Code object result.
285 __ popq(R10); // Restore arguments descriptor array. 284 __ popq(R10); // Restore arguments descriptor array.
286 // Remove the stub frame as we are about to jump to the dart function. 285 // Remove the stub frame as we are about to jump to the dart function.
287 __ LeaveStubFrame(); 286 __ LeaveStubFrame();
288 287
289 __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset())); 288 __ movq(RBX, FieldAddress(RAX, Code::entry_point_offset()));
290 __ jmp(RBX); 289 __ jmp(RBX);
291 } 290 }
292 291
293 292
294 // Called from a static call only when an invalid code has been entered 293 // Called from a static call only when an invalid code has been entered
295 // (invalid because its function was optimized or deoptimized). 294 // (invalid because its function was optimized or deoptimized).
296 // R10: arguments descriptor array. 295 // R10: arguments descriptor array.
297 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 296 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
298 // Load code pointer to this stub from the thread:
299 // The one that is passed in, is not correct - it points to the code object
300 // that needs to be replaced.
301 __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
302 __ EnterStubFrame(); 297 __ EnterStubFrame();
303 __ pushq(R10); // Preserve arguments descriptor array. 298 __ pushq(R10); // Preserve arguments descriptor array.
304 // Setup space on stack for return value. 299 // Setup space on stack for return value.
305 __ PushObject(Object::null_object()); 300 __ PushObject(Object::null_object());
306 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 301 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
307 __ popq(CODE_REG); // Get Code object. 302 __ popq(RAX); // Get Code object.
308 __ popq(R10); // Restore arguments descriptor array. 303 __ popq(R10); // Restore arguments descriptor array.
309 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 304 __ movq(RAX, FieldAddress(RAX, Code::entry_point_offset()));
310 __ LeaveStubFrame(); 305 __ LeaveStubFrame();
311 __ jmp(RAX); 306 __ jmp(RAX);
312 __ int3(); 307 __ int3();
313 } 308 }
314 309
315 310
316 // Called from object allocate instruction when the allocation stub has been 311 // Called from object allocate instruction when the allocation stub has been
317 // disabled. 312 // disabled.
318 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 313 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
319 // Load code pointer to this stub from the thread:
320 // The one that is passed in, is not correct - it points to the code object
321 // that needs to be replaced.
322 __ movq(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
323 __ EnterStubFrame(); 314 __ EnterStubFrame();
324 // Setup space on stack for return value. 315 // Setup space on stack for return value.
325 __ PushObject(Object::null_object()); 316 __ PushObject(Object::null_object());
326 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 317 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
327 __ popq(CODE_REG); // Get Code object. 318 __ popq(RAX); // Get Code object.
328 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 319 __ movq(RAX, FieldAddress(RAX, Code::entry_point_offset()));
329 __ LeaveStubFrame(); 320 __ LeaveStubFrame();
330 __ jmp(RAX); 321 __ jmp(RAX);
331 __ int3(); 322 __ int3();
332 } 323 }
333 324
334 325
335 // Input parameters: 326 // Input parameters:
336 // R10: smi-tagged argument count, may be zero. 327 // R10: smi-tagged argument count, may be zero.
337 // RBP[kParamEndSlotFromFp + 1]: last argument. 328 // RBP[kParamEndSlotFromFp + 1]: last argument.
338 static void PushArgumentsArray(Assembler* assembler) { 329 static void PushArgumentsArray(Assembler* assembler) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 // Stack after EnterDartFrame(0, PP, kNoRegister) below: 372 // Stack after EnterDartFrame(0, PP, kNoRegister) below:
382 // +------------------+ 373 // +------------------+
383 // | Saved PP | <- PP 374 // | Saved PP | <- PP
384 // +------------------+ 375 // +------------------+
385 // | PC marker | <- TOS 376 // | PC marker | <- TOS
386 // +------------------+ 377 // +------------------+
387 // | Saved FP | <- FP of stub 378 // | Saved FP | <- FP of stub
388 // +------------------+ 379 // +------------------+
389 // | return-address | (deoptimization point) 380 // | return-address | (deoptimization point)
390 // +------------------+ 381 // +------------------+
391 // | Saved CODE_REG |
392 // +------------------+
393 // | ... | <- SP of optimized frame 382 // | ... | <- SP of optimized frame
394 // 383 //
395 // Parts of the code cannot GC, part of the code can GC. 384 // Parts of the code cannot GC, part of the code can GC.
396 static void GenerateDeoptimizationSequence(Assembler* assembler, 385 static void GenerateDeoptimizationSequence(Assembler* assembler,
397 DeoptStubKind kind) { 386 bool preserve_result) {
398 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 387 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
399 // is no need to set the correct PC marker or load PP, since they get patched. 388 // is no need to set the correct PC marker or load PP, since they get patched.
400 __ EnterStubFrame(); 389 __ EnterStubFrame();
401 390
402 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry 391 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
403 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. 392 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
404 const intptr_t saved_result_slot_from_fp = 393 const intptr_t saved_result_slot_from_fp =
405 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); 394 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
406 // Result in RAX is preserved as part of pushing all registers below. 395 // Result in RAX is preserved as part of pushing all registers below.
407 396
408 // Push registers in their enumeration order: lowest register number at 397 // Push registers in their enumeration order: lowest register number at
409 // lowest address. 398 // lowest address.
410 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { 399 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
411 if (i == CODE_REG) { 400 __ pushq(static_cast<Register>(i));
412 // Save the original value of CODE_REG pushed before invoking this stub
413 // instead of the value used to call this stub.
414 __ pushq(Address(RBP, 2 * kWordSize));
415 } else {
416 __ pushq(static_cast<Register>(i));
417 }
418 } 401 }
419 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); 402 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
420 intptr_t offset = 0; 403 intptr_t offset = 0;
421 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { 404 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
422 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); 405 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
423 __ movups(Address(RSP, offset), xmm_reg); 406 __ movups(Address(RSP, offset), xmm_reg);
424 offset += kFpuRegisterSize; 407 offset += kFpuRegisterSize;
425 } 408 }
426 409
427 // Pass address of saved registers block. 410 // Pass address of saved registers block.
428 __ movq(CallingConventions::kArg1Reg, RSP); 411 __ movq(CallingConventions::kArg1Reg, RSP);
429 __ movq(CallingConventions::kArg2Reg, Immediate(kind == kLazyDeopt ? 1 : 0));
430 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call. 412 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call.
431 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 413 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
432 // Result (RAX) is stack-size (FP - SP) in bytes. 414 // Result (RAX) is stack-size (FP - SP) in bytes.
433 415
434 const bool preserve_result = (kind == kLazyDeopt);
435 if (preserve_result) { 416 if (preserve_result) {
436 // Restore result into RBX temporarily. 417 // Restore result into RBX temporarily.
437 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); 418 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
438 } 419 }
439 420
440 // There is a Dart Frame on the stack. We must restore PP and leave frame. 421 // There is a Dart Frame on the stack. We must restore PP and leave frame.
441 __ RestoreCodePointer();
442 __ LeaveStubFrame(); 422 __ LeaveStubFrame();
443 423
444 __ popq(RCX); // Preserve return address. 424 __ popq(RCX); // Preserve return address.
445 __ movq(RSP, RBP); // Discard optimized frame. 425 __ movq(RSP, RBP); // Discard optimized frame.
446 __ subq(RSP, RAX); // Reserve space for deoptimized frame. 426 __ subq(RSP, RAX); // Reserve space for deoptimized frame.
447 __ pushq(RCX); // Restore return address. 427 __ pushq(RCX); // Restore return address.
448 428
449 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 429 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
450 // is no need to set the correct PC marker or load PP, since they get patched. 430 // is no need to set the correct PC marker or load PP, since they get patched.
451 __ EnterStubFrame(); 431 __ EnterStubFrame();
452 432
453 if (preserve_result) { 433 if (preserve_result) {
454 __ pushq(RBX); // Preserve result as first local. 434 __ pushq(RBX); // Preserve result as first local.
455 } 435 }
456 __ ReserveAlignedFrameSpace(0); 436 __ ReserveAlignedFrameSpace(0);
457 // Pass last FP as a parameter. 437 // Pass last FP as a parameter.
458 __ movq(CallingConventions::kArg1Reg, RBP); 438 __ movq(CallingConventions::kArg1Reg, RBP);
459 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); 439 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
460 if (preserve_result) { 440 if (preserve_result) {
461 // Restore result into RBX. 441 // Restore result into RBX.
462 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); 442 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
463 } 443 }
464 // Code above cannot cause GC. 444 // Code above cannot cause GC.
465 // There is a Dart Frame on the stack. We must restore PP and leave frame. 445 // There is a Dart Frame on the stack. We must restore PP and leave frame.
466 __ RestoreCodePointer();
467 __ LeaveStubFrame(); 446 __ LeaveStubFrame();
468 447
469 // Frame is fully rewritten at this point and it is safe to perform a GC. 448 // Frame is fully rewritten at this point and it is safe to perform a GC.
470 // Materialize any objects that were deferred by FillFrame because they 449 // Materialize any objects that were deferred by FillFrame because they
471 // require allocation. 450 // require allocation.
472 // Enter stub frame with loading PP. The caller's PP is not materialized yet. 451 // Enter stub frame with loading PP. The caller's PP is not materialized yet.
473 __ EnterStubFrame(); 452 __ EnterStubFrame();
474 if (preserve_result) { 453 if (preserve_result) {
475 __ pushq(RBX); // Preserve result, it will be GC-d here. 454 __ pushq(RBX); // Preserve result, it will be GC-d here.
476 } 455 }
(...skipping 15 matching lines...) Expand all
492 } 471 }
493 472
494 473
495 // TOS: return address + call-instruction-size (5 bytes). 474 // TOS: return address + call-instruction-size (5 bytes).
496 // RAX: result, must be preserved 475 // RAX: result, must be preserved
497 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 476 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
498 // Correct return address to point just after the call that is being 477 // Correct return address to point just after the call that is being
499 // deoptimized. 478 // deoptimized.
500 __ popq(RBX); 479 __ popq(RBX);
501 __ subq(RBX, Immediate(ShortCallPattern::pattern_length_in_bytes())); 480 __ subq(RBX, Immediate(ShortCallPattern::pattern_length_in_bytes()));
502 // Push zap value instead of CODE_REG for lazy deopt.
503 __ pushq(Immediate(0xf1f1f1f1));
504 __ pushq(RBX); 481 __ pushq(RBX);
505 GenerateDeoptimizationSequence(assembler, kLazyDeopt); 482 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX.
506 } 483 }
507 484
508 485
509 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 486 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
510 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 487 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX.
511 } 488 }
512 489
513 490
514 static void GenerateDispatcherCode(Assembler* assembler, 491 static void GenerateDispatcherCode(Assembler* assembler,
515 Label* call_target_function) { 492 Label* call_target_function) {
516 __ Comment("NoSuchMethodDispatch"); 493 __ Comment("NoSuchMethodDispatch");
517 // When lazily generated invocation dispatchers are disabled, the 494 // When lazily generated invocation dispatchers are disabled, the
518 // miss-handler may return null. 495 // miss-handler may return null.
519 __ CompareObject(RAX, Object::null_object()); 496 __ CompareObject(RAX, Object::null_object());
520 __ j(NOT_EQUAL, call_target_function); 497 __ j(NOT_EQUAL, call_target_function);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 __ pushq(RBX); // IC data. 535 __ pushq(RBX); // IC data.
559 __ pushq(R10); // Arguments descriptor. 536 __ pushq(R10); // Arguments descriptor.
560 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 537 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
561 // Discard arguments. 538 // Discard arguments.
562 __ popq(RAX); 539 __ popq(RAX);
563 __ popq(RAX); 540 __ popq(RAX);
564 __ popq(RAX); 541 __ popq(RAX);
565 __ popq(RAX); // Return value from the runtime call (function). 542 __ popq(RAX); // Return value from the runtime call (function).
566 __ popq(R10); // Restore arguments descriptor. 543 __ popq(R10); // Restore arguments descriptor.
567 __ popq(RBX); // Restore IC data. 544 __ popq(RBX); // Restore IC data.
568 __ RestoreCodePointer();
569 __ LeaveStubFrame(); 545 __ LeaveStubFrame();
546
570 if (!FLAG_lazy_dispatchers) { 547 if (!FLAG_lazy_dispatchers) {
571 Label call_target_function; 548 Label call_target_function;
572 GenerateDispatcherCode(assembler, &call_target_function); 549 GenerateDispatcherCode(assembler, &call_target_function);
573 __ Bind(&call_target_function); 550 __ Bind(&call_target_function);
574 } 551 }
575 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); 552
576 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); 553 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
577 __ jmp(RCX); 554 __ jmp(RCX);
578 } 555 }
579 556
580 557
581 // Called for inline allocation of arrays. 558 // Called for inline allocation of arrays.
582 // Input parameters: 559 // Input parameters:
583 // R10 : Array length as Smi. 560 // R10 : Array length as Smi.
584 // RBX : array element type (either NULL or an instantiated type). 561 // RBX : array element type (either NULL or an instantiated type).
585 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. 562 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 __ popq(R10); // Pop array length argument. 686 __ popq(R10); // Pop array length argument.
710 __ popq(RAX); // Pop return value from return slot. 687 __ popq(RAX); // Pop return value from return slot.
711 __ LeaveStubFrame(); 688 __ LeaveStubFrame();
712 __ ret(); 689 __ ret();
713 } 690 }
714 691
715 692
716 // Called when invoking Dart code from C++ (VM code). 693 // Called when invoking Dart code from C++ (VM code).
717 // Input parameters: 694 // Input parameters:
718 // RSP : points to return address. 695 // RSP : points to return address.
719 // RDI : target code 696 // RDI : entrypoint of the Dart function to call.
720 // RSI : arguments descriptor array. 697 // RSI : arguments descriptor array.
721 // RDX : arguments array. 698 // RDX : arguments array.
722 // RCX : current thread. 699 // RCX : current thread.
723 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 700 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
724 // Save frame pointer coming in. 701 // Save frame pointer coming in.
725 __ EnterFrame(0); 702 __ EnterFrame(0);
726 703
727 const Register kTargetCodeReg = CallingConventions::kArg1Reg; 704 const Register kEntryPointReg = CallingConventions::kArg1Reg;
728 const Register kArgDescReg = CallingConventions::kArg2Reg; 705 const Register kArgDescReg = CallingConventions::kArg2Reg;
729 const Register kArgsReg = CallingConventions::kArg3Reg; 706 const Register kArgsReg = CallingConventions::kArg3Reg;
730 const Register kThreadReg = CallingConventions::kArg4Reg; 707 const Register kThreadReg = CallingConventions::kArg4Reg;
731 708
732 // At this point, the stack looks like: 709 // At this point, the stack looks like:
733 // | saved RBP | <-- RBP 710 // | saved RBP | <-- RBP
734 // | saved PC (return to DartEntry::InvokeFunction) | 711 // | saved PC (return to DartEntry::InvokeFunction) |
735 712
736 const intptr_t kInitialOffset = 1; 713 const intptr_t kInitialOffset = 1;
737 // Save arguments descriptor array. 714 // Save arguments descriptor array.
738 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize; 715 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize;
739 __ pushq(kArgDescReg); 716 __ pushq(kArgDescReg);
740 717
741 // Save C++ ABI callee-saved registers. 718 // Save C++ ABI callee-saved registers.
742 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, 719 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
743 CallingConventions::kCalleeSaveXmmRegisters); 720 CallingConventions::kCalleeSaveXmmRegisters);
744 721
722 // We now load the pool pointer(PP) as we are about to invoke dart code and we
723 // could potentially invoke some intrinsic functions which need the PP to be
724 // set up.
725 __ LoadPoolPointer();
726
745 // If any additional (or fewer) values are pushed, the offsets in 727 // If any additional (or fewer) values are pushed, the offsets in
746 // kExitLinkSlotFromEntryFp will need to be changed. 728 // kExitLinkSlotFromEntryFp will need to be changed.
747 729
748 // Set up THR, which caches the current thread in Dart code. 730 // Set up THR, which caches the current thread in Dart code.
749 if (THR != kThreadReg) { 731 if (THR != kThreadReg) {
750 __ movq(THR, kThreadReg); 732 __ movq(THR, kThreadReg);
751 } 733 }
752 // Load Isolate pointer into kIsolateReg. 734 // Load Isolate pointer into kIsolateReg.
753 const Register kIsolateReg = RBX; 735 const Register kIsolateReg = RBX;
754 __ LoadIsolate(kIsolateReg); 736 __ LoadIsolate(kIsolateReg);
(...skipping 25 matching lines...) Expand all
780 __ Stop("kExitLinkSlotFromEntryFp mismatch"); 762 __ Stop("kExitLinkSlotFromEntryFp mismatch");
781 __ Bind(&ok); 763 __ Bind(&ok);
782 } 764 }
783 #endif 765 #endif
784 __ movq(Address(THR, Thread::top_exit_frame_info_offset()), 766 __ movq(Address(THR, Thread::top_exit_frame_info_offset()),
785 Immediate(0)); 767 Immediate(0));
786 768
787 // Load arguments descriptor array into R10, which is passed to Dart code. 769 // Load arguments descriptor array into R10, which is passed to Dart code.
788 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); 770 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
789 771
790 // Push arguments. At this point we only need to preserve kTargetCodeReg. 772 // Push arguments. At this point we only need to preserve kEntryPointReg.
791 ASSERT(kTargetCodeReg != RDX); 773 ASSERT(kEntryPointReg != RDX);
792 774
793 // Load number of arguments into RBX. 775 // Load number of arguments into RBX.
794 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 776 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
795 __ SmiUntag(RBX); 777 __ SmiUntag(RBX);
796 778
797 // Compute address of 'arguments array' data area into RDX. 779 // Compute address of 'arguments array' data area into RDX.
798 __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle)); 780 __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle));
799 __ leaq(RDX, FieldAddress(RDX, Array::data_offset())); 781 __ leaq(RDX, FieldAddress(RDX, Array::data_offset()));
800 782
801 // Set up arguments for the Dart call. 783 // Set up arguments for the Dart call.
802 Label push_arguments; 784 Label push_arguments;
803 Label done_push_arguments; 785 Label done_push_arguments;
804 __ testq(RBX, RBX); // check if there are arguments. 786 __ testq(RBX, RBX); // check if there are arguments.
805 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); 787 __ j(ZERO, &done_push_arguments, Assembler::kNearJump);
806 __ movq(RAX, Immediate(0)); 788 __ movq(RAX, Immediate(0));
807 __ Bind(&push_arguments); 789 __ Bind(&push_arguments);
808 __ pushq(Address(RDX, RAX, TIMES_8, 0)); 790 __ pushq(Address(RDX, RAX, TIMES_8, 0));
809 __ incq(RAX); 791 __ incq(RAX);
810 __ cmpq(RAX, RBX); 792 __ cmpq(RAX, RBX);
811 __ j(LESS, &push_arguments, Assembler::kNearJump); 793 __ j(LESS, &push_arguments, Assembler::kNearJump);
812 __ Bind(&done_push_arguments); 794 __ Bind(&done_push_arguments);
813 795
814 // Call the Dart code entrypoint. 796 // Call the Dart code entrypoint.
815 __ xorq(PP, PP); // GC-safe value into PP. 797 __ call(kEntryPointReg); // R10 is the arguments descriptor array.
816 __ movq(CODE_REG,
817 Address(kTargetCodeReg, VMHandles::kOffsetOfRawPtrInHandle));
818 __ movq(kTargetCodeReg, FieldAddress(CODE_REG, Code::entry_point_offset()));
819 __ call(kTargetCodeReg); // R10 is the arguments descriptor array.
820 798
821 // Read the saved arguments descriptor array to obtain the number of passed 799 // Read the saved arguments descriptor array to obtain the number of passed
822 // arguments. 800 // arguments.
823 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset)); 801 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset));
824 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); 802 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
825 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 803 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
826 // Get rid of arguments pushed on the stack. 804 // Get rid of arguments pushed on the stack.
827 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. 805 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi.
828 806
829 // Restore the saved top exit frame info and top resource back into the 807 // Restore the saved top exit frame info and top resource back into the
(...skipping 16 matching lines...) Expand all
846 __ ret(); 824 __ ret();
847 } 825 }
848 826
849 827
850 // Called for inline allocation of contexts. 828 // Called for inline allocation of contexts.
851 // Input: 829 // Input:
852 // R10: number of context variables. 830 // R10: number of context variables.
853 // Output: 831 // Output:
854 // RAX: new allocated RawContext object. 832 // RAX: new allocated RawContext object.
855 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 833 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
856 __ LoadObject(R9, Object::null_object()); 834 __ LoadObject(R12, Object::null_object());
857 if (FLAG_inline_alloc) { 835 if (FLAG_inline_alloc) {
858 Label slow_case; 836 Label slow_case;
859 // First compute the rounded instance size. 837 // First compute the rounded instance size.
860 // R10: number of context variables. 838 // R10: number of context variables.
861 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); 839 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
862 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); 840 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
863 __ andq(R13, Immediate(-kObjectAlignment)); 841 __ andq(R13, Immediate(-kObjectAlignment));
864 842
865 // Check for allocation tracing. 843 // Check for allocation tracing.
866 __ MaybeTraceAllocation(kContextCid, 844 __ MaybeTraceAllocation(kContextCid,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 // RAX: new object. 908 // RAX: new object.
931 // R10: number of context variables as integer value (not object). 909 // R10: number of context variables as integer value (not object).
932 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); 910 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
933 911
934 // Setup the parent field. 912 // Setup the parent field.
935 // RAX: new object. 913 // RAX: new object.
936 // R10: number of context variables. 914 // R10: number of context variables.
937 // No generational barrier needed, since we are storing null. 915 // No generational barrier needed, since we are storing null.
938 __ InitializeFieldNoBarrier(RAX, 916 __ InitializeFieldNoBarrier(RAX,
939 FieldAddress(RAX, Context::parent_offset()), 917 FieldAddress(RAX, Context::parent_offset()),
940 R9); 918 R12);
941 919
942 // Initialize the context variables. 920 // Initialize the context variables.
943 // RAX: new object. 921 // RAX: new object.
944 // R10: number of context variables. 922 // R10: number of context variables.
945 { 923 {
946 Label loop, entry; 924 Label loop, entry;
947 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); 925 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
948 #if defined(DEBUG) 926 #if defined(DEBUG)
949 static const bool kJumpLength = Assembler::kFarJump; 927 static const bool kJumpLength = Assembler::kFarJump;
950 #else 928 #else
951 static const bool kJumpLength = Assembler::kNearJump; 929 static const bool kJumpLength = Assembler::kNearJump;
952 #endif // DEBUG 930 #endif // DEBUG
953 __ jmp(&entry, kJumpLength); 931 __ jmp(&entry, kJumpLength);
954 __ Bind(&loop); 932 __ Bind(&loop);
955 __ decq(R10); 933 __ decq(R10);
956 // No generational barrier needed, since we are storing null. 934 // No generational barrier needed, since we are storing null.
957 __ InitializeFieldNoBarrier(RAX, 935 __ InitializeFieldNoBarrier(RAX,
958 Address(R13, R10, TIMES_8, 0), 936 Address(R13, R10, TIMES_8, 0),
959 R9); 937 R12);
960 __ Bind(&entry); 938 __ Bind(&entry);
961 __ cmpq(R10, Immediate(0)); 939 __ cmpq(R10, Immediate(0));
962 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 940 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
963 } 941 }
964 942
965 // Done allocating and initializing the context. 943 // Done allocating and initializing the context.
966 // RAX: new object. 944 // RAX: new object.
967 __ ret(); 945 __ ret();
968 946
969 __ Bind(&slow_case); 947 __ Bind(&slow_case);
970 } 948 }
971 // Create a stub frame. 949 // Create a stub frame.
972 __ EnterStubFrame(); 950 __ EnterStubFrame();
973 __ pushq(R9); // Setup space on stack for the return value. 951 __ pushq(R12); // Setup space on stack for the return value.
974 __ SmiTag(R10); 952 __ SmiTag(R10);
975 __ pushq(R10); // Push number of context variables. 953 __ pushq(R10); // Push number of context variables.
976 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. 954 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
977 __ popq(RAX); // Pop number of context variables argument. 955 __ popq(RAX); // Pop number of context variables argument.
978 __ popq(RAX); // Pop the new context object. 956 __ popq(RAX); // Pop the new context object.
979 // RAX: new object 957 // RAX: new object
980 // Restore the frame pointer. 958 // Restore the frame pointer.
981 __ LeaveStubFrame(); 959 __ LeaveStubFrame();
982 __ ret(); 960 __ ret();
983 } 961 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); 1021 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
1044 __ LeaveCallRuntimeFrame(); 1022 __ LeaveCallRuntimeFrame();
1045 __ ret(); 1023 __ ret();
1046 } 1024 }
1047 1025
1048 1026
1049 // Called for inline allocation of objects. 1027 // Called for inline allocation of objects.
1050 // Input parameters: 1028 // Input parameters:
1051 // RSP + 8 : type arguments object (only if class is parameterized). 1029 // RSP + 8 : type arguments object (only if class is parameterized).
1052 // RSP : points to return address. 1030 // RSP : points to return address.
1053 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1031 void StubCode::GenerateAllocationStubForClass(
1054 const Class& cls) { 1032 Assembler* assembler, const Class& cls,
1033 uword* entry_patch_offset, uword* patch_code_pc_offset) {
1034 // Must load pool pointer before being able to patch.
1035 Register new_pp = R13;
1036 __ LoadPoolPointer(new_pp);
1037 *entry_patch_offset = assembler->CodeSize();
1038
1055 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize; 1039 const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
1056 // The generated code is different if the class is parameterized. 1040 // The generated code is different if the class is parameterized.
1057 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1041 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1058 ASSERT(!is_cls_parameterized || 1042 ASSERT(!is_cls_parameterized ||
1059 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1043 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1060 // kInlineInstanceSize is a constant used as a threshold for determining 1044 // kInlineInstanceSize is a constant used as a threshold for determining
1061 // when the object initialization should be done as a loop or as 1045 // when the object initialization should be done as a loop or as
1062 // straight line code. 1046 // straight line code.
1063 const int kInlineInstanceSize = 12; // In words. 1047 const int kInlineInstanceSize = 12; // In words.
1064 const intptr_t instance_size = cls.instance_size(); 1048 const intptr_t instance_size = cls.instance_size();
1065 ASSERT(instance_size > 0); 1049 ASSERT(instance_size > 0);
1066 __ LoadObject(R9, Object::null_object()); 1050 __ LoadObject(R12, Object::null_object());
1067 if (is_cls_parameterized) { 1051 if (is_cls_parameterized) {
1068 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset)); 1052 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
1069 // RDX: instantiated type arguments. 1053 // RDX: instantiated type arguments.
1070 } 1054 }
1071 Isolate* isolate = Isolate::Current(); 1055 Isolate* isolate = Isolate::Current();
1072 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) && 1056 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) &&
1073 !cls.TraceAllocation(isolate)) { 1057 !cls.TraceAllocation(isolate)) {
1074 Label slow_case; 1058 Label slow_case;
1075 // Allocate the object and update top to point to 1059 // Allocate the object and update top to point to
1076 // next object start and initialize the allocated object. 1060 // next object start and initialize the allocated object.
(...skipping 23 matching lines...) Expand all
1100 tags = RawObject::SizeTag::update(instance_size, tags); 1084 tags = RawObject::SizeTag::update(instance_size, tags);
1101 ASSERT(cls.id() != kIllegalCid); 1085 ASSERT(cls.id() != kIllegalCid);
1102 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1086 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1103 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); 1087 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
1104 __ addq(RAX, Immediate(kHeapObjectTag)); 1088 __ addq(RAX, Immediate(kHeapObjectTag));
1105 1089
1106 // Initialize the remaining words of the object. 1090 // Initialize the remaining words of the object.
1107 // RAX: new object (tagged). 1091 // RAX: new object (tagged).
1108 // RBX: next object start. 1092 // RBX: next object start.
1109 // RDX: new object type arguments (if is_cls_parameterized). 1093 // RDX: new object type arguments (if is_cls_parameterized).
1110 // R9: raw null. 1094 // R12: raw null.
1111 // First try inlining the initialization without a loop. 1095 // First try inlining the initialization without a loop.
1112 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1096 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1113 // Check if the object contains any non-header fields. 1097 // Check if the object contains any non-header fields.
1114 // Small objects are initialized using a consecutive set of writes. 1098 // Small objects are initialized using a consecutive set of writes.
1115 for (intptr_t current_offset = Instance::NextFieldOffset(); 1099 for (intptr_t current_offset = Instance::NextFieldOffset();
1116 current_offset < instance_size; 1100 current_offset < instance_size;
1117 current_offset += kWordSize) { 1101 current_offset += kWordSize) {
1118 __ InitializeFieldNoBarrier(RAX, 1102 __ InitializeFieldNoBarrier(RAX,
1119 FieldAddress(RAX, current_offset), 1103 FieldAddress(RAX, current_offset),
1120 R9); 1104 R12);
1121 } 1105 }
1122 } else { 1106 } else {
1123 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); 1107 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset()));
1124 // Loop until the whole object is initialized. 1108 // Loop until the whole object is initialized.
1125 // RAX: new object (tagged). 1109 // RAX: new object (tagged).
1126 // RBX: next object start. 1110 // RBX: next object start.
1127 // RCX: next word to be initialized. 1111 // RCX: next word to be initialized.
1128 // RDX: new object type arguments (if is_cls_parameterized). 1112 // RDX: new object type arguments (if is_cls_parameterized).
1129 Label init_loop; 1113 Label init_loop;
1130 Label done; 1114 Label done;
1131 __ Bind(&init_loop); 1115 __ Bind(&init_loop);
1132 __ cmpq(RCX, RBX); 1116 __ cmpq(RCX, RBX);
1133 #if defined(DEBUG) 1117 #if defined(DEBUG)
1134 static const bool kJumpLength = Assembler::kFarJump; 1118 static const bool kJumpLength = Assembler::kFarJump;
1135 #else 1119 #else
1136 static const bool kJumpLength = Assembler::kNearJump; 1120 static const bool kJumpLength = Assembler::kNearJump;
1137 #endif // DEBUG 1121 #endif // DEBUG
1138 __ j(ABOVE_EQUAL, &done, kJumpLength); 1122 __ j(ABOVE_EQUAL, &done, kJumpLength);
1139 __ InitializeFieldNoBarrier(RAX, Address(RCX, 0), R9); 1123 __ InitializeFieldNoBarrier(RAX, Address(RCX, 0), R12);
1140 __ addq(RCX, Immediate(kWordSize)); 1124 __ addq(RCX, Immediate(kWordSize));
1141 __ jmp(&init_loop, Assembler::kNearJump); 1125 __ jmp(&init_loop, Assembler::kNearJump);
1142 __ Bind(&done); 1126 __ Bind(&done);
1143 } 1127 }
1144 if (is_cls_parameterized) { 1128 if (is_cls_parameterized) {
1145 // RDX: new object type arguments. 1129 // RDX: new object type arguments.
1146 // Set the type arguments in the new object. 1130 // Set the type arguments in the new object.
1147 intptr_t offset = cls.type_arguments_field_offset(); 1131 intptr_t offset = cls.type_arguments_field_offset();
1148 __ InitializeFieldNoBarrier(RAX, FieldAddress(RAX, offset), RDX); 1132 __ InitializeFieldNoBarrier(RAX, FieldAddress(RAX, offset), RDX);
1149 } 1133 }
1150 // Done allocating and initializing the instance. 1134 // Done allocating and initializing the instance.
1151 // RAX: new object (tagged). 1135 // RAX: new object (tagged).
1152 __ ret(); 1136 __ ret();
1153 1137
1154 __ Bind(&slow_case); 1138 __ Bind(&slow_case);
1155 } 1139 }
1156 // If is_cls_parameterized: 1140 // If is_cls_parameterized:
1157 // RDX: new object type arguments. 1141 // RDX: new object type arguments.
1158 // Create a stub frame. 1142 // Create a stub frame.
1159 __ EnterStubFrame(); // Uses PP to access class object. 1143 __ EnterStubFrame(); // Uses PP to access class object.
1160 __ pushq(R9); // Setup space on stack for return value. 1144 __ pushq(R12); // Setup space on stack for return value.
1161 __ PushObject(cls); // Push class of object to be allocated. 1145 __ PushObject(cls); // Push class of object to be allocated.
1162 if (is_cls_parameterized) { 1146 if (is_cls_parameterized) {
1163 __ pushq(RDX); // Push type arguments of object to be allocated. 1147 __ pushq(RDX); // Push type arguments of object to be allocated.
1164 } else { 1148 } else {
1165 __ pushq(R9); // Push null type arguments. 1149 __ pushq(R12); // Push null type arguments.
1166 } 1150 }
1167 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1151 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1168 __ popq(RAX); // Pop argument (type arguments of object). 1152 __ popq(RAX); // Pop argument (type arguments of object).
1169 __ popq(RAX); // Pop argument (class of object). 1153 __ popq(RAX); // Pop argument (class of object).
1170 __ popq(RAX); // Pop result (newly allocated object). 1154 __ popq(RAX); // Pop result (newly allocated object).
1171 // RAX: new object 1155 // RAX: new object
1172 // Restore the frame pointer. 1156 // Restore the frame pointer.
1173 __ LeaveStubFrame(); 1157 __ LeaveStubFrame();
1174 __ ret(); 1158 __ ret();
1159 *patch_code_pc_offset = assembler->CodeSize();
1160 __ JmpPatchable(*StubCode::FixAllocationStubTarget_entry(), new_pp);
1175 } 1161 }
1176 1162
1177 1163
1178 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function 1164 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
1179 // from the entry code of a dart function after an error in passed argument 1165 // from the entry code of a dart function after an error in passed argument
1180 // name or number is detected. 1166 // name or number is detected.
1181 // Input parameters: 1167 // Input parameters:
1182 // RSP : points to return address. 1168 // RSP : points to return address.
1183 // RSP + 8 : address of last argument. 1169 // RSP + 8 : address of last argument.
1184 // R10 : arguments descriptor array. 1170 // R10 : arguments descriptor array.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 Label* not_smi_or_overflow, 1236 Label* not_smi_or_overflow,
1251 bool should_update_result_range) { 1237 bool should_update_result_range) {
1252 __ Comment("Fast Smi op"); 1238 __ Comment("Fast Smi op");
1253 if (FLAG_throw_on_javascript_int_overflow) { 1239 if (FLAG_throw_on_javascript_int_overflow) {
1254 // The overflow check is more complex than implemented below. 1240 // The overflow check is more complex than implemented below.
1255 return; 1241 return;
1256 } 1242 }
1257 ASSERT(num_args == 2); 1243 ASSERT(num_args == 2);
1258 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right 1244 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right
1259 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. 1245 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left.
1260 __ movq(R13, RCX); 1246 __ movq(R12, RCX);
1261 __ orq(R13, RAX); 1247 __ orq(R12, RAX);
1262 __ testq(R13, Immediate(kSmiTagMask)); 1248 __ testq(R12, Immediate(kSmiTagMask));
1263 __ j(NOT_ZERO, not_smi_or_overflow); 1249 __ j(NOT_ZERO, not_smi_or_overflow);
1264 switch (kind) { 1250 switch (kind) {
1265 case Token::kADD: { 1251 case Token::kADD: {
1266 __ addq(RAX, RCX); 1252 __ addq(RAX, RCX);
1267 __ j(OVERFLOW, not_smi_or_overflow); 1253 __ j(OVERFLOW, not_smi_or_overflow);
1268 break; 1254 break;
1269 } 1255 }
1270 case Token::kSUB: { 1256 case Token::kSUB: {
1271 __ subq(RAX, RCX); 1257 __ subq(RAX, RCX);
1272 __ j(OVERFLOW, not_smi_or_overflow); 1258 __ j(OVERFLOW, not_smi_or_overflow);
(...skipping 15 matching lines...) Expand all
1288 1274
1289 1275
1290 if (should_update_result_range) { 1276 if (should_update_result_range) {
1291 Label done; 1277 Label done;
1292 __ movq(RSI, RAX); 1278 __ movq(RSI, RAX);
1293 __ UpdateRangeFeedback(RSI, 2, RBX, RCX, &done); 1279 __ UpdateRangeFeedback(RSI, 2, RBX, RCX, &done);
1294 __ Bind(&done); 1280 __ Bind(&done);
1295 } 1281 }
1296 1282
1297 // RBX: IC data object (preserved). 1283 // RBX: IC data object (preserved).
1298 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); 1284 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1299 // R13: ic_data_array with check entries: classes and target functions. 1285 // R12: ic_data_array with check entries: classes and target functions.
1300 __ leaq(R13, FieldAddress(R13, Array::data_offset())); 1286 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1301 // R13: points directly to the first ic data array element. 1287 // R12: points directly to the first ic data array element.
1302 #if defined(DEBUG) 1288 #if defined(DEBUG)
1303 // Check that first entry is for Smi/Smi. 1289 // Check that first entry is for Smi/Smi.
1304 Label error, ok; 1290 Label error, ok;
1305 const Immediate& imm_smi_cid = 1291 const Immediate& imm_smi_cid =
1306 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid))); 1292 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
1307 __ cmpq(Address(R13, 0 * kWordSize), imm_smi_cid); 1293 __ cmpq(Address(R12, 0 * kWordSize), imm_smi_cid);
1308 __ j(NOT_EQUAL, &error, Assembler::kNearJump); 1294 __ j(NOT_EQUAL, &error, Assembler::kNearJump);
1309 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid); 1295 __ cmpq(Address(R12, 1 * kWordSize), imm_smi_cid);
1310 __ j(EQUAL, &ok, Assembler::kNearJump); 1296 __ j(EQUAL, &ok, Assembler::kNearJump);
1311 __ Bind(&error); 1297 __ Bind(&error);
1312 __ Stop("Incorrect IC data"); 1298 __ Stop("Incorrect IC data");
1313 __ Bind(&ok); 1299 __ Bind(&ok);
1314 #endif 1300 #endif
1315 1301
1316 if (FLAG_optimization_counter_threshold >= 0) { 1302 if (FLAG_optimization_counter_threshold >= 0) {
1317 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1303 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1318 // Update counter. 1304 // Update counter.
1319 __ movq(R8, Address(R13, count_offset)); 1305 __ movq(R8, Address(R12, count_offset));
1320 __ addq(R8, Immediate(Smi::RawValue(1))); 1306 __ addq(R8, Immediate(Smi::RawValue(1)));
1321 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); 1307 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue)));
1322 __ cmovnoq(R9, R8); 1308 __ cmovnoq(R13, R8);
1323 __ StoreIntoSmiField(Address(R13, count_offset), R9); 1309 __ StoreIntoSmiField(Address(R12, count_offset), R13);
1324 } 1310 }
1325 1311
1326 __ ret(); 1312 __ ret();
1327 } 1313 }
1328 1314
1329 1315
1330 // Generate inline cache check for 'num_args'. 1316 // Generate inline cache check for 'num_args'.
1331 // RBX: Inline cache data object. 1317 // RBX: Inline cache data object.
1332 // TOS(0): return address 1318 // TOS(0): return address
1333 // Control flow: 1319 // Control flow:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 range_collection_mode == kCollectRanges); 1375 range_collection_mode == kCollectRanges);
1390 } 1376 }
1391 __ Bind(&not_smi_or_overflow); 1377 __ Bind(&not_smi_or_overflow);
1392 1378
1393 __ Comment("Extract ICData initial values and receiver cid"); 1379 __ Comment("Extract ICData initial values and receiver cid");
1394 // Load arguments descriptor into R10. 1380 // Load arguments descriptor into R10.
1395 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1381 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1396 // Loop that checks if there is an IC data match. 1382 // Loop that checks if there is an IC data match.
1397 Label loop, update, test, found; 1383 Label loop, update, test, found;
1398 // RBX: IC data object (preserved). 1384 // RBX: IC data object (preserved).
1399 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); 1385 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1400 // R13: ic_data_array with check entries: classes and target functions. 1386 // R12: ic_data_array with check entries: classes and target functions.
1401 __ leaq(R13, FieldAddress(R13, Array::data_offset())); 1387 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1402 // R13: points directly to the first ic data array element. 1388 // R12: points directly to the first ic data array element.
1403 1389
1404 // Get the receiver's class ID (first read number of arguments from 1390 // Get the receiver's class ID (first read number of arguments from
1405 // arguments descriptor array and then access the receiver from the stack). 1391 // arguments descriptor array and then access the receiver from the stack).
1406 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1392 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1407 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. 1393 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1408 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1394 __ LoadTaggedClassIdMayBeSmi(RAX, R13);
1409 // RAX: receiver's class ID as smi. 1395 // RAX: receiver's class ID as smi.
1410 __ movq(R9, Address(R13, 0)); // First class ID (Smi) to check. 1396 __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check.
1411 __ jmp(&test); 1397 __ jmp(&test);
1412 1398
1413 __ Comment("ICData loop"); 1399 __ Comment("ICData loop");
1414 __ Bind(&loop); 1400 __ Bind(&loop);
1415 for (int i = 0; i < num_args; i++) { 1401 for (int i = 0; i < num_args; i++) {
1416 if (i > 0) { 1402 if (i > 0) {
1417 // If not the first, load the next argument's class ID. 1403 // If not the first, load the next argument's class ID.
1418 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1404 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1419 __ movq(R9, Address(RSP, RAX, TIMES_4, - i * kWordSize)); 1405 __ movq(R13, Address(RSP, RAX, TIMES_4, - i * kWordSize));
1420 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1406 __ LoadTaggedClassIdMayBeSmi(RAX, R13);
1421 // RAX: next argument class ID (smi). 1407 // RAX: next argument class ID (smi).
1422 __ movq(R9, Address(R13, i * kWordSize)); 1408 __ movq(R13, Address(R12, i * kWordSize));
1423 // R9: next class ID to check (smi). 1409 // R13: next class ID to check (smi).
1424 } 1410 }
1425 __ cmpq(RAX, R9); // Class id match? 1411 __ cmpq(RAX, R13); // Class id match?
1426 if (i < (num_args - 1)) { 1412 if (i < (num_args - 1)) {
1427 __ j(NOT_EQUAL, &update); // Continue. 1413 __ j(NOT_EQUAL, &update); // Continue.
1428 } else { 1414 } else {
1429 // Last check, all checks before matched. 1415 // Last check, all checks before matched.
1430 __ j(EQUAL, &found); // Break. 1416 __ j(EQUAL, &found); // Break.
1431 } 1417 }
1432 } 1418 }
1433 __ Bind(&update); 1419 __ Bind(&update);
1434 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1420 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1435 if (num_args > 1) { 1421 if (num_args > 1) {
1436 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1422 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1437 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); 1423 __ movq(R13, Address(RSP, RAX, TIMES_4, 0));
1438 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1424 __ LoadTaggedClassIdMayBeSmi(RAX, R13);
1439 } 1425 }
1440 1426
1441 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1427 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1442 __ addq(R13, Immediate(entry_size)); // Next entry. 1428 __ addq(R12, Immediate(entry_size)); // Next entry.
1443 __ movq(R9, Address(R13, 0)); // Next class ID. 1429 __ movq(R13, Address(R12, 0)); // Next class ID.
1444 1430
1445 __ Bind(&test); 1431 __ Bind(&test);
1446 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1432 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1447 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1433 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1448 1434
1449 __ Comment("IC miss"); 1435 __ Comment("IC miss");
1450 __ LoadObject(R13, Object::null_object()); 1436 __ LoadObject(R12, Object::null_object());
1451 // Compute address of arguments (first read number of arguments from 1437 // Compute address of arguments (first read number of arguments from
1452 // arguments descriptor array and then compute address on the stack). 1438 // arguments descriptor array and then compute address on the stack).
1453 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1439 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1454 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1440 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1455 __ EnterStubFrame(); 1441 __ EnterStubFrame();
1456 __ pushq(R10); // Preserve arguments descriptor array. 1442 __ pushq(R10); // Preserve arguments descriptor array.
1457 __ pushq(RBX); // Preserve IC data object. 1443 __ pushq(RBX); // Preserve IC data object.
1458 __ pushq(R13); // Setup space on stack for result (target code object). 1444 __ pushq(R12); // Setup space on stack for result (target code object).
1459 // Push call arguments. 1445 // Push call arguments.
1460 for (intptr_t i = 0; i < num_args; i++) { 1446 for (intptr_t i = 0; i < num_args; i++) {
1461 __ movq(RCX, Address(RAX, -kWordSize * i)); 1447 __ movq(RCX, Address(RAX, -kWordSize * i));
1462 __ pushq(RCX); 1448 __ pushq(RCX);
1463 } 1449 }
1464 __ pushq(RBX); // Pass IC data object. 1450 __ pushq(RBX); // Pass IC data object.
1465 __ CallRuntime(handle_ic_miss, num_args + 1); 1451 __ CallRuntime(handle_ic_miss, num_args + 1);
1466 // Remove the call arguments pushed earlier, including the IC data object. 1452 // Remove the call arguments pushed earlier, including the IC data object.
1467 for (intptr_t i = 0; i < num_args + 1; i++) { 1453 for (intptr_t i = 0; i < num_args + 1; i++) {
1468 __ popq(RAX); 1454 __ popq(RAX);
1469 } 1455 }
1470 __ popq(RAX); // Pop returned function object into RAX. 1456 __ popq(RAX); // Pop returned function object into RAX.
1471 __ popq(RBX); // Restore IC data array. 1457 __ popq(RBX); // Restore IC data array.
1472 __ popq(R10); // Restore arguments descriptor array. 1458 __ popq(R10); // Restore arguments descriptor array.
1473 if (range_collection_mode == kCollectRanges) {
1474 __ RestoreCodePointer();
1475 }
1476 __ LeaveStubFrame(); 1459 __ LeaveStubFrame();
1477 Label call_target_function; 1460 Label call_target_function;
1478 if (!FLAG_lazy_dispatchers) { 1461 if (!FLAG_lazy_dispatchers) {
1479 GenerateDispatcherCode(assembler, &call_target_function); 1462 GenerateDispatcherCode(assembler, &call_target_function);
1480 } else { 1463 } else {
1481 __ jmp(&call_target_function); 1464 __ jmp(&call_target_function);
1482 } 1465 }
1483 1466
1484 __ Bind(&found); 1467 __ Bind(&found);
1485 // R13: Pointer to an IC data check group. 1468 // R12: Pointer to an IC data check group.
1486 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1469 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1487 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1470 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1488 __ movq(RAX, Address(R13, target_offset)); 1471 __ movq(RAX, Address(R12, target_offset));
1489 1472
1490 if (FLAG_optimization_counter_threshold >= 0) { 1473 if (FLAG_optimization_counter_threshold >= 0) {
1491 // Update counter. 1474 // Update counter.
1492 __ Comment("Update caller's counter"); 1475 __ Comment("Update caller's counter");
1493 __ movq(R8, Address(R13, count_offset)); 1476 __ movq(R8, Address(R12, count_offset));
1494 __ addq(R8, Immediate(Smi::RawValue(1))); 1477 __ addq(R8, Immediate(Smi::RawValue(1)));
1495 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); 1478 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue)));
1496 __ cmovnoq(R9, R8); 1479 __ cmovnoq(R13, R8);
1497 __ StoreIntoSmiField(Address(R13, count_offset), R9); 1480 __ StoreIntoSmiField(Address(R12, count_offset), R13);
1498 } 1481 }
1499 1482
1500 __ Comment("Call target"); 1483 __ Comment("Call target");
1501 __ Bind(&call_target_function); 1484 __ Bind(&call_target_function);
1502 // RAX: Target function. 1485 // RAX: Target function.
1503 Label is_compiled; 1486 Label is_compiled;
1487 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1504 if (range_collection_mode == kCollectRanges) { 1488 if (range_collection_mode == kCollectRanges) {
1505 __ movq(R13, FieldAddress(RAX, Function::code_offset()));
1506 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1507 __ movq(R8, Address(RSP, + 1 * kWordSize)); 1489 __ movq(R8, Address(RSP, + 1 * kWordSize));
1508 if (num_args == 2) { 1490 if (num_args == 2) {
1509 __ movq(R9, Address(RSP, + 2 * kWordSize)); 1491 __ movq(R13, Address(RSP, + 2 * kWordSize));
1510 } 1492 }
1511 __ EnterStubFrame(); 1493 __ EnterStubFrame();
1512 __ pushq(RBX); 1494 __ pushq(RBX);
1513 if (num_args == 2) { 1495 if (num_args == 2) {
1514 __ pushq(R9); 1496 __ pushq(R13);
1515 } 1497 }
1516 __ pushq(R8); 1498 __ pushq(R8);
1517 __ movq(CODE_REG, R13);
1518 __ call(RCX); 1499 __ call(RCX);
1519 1500
1520 Label done; 1501 Label done;
1521 __ movq(RDX, RAX); 1502 __ movq(RDX, RAX);
1522 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); 1503 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
1523 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done); 1504 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done);
1524 __ Bind(&done); 1505 __ Bind(&done);
1525 __ LeaveStubFrame(); 1506 __ LeaveStubFrame();
1526 __ ret(); 1507 __ ret();
1527 } else { 1508 } else {
1528 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1529 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1530 __ jmp(RCX); 1509 __ jmp(RCX);
1531 } 1510 }
1532 1511
1533 if (FLAG_support_debugger && !optimized) { 1512 if (FLAG_support_debugger && !optimized) {
1534 __ Bind(&stepping); 1513 __ Bind(&stepping);
1535 __ EnterStubFrame(); 1514 __ EnterStubFrame();
1536 __ pushq(RBX); 1515 __ pushq(RBX);
1537 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1516 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1538 __ popq(RBX); 1517 __ popq(RBX);
1539 __ RestoreCodePointer();
1540 __ LeaveStubFrame(); 1518 __ LeaveStubFrame();
1541 __ jmp(&done_stepping); 1519 __ jmp(&done_stepping);
1542 } 1520 }
1543 } 1521 }
1544 1522
1545 1523
1546 // Use inline cache data array to invoke the target or continue in inline 1524 // Use inline cache data array to invoke the target or continue in inline
1547 // cache miss handler. Stub for 1-argument check (receiver class). 1525 // cache miss handler. Stub for 1-argument check (receiver class).
1548 // RBX: Inline cache data object. 1526 // RBX: Inline cache data object.
1549 // TOS(0): Return address. 1527 // TOS(0): Return address.
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); 1676 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue)));
1699 __ cmovnoq(R13, R8); 1677 __ cmovnoq(R13, R8);
1700 __ StoreIntoSmiField(Address(R12, count_offset), R13); 1678 __ StoreIntoSmiField(Address(R12, count_offset), R13);
1701 } 1679 }
1702 1680
1703 // Load arguments descriptor into R10. 1681 // Load arguments descriptor into R10.
1704 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1682 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1705 1683
1706 // Get function and call it, if possible. 1684 // Get function and call it, if possible.
1707 __ movq(RAX, Address(R12, target_offset)); 1685 __ movq(RAX, Address(R12, target_offset));
1708 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1709 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); 1686 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1710 __ jmp(RCX); 1687 __ jmp(RCX);
1711 1688
1712 if (FLAG_support_debugger) { 1689 if (FLAG_support_debugger) {
1713 __ Bind(&stepping); 1690 __ Bind(&stepping);
1714 __ EnterStubFrame(); 1691 __ EnterStubFrame();
1715 __ pushq(RBX); // Preserve IC data object. 1692 __ pushq(RBX); // Preserve IC data object.
1716 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1693 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1717 __ popq(RBX); 1694 __ popq(RBX);
1718 __ RestoreCodePointer();
1719 __ LeaveStubFrame(); 1695 __ LeaveStubFrame();
1720 __ jmp(&done_stepping, Assembler::kNearJump); 1696 __ jmp(&done_stepping, Assembler::kNearJump);
1721 } 1697 }
1722 } 1698 }
1723 1699
1724 1700
1725 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1701 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1726 GenerateUsageCounterIncrement(assembler, RCX); 1702 GenerateUsageCounterIncrement(assembler, RCX);
1727 GenerateNArgsCheckInlineCacheStub( 1703 GenerateNArgsCheckInlineCacheStub(
1728 assembler, 1704 assembler,
(...skipping 22 matching lines...) Expand all
1751 __ EnterStubFrame(); 1727 __ EnterStubFrame();
1752 __ pushq(R10); // Preserve arguments descriptor array. 1728 __ pushq(R10); // Preserve arguments descriptor array.
1753 __ pushq(RBX); // Preserve IC data object. 1729 __ pushq(RBX); // Preserve IC data object.
1754 __ pushq(RAX); // Pass function. 1730 __ pushq(RAX); // Pass function.
1755 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1731 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1756 __ popq(RAX); // Restore function. 1732 __ popq(RAX); // Restore function.
1757 __ popq(RBX); // Restore IC data array. 1733 __ popq(RBX); // Restore IC data array.
1758 __ popq(R10); // Restore arguments descriptor array. 1734 __ popq(R10); // Restore arguments descriptor array.
1759 __ LeaveStubFrame(); 1735 __ LeaveStubFrame();
1760 1736
1761 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1762 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset())); 1737 __ movq(RAX, FieldAddress(RAX, Function::entry_point_offset()));
1763 __ jmp(RAX); 1738 __ jmp(RAX);
1764 } 1739 }
1765 1740
1766 1741
1767 // RBX: Contains an ICData. 1742 // RBX: Contains an ICData.
1768 // TOS(0): return address (Dart code). 1743 // TOS(0): return address (Dart code).
1769 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1744 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1770 __ EnterStubFrame(); 1745 __ EnterStubFrame();
1771 // Preserve IC data. 1746 // Preserve IC data.
1772 __ pushq(RBX); 1747 __ pushq(RBX);
1773 // Room for result. Debugger stub returns address of the 1748 // Room for result. Debugger stub returns address of the
1774 // unpatched runtime stub. 1749 // unpatched runtime stub.
1775 __ LoadObject(R12, Object::null_object()); 1750 __ LoadObject(R12, Object::null_object());
1776 __ pushq(R12); // Room for result. 1751 __ pushq(R12); // Room for result.
1777 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1752 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1778 __ popq(CODE_REG); // Address of original. 1753 __ popq(RAX); // Address of original.
1779 __ popq(RBX); // Restore IC data. 1754 __ popq(RBX); // Restore IC data.
1780 __ LeaveStubFrame(); 1755 __ LeaveStubFrame();
1781
1782 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
1783 __ jmp(RAX); // Jump to original stub. 1756 __ jmp(RAX); // Jump to original stub.
1784 } 1757 }
1785 1758
1786 1759
1787 // TOS(0): return address (Dart code). 1760 // TOS(0): return address (Dart code).
1788 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1761 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1789 __ EnterStubFrame(); 1762 __ EnterStubFrame();
1790 // Room for result. Debugger stub returns address of the 1763 // Room for result. Debugger stub returns address of the
1791 // unpatched runtime stub. 1764 // unpatched runtime stub.
1792 __ LoadObject(R12, Object::null_object()); 1765 __ LoadObject(R12, Object::null_object());
1793 __ pushq(R12); // Room for result. 1766 __ pushq(R12); // Room for result.
1794 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1767 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1795 __ popq(CODE_REG); // Address of original. 1768 __ popq(RAX); // Address of original.
1796 __ LeaveStubFrame(); 1769 __ LeaveStubFrame();
1797
1798 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
1799 __ jmp(RAX); // Jump to original stub. 1770 __ jmp(RAX); // Jump to original stub.
1800 } 1771 }
1801 1772
1802 1773
1803 // Called only from unoptimized code. 1774 // Called only from unoptimized code.
1804 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { 1775 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
1805 // Check single stepping. 1776 // Check single stepping.
1806 Label stepping, done_stepping; 1777 Label stepping, done_stepping;
1807 __ LoadIsolate(RAX); 1778 __ LoadIsolate(RAX);
1808 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); 1779 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
(...skipping 15 matching lines...) Expand all
1824 // TOS + 1: instantiator type arguments (can be NULL). 1795 // TOS + 1: instantiator type arguments (can be NULL).
1825 // TOS + 2: instance. 1796 // TOS + 2: instance.
1826 // TOS + 3: SubtypeTestCache. 1797 // TOS + 3: SubtypeTestCache.
1827 // Result in RCX: null -> not found, otherwise result (true or false). 1798 // Result in RCX: null -> not found, otherwise result (true or false).
1828 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1799 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1829 ASSERT((1 <= n) && (n <= 3)); 1800 ASSERT((1 <= n) && (n <= 3));
1830 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; 1801 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize;
1831 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; 1802 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
1832 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1803 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1833 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); 1804 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes));
1834 __ LoadObject(R9, Object::null_object()); 1805 __ LoadObject(R12, Object::null_object());
1835 if (n > 1) { 1806 if (n > 1) {
1836 __ LoadClass(R10, RAX); 1807 __ LoadClass(R10, RAX);
1837 // Compute instance type arguments into R13. 1808 // Compute instance type arguments into R13.
1838 Label has_no_type_arguments; 1809 Label has_no_type_arguments;
1839 __ movq(R13, R9); 1810 __ movq(R13, R12);
1840 __ movl(RDI, FieldAddress(R10, 1811 __ movl(RDI, FieldAddress(R10,
1841 Class::type_arguments_field_offset_in_words_offset())); 1812 Class::type_arguments_field_offset_in_words_offset()));
1842 __ cmpl(RDI, Immediate(Class::kNoTypeArguments)); 1813 __ cmpl(RDI, Immediate(Class::kNoTypeArguments));
1843 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1814 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
1844 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); 1815 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0));
1845 __ Bind(&has_no_type_arguments); 1816 __ Bind(&has_no_type_arguments);
1846 } 1817 }
1847 __ LoadClassId(R10, RAX); 1818 __ LoadClassId(R10, RAX);
1848 // RAX: instance, R10: instance class id. 1819 // RAX: instance, R10: instance class id.
1849 // R13: instance type arguments or null, used only if n > 1. 1820 // R13: instance type arguments or null, used only if n > 1.
1850 __ movq(RDX, Address(RSP, kCacheOffsetInBytes)); 1821 __ movq(RDX, Address(RSP, kCacheOffsetInBytes));
1851 // RDX: SubtypeTestCache. 1822 // RDX: SubtypeTestCache.
1852 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset())); 1823 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset()));
1853 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1824 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag));
1854 // RDX: Entry start. 1825 // RDX: Entry start.
1855 // R10: instance class id. 1826 // R10: instance class id.
1856 // R13: instance type arguments. 1827 // R13: instance type arguments.
1857 Label loop, found, not_found, next_iteration; 1828 Label loop, found, not_found, next_iteration;
1858 __ SmiTag(R10); 1829 __ SmiTag(R10);
1859 __ Bind(&loop); 1830 __ Bind(&loop);
1860 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId)); 1831 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId));
1861 __ cmpq(RDI, R9); 1832 __ cmpq(RDI, R12);
1862 __ j(EQUAL, &not_found, Assembler::kNearJump); 1833 __ j(EQUAL, &not_found, Assembler::kNearJump);
1863 __ cmpq(RDI, R10); 1834 __ cmpq(RDI, R10);
1864 if (n == 1) { 1835 if (n == 1) {
1865 __ j(EQUAL, &found, Assembler::kNearJump); 1836 __ j(EQUAL, &found, Assembler::kNearJump);
1866 } else { 1837 } else {
1867 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1838 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1868 __ movq(RDI, 1839 __ movq(RDI,
1869 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1840 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1870 __ cmpq(RDI, R13); 1841 __ cmpq(RDI, R13);
1871 if (n == 2) { 1842 if (n == 2) {
1872 __ j(EQUAL, &found, Assembler::kNearJump); 1843 __ j(EQUAL, &found, Assembler::kNearJump);
1873 } else { 1844 } else {
1874 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1845 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1875 __ movq(RDI, 1846 __ movq(RDI,
1876 Address(RDX, 1847 Address(RDX,
1877 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments)); 1848 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments));
1878 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes)); 1849 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes));
1879 __ j(EQUAL, &found, Assembler::kNearJump); 1850 __ j(EQUAL, &found, Assembler::kNearJump);
1880 } 1851 }
1881 } 1852 }
1882 1853
1883 __ Bind(&next_iteration); 1854 __ Bind(&next_iteration);
1884 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1855 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1885 __ jmp(&loop, Assembler::kNearJump); 1856 __ jmp(&loop, Assembler::kNearJump);
1886 // Fall through to not found. 1857 // Fall through to not found.
1887 __ Bind(&not_found); 1858 __ Bind(&not_found);
1888 __ movq(RCX, R9); 1859 __ movq(RCX, R12);
1889 __ ret(); 1860 __ ret();
1890 1861
1891 __ Bind(&found); 1862 __ Bind(&found);
1892 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); 1863 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult));
1893 __ ret(); 1864 __ ret();
1894 } 1865 }
1895 1866
1896 1867
1897 // Used to check class and type arguments. Arguments passed on stack: 1868 // Used to check class and type arguments. Arguments passed on stack:
1898 // TOS + 0: return address. 1869 // TOS + 0: return address.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1981 // RDI: function to be reoptimized. 1952 // RDI: function to be reoptimized.
1982 // R10: argument descriptor (preserved). 1953 // R10: argument descriptor (preserved).
1983 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1954 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1984 __ EnterStubFrame(); 1955 __ EnterStubFrame();
1985 __ LoadObject(R12, Object::null_object()); 1956 __ LoadObject(R12, Object::null_object());
1986 __ pushq(R10); 1957 __ pushq(R10);
1987 __ pushq(R12); // Setup space on stack for return value. 1958 __ pushq(R12); // Setup space on stack for return value.
1988 __ pushq(RDI); 1959 __ pushq(RDI);
1989 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1960 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1990 __ popq(RAX); // Disard argument. 1961 __ popq(RAX); // Disard argument.
1991 __ popq(CODE_REG); // Get Code object. 1962 __ popq(RAX); // Get Code object.
1992 __ popq(R10); // Restore argument descriptor. 1963 __ popq(R10); // Restore argument descriptor.
1993 __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset())); 1964 __ movq(RAX, FieldAddress(RAX, Code::entry_point_offset()));
1994 __ LeaveStubFrame(); 1965 __ LeaveStubFrame();
1995 __ jmp(RAX); 1966 __ jmp(RAX);
1996 __ int3(); 1967 __ int3();
1997 } 1968 }
1998 1969
1999 1970
2000 // Does identical check (object references are equal or not equal) with special 1971 // Does identical check (object references are equal or not equal) with special
2001 // checks for boxed numbers. 1972 // checks for boxed numbers.
2002 // Left and right are pushed on stack. 1973 // Left and right are pushed on stack.
2003 // Return ZF set. 1974 // Return ZF set.
2004 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 1975 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
2005 // cannot contain a value that fits in Mint or Smi. 1976 // cannot contain a value that fits in Mint or Smi.
2006 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, 1977 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
2007 const Register left, 1978 const Register left,
2008 const Register right) { 1979 const Register right) {
2009 Label reference_compare, done, check_mint, check_bigint; 1980 Label reference_compare, done, check_mint, check_bigint;
2010 // If any of the arguments is Smi do reference compare. 1981 // If any of the arguments is Smi do reference compare.
2011 __ testq(left, Immediate(kSmiTagMask)); 1982 __ testq(left, Immediate(kSmiTagMask));
2012 __ j(ZERO, &reference_compare); 1983 __ j(ZERO, &reference_compare);
2013 __ testq(right, Immediate(kSmiTagMask)); 1984 __ testq(right, Immediate(kSmiTagMask));
2014 __ j(ZERO, &reference_compare); 1985 __ j(ZERO, &reference_compare);
2015 1986
2016 // Value compare for two doubles. 1987 // Value compare for two doubles.
2017 __ CompareClassId(left, kDoubleCid); 1988 __ CompareClassId(left, kDoubleCid);
2018 __ j(NOT_EQUAL, &check_mint, Assembler::kNearJump); 1989 __ j(NOT_EQUAL, &check_mint, Assembler::kNearJump);
2019 __ CompareClassId(right, kDoubleCid); 1990 __ CompareClassId(right, kDoubleCid);
2020 __ j(NOT_EQUAL, &done, Assembler::kFarJump); 1991 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
2021 1992
2022 // Double values bitwise compare. 1993 // Double values bitwise compare.
2023 __ movq(left, FieldAddress(left, Double::value_offset())); 1994 __ movq(left, FieldAddress(left, Double::value_offset()));
2024 __ cmpq(left, FieldAddress(right, Double::value_offset())); 1995 __ cmpq(left, FieldAddress(right, Double::value_offset()));
2025 __ jmp(&done, Assembler::kFarJump); 1996 __ jmp(&done, Assembler::kNearJump);
2026 1997
2027 __ Bind(&check_mint); 1998 __ Bind(&check_mint);
2028 __ CompareClassId(left, kMintCid); 1999 __ CompareClassId(left, kMintCid);
2029 __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump); 2000 __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump);
2030 __ CompareClassId(right, kMintCid); 2001 __ CompareClassId(right, kMintCid);
2031 __ j(NOT_EQUAL, &done, Assembler::kFarJump); 2002 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
2032 __ movq(left, FieldAddress(left, Mint::value_offset())); 2003 __ movq(left, FieldAddress(left, Mint::value_offset()));
2033 __ cmpq(left, FieldAddress(right, Mint::value_offset())); 2004 __ cmpq(left, FieldAddress(right, Mint::value_offset()));
2034 __ jmp(&done, Assembler::kFarJump); 2005 __ jmp(&done, Assembler::kNearJump);
2035 2006
2036 __ Bind(&check_bigint); 2007 __ Bind(&check_bigint);
2037 __ CompareClassId(left, kBigintCid); 2008 __ CompareClassId(left, kBigintCid);
2038 __ j(NOT_EQUAL, &reference_compare, Assembler::kFarJump); 2009 __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
2039 __ CompareClassId(right, kBigintCid); 2010 __ CompareClassId(right, kBigintCid);
2040 __ j(NOT_EQUAL, &done, Assembler::kFarJump); 2011 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
2041 __ EnterStubFrame(); 2012 __ EnterStubFrame();
2042 __ ReserveAlignedFrameSpace(0); 2013 __ ReserveAlignedFrameSpace(0);
2043 __ movq(CallingConventions::kArg1Reg, left); 2014 __ movq(CallingConventions::kArg1Reg, left);
2044 __ movq(CallingConventions::kArg2Reg, right); 2015 __ movq(CallingConventions::kArg2Reg, right);
2045 __ CallRuntime(kBigintCompareRuntimeEntry, 2); 2016 __ CallRuntime(kBigintCompareRuntimeEntry, 2);
2046 // Result in RAX, 0 means equal. 2017 // Result in RAX, 0 means equal.
2047 __ LeaveStubFrame(); 2018 __ LeaveStubFrame();
2048 __ cmpq(RAX, Immediate(0)); 2019 __ cmpq(RAX, Immediate(0));
2049 __ jmp(&done); 2020 __ jmp(&done);
2050 2021
(...skipping 25 matching lines...) Expand all
2076 2047
2077 __ movq(left, Address(RSP, 2 * kWordSize)); 2048 __ movq(left, Address(RSP, 2 * kWordSize));
2078 __ movq(right, Address(RSP, 1 * kWordSize)); 2049 __ movq(right, Address(RSP, 1 * kWordSize));
2079 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 2050 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
2080 __ ret(); 2051 __ ret();
2081 2052
2082 if (FLAG_support_debugger) { 2053 if (FLAG_support_debugger) {
2083 __ Bind(&stepping); 2054 __ Bind(&stepping);
2084 __ EnterStubFrame(); 2055 __ EnterStubFrame();
2085 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 2056 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2086 __ RestoreCodePointer();
2087 __ LeaveStubFrame(); 2057 __ LeaveStubFrame();
2088 __ jmp(&done_stepping); 2058 __ jmp(&done_stepping);
2089 } 2059 }
2090 } 2060 }
2091 2061
2092 2062
2093 // Called from optimized code only. 2063 // Called from optimized code only.
2094 // TOS + 0: return address 2064 // TOS + 0: return address
2095 // TOS + 1: right argument. 2065 // TOS + 1: right argument.
2096 // TOS + 2: left argument. 2066 // TOS + 2: left argument.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 __ j(ZERO, &call_target_function, Assembler::kNearJump); 2104 __ j(ZERO, &call_target_function, Assembler::kNearJump);
2135 __ cmpq(RDX, RAX); 2105 __ cmpq(RDX, RAX);
2136 __ j(NOT_EQUAL, &update, Assembler::kNearJump); 2106 __ j(NOT_EQUAL, &update, Assembler::kNearJump);
2137 2107
2138 __ Bind(&call_target_function); 2108 __ Bind(&call_target_function);
2139 // Call the target found in the cache. For a class id match, this is a 2109 // Call the target found in the cache. For a class id match, this is a
2140 // proper target for the given name and arguments descriptor. If the 2110 // proper target for the given name and arguments descriptor. If the
2141 // illegal class id was found, the target is a cache miss handler that can 2111 // illegal class id was found, the target is a cache miss handler that can
2142 // be invoked as a normal Dart function. 2112 // be invoked as a normal Dart function.
2143 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); 2113 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
2144 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
2145 __ movq(target, FieldAddress(RAX, Function::entry_point_offset())); 2114 __ movq(target, FieldAddress(RAX, Function::entry_point_offset()));
2146 } 2115 }
2147 2116
2148 2117
2149 // Called from megamorphic calls. 2118 // Called from megamorphic calls.
2150 // RDI: receiver. 2119 // RDI: receiver.
2151 // RBX: lookup cache. 2120 // RBX: lookup cache.
2152 // Result: 2121 // Result:
2153 // RCX: entry point. 2122 // RCX: entry point.
2154 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { 2123 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
2155 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); 2124 EmitMegamorphicLookup(assembler, RDI, RBX, RCX);
2156 __ ret(); 2125 __ ret();
2157 } 2126 }
2158 2127
2159 } // namespace dart 2128 } // namespace dart
2160 2129
2161 #endif // defined TARGET_ARCH_X64 2130 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_mips.cc ('k') | runtime/vm/thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698