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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
« runtime/vm/code_patcher_x64.cc ('K') | « runtime/vm/stub_code.cc ('k') | no next file » | 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 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 270
271 271
272 // Input parameters: 272 // Input parameters:
273 // R10: arguments descriptor array. 273 // R10: arguments descriptor array.
274 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 274 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
275 __ EnterStubFrame(); 275 __ EnterStubFrame();
276 __ pushq(R10); // Preserve arguments descriptor array. 276 __ pushq(R10); // Preserve arguments descriptor array.
277 // Setup space on stack for return value. 277 // Setup space on stack for return value.
278 __ PushObject(Object::null_object(), PP); 278 __ PushObject(Object::null_object(), PP);
279 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 279 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
280 __ popq(RAX); // Get Code object result. 280 __ popq(CODE_REG); // Get Code object result.
281 __ popq(R10); // Restore arguments descriptor array. 281 __ popq(R10); // Restore arguments descriptor array.
282 // Remove the stub frame as we are about to jump to the dart function. 282 // Remove the stub frame as we are about to jump to the dart function.
283 __ LeaveStubFrame(); 283 __ LeaveStubFrame();
284 284
285 __ movq(RBX, FieldAddress(RAX, Code::instructions_offset())); 285 __ movq(RBX, FieldAddress(CODE_REG, Code::instructions_offset()));
286 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 286 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
287 __ jmp(RBX); 287 __ jmp(RBX);
288 } 288 }
289 289
290 290
291 // Called from a static call only when an invalid code has been entered 291 // Called from a static call only when an invalid code has been entered
292 // (invalid because its function was optimized or deoptimized). 292 // (invalid because its function was optimized or deoptimized).
293 // R10: arguments descriptor array. 293 // R10: arguments descriptor array.
294 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 294 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
295 __ EnterStubFrame(); 295 __ EnterStubFrame();
296 __ pushq(R10); // Preserve arguments descriptor array. 296 __ pushq(R10); // Preserve arguments descriptor array.
297 // Setup space on stack for return value. 297 // Setup space on stack for return value.
298 __ PushObject(Object::null_object(), PP); 298 __ PushObject(Object::null_object(), PP);
299 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 299 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
300 __ popq(RAX); // Get Code object. 300 __ popq(CODE_REG); // Get Code object.
301 __ popq(R10); // Restore arguments descriptor array. 301 __ popq(R10); // Restore arguments descriptor array.
302 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); 302 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
303 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 303 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
304 __ LeaveStubFrame(); 304 __ LeaveStubFrame();
305 __ jmp(RAX); 305 __ jmp(RAX);
306 __ int3(); 306 __ int3();
307 } 307 }
308 308
309 309
310 // Called from object allocate instruction when the allocation stub has been 310 // Called from object allocate instruction when the allocation stub has been
311 // disabled. 311 // disabled.
312 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 312 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
313 __ EnterStubFrame(); 313 __ EnterStubFrame();
314 // Setup space on stack for return value. 314 // Setup space on stack for return value.
315 __ PushObject(Object::null_object(), PP); 315 __ PushObject(Object::null_object(), PP);
316 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 316 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
317 __ popq(RAX); // Get Code object. 317 __ popq(CODE_REG); // Get Code object.
318 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); 318 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
319 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 319 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
320 __ LeaveStubFrame(); 320 __ LeaveStubFrame();
321 __ jmp(RAX); 321 __ jmp(RAX);
322 __ int3(); 322 __ int3();
323 } 323 }
324 324
325 325
326 // Called from array allocate instruction when the allocation stub has been 326 // Called from array allocate instruction when the allocation stub has been
327 // disabled. 327 // disabled.
328 // R10: length (preserved). 328 // R10: length (preserved).
329 // RBX: element type (preserved). 329 // RBX: element type (preserved).
330 void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) { 330 void StubCode::GenerateFixAllocateArrayStubTargetStub(Assembler* assembler) {
331 __ EnterStubFrame(); 331 __ EnterStubFrame();
332 __ pushq(R10); // Preserve length. 332 __ pushq(R10); // Preserve length.
333 __ pushq(RBX); // Preserve element type. 333 __ pushq(RBX); // Preserve element type.
334 // Setup space on stack for return value. 334 // Setup space on stack for return value.
335 __ PushObject(Object::null_object(), PP); 335 __ PushObject(Object::null_object(), PP);
336 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 336 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
337 __ popq(RAX); // Get Code object. 337 __ popq(CODE_REG); // Get Code object.
338 __ popq(RBX); // Restore element type. 338 __ popq(RBX); // Restore element type.
339 __ popq(R10); // Restore length. 339 __ popq(R10); // Restore length.
340 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); 340 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
341 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 341 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
342 __ LeaveStubFrame(); 342 __ LeaveStubFrame();
343 __ jmp(RAX); 343 __ jmp(RAX);
344 __ int3(); 344 __ int3();
345 } 345 }
346 346
347 347
348 // Input parameters: 348 // Input parameters:
349 // R10: smi-tagged argument count, may be zero. 349 // R10: smi-tagged argument count, may be zero.
350 // RBP[kParamEndSlotFromFp + 1]: last argument. 350 // RBP[kParamEndSlotFromFp + 1]: last argument.
351 static void PushArgumentsArray(Assembler* assembler) { 351 static void PushArgumentsArray(Assembler* assembler) {
352 StubCode* stub_code = Isolate::Current()->stub_code(); 352 StubCode* stub_code = Isolate::Current()->stub_code();
353 353
354 __ LoadObject(R12, Object::null_object(), PP); 354 __ LoadObject(R12, Object::null_object(), PP);
355 // Allocate array to store arguments of caller. 355 // Allocate array to store arguments of caller.
356 __ movq(RBX, R12); // Null element type for raw Array. 356 __ movq(RBX, R12); // Null element type for raw Array.
357 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub()); 357 const Code& array_stub = Code::Handle(stub_code->GetAllocateArrayStub());
358 const ExternalLabel array_label(array_stub.EntryPoint()); 358 __ Call(array_stub, PP);
359 __ call(&array_label);
360 __ SmiUntag(R10); 359 __ SmiUntag(R10);
361 // RAX: newly allocated array. 360 // RAX: newly allocated array.
362 // R10: length of the array (was preserved by the stub). 361 // R10: length of the array (was preserved by the stub).
363 __ pushq(RAX); // Array is in RAX and on top of stack. 362 __ pushq(RAX); // Array is in RAX and on top of stack.
364 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); 363 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
365 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); 364 __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
366 // R12: address of first argument on stack. 365 // R12: address of first argument on stack.
367 // RBX: address of first argument in array. 366 // RBX: address of first argument in array.
368 Label loop, loop_condition; 367 Label loop, loop_condition;
369 #if defined(DEBUG) 368 #if defined(DEBUG)
370 static const bool kJumpLength = Assembler::kFarJump; 369 static const bool kJumpLength = Assembler::kFarJump;
371 #else 370 #else
372 static const bool kJumpLength = Assembler::kNearJump; 371 static const bool kJumpLength = Assembler::kNearJump;
373 #endif // DEBUG 372 #endif // DEBUG
374 __ jmp(&loop_condition, kJumpLength); 373 __ jmp(&loop_condition, kJumpLength);
375 __ Bind(&loop); 374 __ Bind(&loop);
376 __ movq(RDI, Address(R12, 0)); 375 __ movq(RDI, Address(R12, 0));
377 // No generational barrier needed, since array is in new space. 376 // No generational barrier needed, since array is in new space.
378 __ InitializeFieldNoBarrier(RAX, Address(RBX, 0), RDI); 377 __ InitializeFieldNoBarrier(RAX, Address(RBX, 0), RDI);
379 __ addq(RBX, Immediate(kWordSize)); 378 __ addq(RBX, Immediate(kWordSize));
380 __ subq(R12, Immediate(kWordSize)); 379 __ subq(R12, Immediate(kWordSize));
381 __ Bind(&loop_condition); 380 __ Bind(&loop_condition);
382 __ decq(R10); 381 __ decq(R10);
383 __ j(POSITIVE, &loop, Assembler::kNearJump); 382 __ j(POSITIVE, &loop, Assembler::kNearJump);
384 } 383 }
385 384
386 385
387 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 386 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
388 intptr_t deopt_reason, 387 uword saved_registers_address,
389 uword saved_registers_address); 388 uword is_lazy_deopt);
390 389
391 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); 390 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp);
392 391
393 392
393 enum DeoptStubKind {
394 kLazyDeopt,
395 kEagerDeopt
396 };
397
394 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. 398 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary.
395 // This stub translates optimized frame into unoptimized frame. The optimized 399 // This stub translates optimized frame into unoptimized frame. The optimized
396 // frame can contain values in registers and on stack, the unoptimized 400 // frame can contain values in registers and on stack, the unoptimized
397 // frame contains all values on stack. 401 // frame contains all values on stack.
398 // Deoptimization occurs in following steps: 402 // Deoptimization occurs in following steps:
399 // - Push all registers that can contain values. 403 // - Push all registers that can contain values.
400 // - Call C routine to copy the stack and saved registers into temporary buffer. 404 // - Call C routine to copy the stack and saved registers into temporary buffer.
401 // - Adjust caller's frame to correct unoptimized frame size. 405 // - Adjust caller's frame to correct unoptimized frame size.
402 // - Fill the unoptimized frame. 406 // - Fill the unoptimized frame.
403 // - Materialize objects that require allocation (e.g. Double instances). 407 // - Materialize objects that require allocation (e.g. Double instances).
404 // GC can occur only after frame is fully rewritten. 408 // GC can occur only after frame is fully rewritten.
405 // Stack after EnterDartFrame(0, PP, kNoRegister) below: 409 // Stack after EnterDartFrame(0, PP, kNoRegister) below:
406 // +------------------+ 410 // +------------------+
407 // | Saved PP | <- PP 411 // | Saved PP | <- PP
408 // +------------------+ 412 // +------------------+
409 // | PC marker | <- TOS 413 // | PC marker | <- TOS
410 // +------------------+ 414 // +------------------+
411 // | Saved FP | <- FP of stub 415 // | Saved FP | <- FP of stub
412 // +------------------+ 416 // +------------------+
413 // | return-address | (deoptimization point) 417 // | return-address | (deoptimization point)
414 // +------------------+ 418 // +------------------+
415 // | ... | <- SP of optimized frame 419 // | ... | <- SP of optimized frame
416 // 420 //
417 // Parts of the code cannot GC, part of the code can GC. 421 // Parts of the code cannot GC, part of the code can GC.
418 static void GenerateDeoptimizationSequence(Assembler* assembler, 422 static void GenerateDeoptimizationSequence(Assembler* assembler,
419 bool preserve_result) { 423 DeoptStubKind kind) {
420 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 424 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
421 // is no need to set the correct PC marker or load PP, since they get patched. 425 // is no need to set the correct PC marker or load PP, since they get patched.
422 __ EnterFrame(0); 426 __ EnterDartFrame(0, kNoRegister);
423 __ pushq(Immediate(0));
424 __ pushq(PP);
425 427
426 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry 428 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
427 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. 429 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
428 const intptr_t saved_result_slot_from_fp = 430 const intptr_t saved_result_slot_from_fp =
429 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX); 431 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - RAX);
430 // Result in RAX is preserved as part of pushing all registers below. 432 // Result in RAX is preserved as part of pushing all registers below.
431 433
432 // Push registers in their enumeration order: lowest register number at 434 // Push registers in their enumeration order: lowest register number at
433 // lowest address. 435 // lowest address.
434 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { 436 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
435 __ pushq(static_cast<Register>(i)); 437 __ pushq(static_cast<Register>(i));
436 } 438 }
437 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize)); 439 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
438 intptr_t offset = 0; 440 intptr_t offset = 0;
439 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { 441 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) {
440 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); 442 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx);
441 __ movups(Address(RSP, offset), xmm_reg); 443 __ movups(Address(RSP, offset), xmm_reg);
442 offset += kFpuRegisterSize; 444 offset += kFpuRegisterSize;
443 } 445 }
444 446
445 // Pass address of saved registers block. 447 // Pass address of saved registers block.
446 __ movq(CallingConventions::kArg1Reg, RSP); 448 __ movq(CallingConventions::kArg1Reg, RSP);
449 __ movq(CallingConventions::kArg2Reg, Immediate(kind == kLazyDeopt ? 1 : 0));
447 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call. 450 __ ReserveAlignedFrameSpace(0); // Ensure stack is aligned before the call.
448 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1); 451 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
449 // Result (RAX) is stack-size (FP - SP) in bytes. 452 // Result (RAX) is stack-size (FP - SP) in bytes.
450 453
451 if (preserve_result) { 454 if (kind == kLazyDeopt) {
452 // Restore result into RBX temporarily. 455 // Restore result into RBX temporarily.
453 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize)); 456 __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
454 } 457 }
455 458
456 // There is a Dart Frame on the stack. We must restore PP and leave frame. 459 // There is a Dart Frame on the stack. We must restore PP and leave frame.
460 __ RestoreCodePointer();
457 __ LeaveDartFrame(); 461 __ LeaveDartFrame();
458 462
459 __ popq(RCX); // Preserve return address. 463 __ popq(RCX); // Preserve return address.
460 __ movq(RSP, RBP); // Discard optimized frame. 464 __ movq(RSP, RBP); // Discard optimized frame.
461 __ subq(RSP, RAX); // Reserve space for deoptimized frame. 465 __ subq(RSP, RAX); // Reserve space for deoptimized frame.
462 __ pushq(RCX); // Restore return address. 466 __ pushq(RCX); // Restore return address.
463 467
464 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 468 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
465 // is no need to set the correct PC marker or load PP, since they get patched. 469 // is no need to set the correct PC marker or load PP, since they get patched.
466 __ EnterFrame(0); 470 __ EnterDartFrame(0, kNoRegister);
467 __ pushq(Immediate(0));
468 __ pushq(PP);
469 471
470 if (preserve_result) { 472 if (kind == kLazyDeopt) {
471 __ pushq(RBX); // Preserve result as first local. 473 __ pushq(RBX); // Preserve result as first local.
472 } 474 }
473 __ ReserveAlignedFrameSpace(0); 475 __ ReserveAlignedFrameSpace(0);
474 // Pass last FP as a parameter. 476 // Pass last FP as a parameter.
475 __ movq(CallingConventions::kArg1Reg, RBP); 477 __ movq(CallingConventions::kArg1Reg, RBP);
476 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); 478 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
477 if (preserve_result) { 479 if (kind == kLazyDeopt) {
478 // Restore result into RBX. 480 // Restore result into RBX.
479 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); 481 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
480 } 482 }
481 // Code above cannot cause GC. 483 // Code above cannot cause GC.
482 // There is a Dart Frame on the stack. We must restore PP and leave frame. 484 // There is a Dart Frame on the stack. We must restore PP and leave frame.
485 __ RestoreCodePointer();
483 __ LeaveDartFrame(); 486 __ LeaveDartFrame();
484 487
485 // Frame is fully rewritten at this point and it is safe to perform a GC. 488 // Frame is fully rewritten at this point and it is safe to perform a GC.
486 // Materialize any objects that were deferred by FillFrame because they 489 // Materialize any objects that were deferred by FillFrame because they
487 // require allocation. 490 // require allocation.
488 // Enter stub frame with loading PP. The caller's PP is not materialized yet. 491 // Enter stub frame with loading PP. The caller's PP is not materialized yet.
489 __ EnterStubFrame(); 492 __ EnterStubFrame();
490 if (preserve_result) { 493 if (kind == kLazyDeopt) {
491 __ pushq(Immediate(0)); // Workaround for dropped stack slot during GC. 494 __ pushq(Immediate(0)); // Workaround for dropped stack slot during GC.
492 __ pushq(RBX); // Preserve result, it will be GC-d here. 495 __ pushq(RBX); // Preserve result, it will be GC-d here.
493 } 496 }
494 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result. 497 __ pushq(Immediate(Smi::RawValue(0))); // Space for the result.
495 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); 498 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
496 // Result tells stub how many bytes to remove from the expression stack 499 // Result tells stub how many bytes to remove from the expression stack
497 // of the bottom-most frame. They were used as materialization arguments. 500 // of the bottom-most frame. They were used as materialization arguments.
498 __ popq(RBX); 501 __ popq(RBX);
499 __ SmiUntag(RBX); 502 __ SmiUntag(RBX);
500 if (preserve_result) { 503 if (kind == kLazyDeopt) {
501 __ popq(RAX); // Restore result. 504 __ popq(RAX); // Restore result.
502 __ Drop(1); // Workaround for dropped stack slot during GC. 505 __ Drop(1); // Workaround for dropped stack slot during GC.
503 } 506 }
504 __ LeaveStubFrame(); 507 __ LeaveStubFrame();
505 508
506 __ popq(RCX); // Pop return address. 509 __ popq(RCX); // Pop return address.
507 __ addq(RSP, RBX); // Remove materialization arguments. 510 __ addq(RSP, RBX); // Remove materialization arguments.
508 __ pushq(RCX); // Push return address. 511 __ pushq(RCX); // Push return address.
509 __ ret(); 512 __ ret();
510 } 513 }
511 514
512 515
513 // TOS: return address + call-instruction-size (5 bytes). 516 // TOS: return address + call-instruction-size (5 bytes).
514 // RAX: result, must be preserved 517 // RAX: result, must be preserved
515 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 518 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
516 // Correct return address to point just after the call that is being 519 // Correct return address to point just after the call that is being
517 // deoptimized. 520 // deoptimized.
518 __ popq(RBX); 521 __ popq(RBX);
519 __ subq(RBX, Immediate(ShortCallPattern::InstructionLength())); 522 __ subq(RBX, Immediate(ShortCallPattern::InstructionLength()));
520 __ pushq(RBX); 523 __ pushq(RBX);
521 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. 524 GenerateDeoptimizationSequence(assembler, kLazyDeopt);
522 } 525 }
523 526
524 527
525 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 528 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
526 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. 529 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
527 } 530 }
528 531
529 532
530 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 533 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
531 __ EnterStubFrame(); 534 __ EnterStubFrame();
532 // Load the receiver into RAX. The argument count in the arguments 535 // Load the receiver into RAX. The argument count in the arguments
533 // descriptor in R10 is a smi. 536 // descriptor in R10 is a smi.
534 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 537 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
535 // Three words (saved pp, saved fp, stub's pc marker) 538 // Three words (saved pp, saved fp, stub's pc marker)
536 // in the stack above the return address. 539 // in the stack above the return address.
537 __ movq(RAX, Address(RSP, RAX, TIMES_4, 540 __ movq(RAX, Address(RSP, RAX, TIMES_4,
538 kSavedAboveReturnAddress * kWordSize)); 541 kSavedAboveReturnAddress * kWordSize));
539 // Preserve IC data and arguments descriptor. 542 // Preserve IC data and arguments descriptor.
540 __ pushq(RBX); 543 __ pushq(RBX);
541 __ pushq(R10); 544 __ pushq(R10);
542 545
543 // Space for the result of the runtime call. 546 // Space for the result of the runtime call.
544 __ PushObject(Object::null_object(), PP); 547 __ PushObject(Object::null_object(), PP);
545 __ pushq(RAX); // Receiver. 548 __ pushq(RAX); // Receiver.
546 __ pushq(RBX); // IC data. 549 __ pushq(RBX); // IC data.
547 __ pushq(R10); // Arguments descriptor. 550 __ pushq(R10); // Arguments descriptor.
548 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 551 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
549 // Discard arguments. 552 // Discard arguments.
550 __ popq(RAX); 553 __ popq(RAX);
551 __ popq(RAX); 554 __ popq(RAX);
552 __ popq(RAX); 555 __ popq(RAX);
553 __ popq(RAX); // Return value from the runtime call (function). 556 __ popq(RAX); // Return value from the runtime call (function).
554 __ popq(R10); // Restore arguments descriptor. 557 __ popq(R10); // Restore arguments descriptor.
555 __ popq(RBX); // Restore IC data. 558 __ popq(RBX); // Restore IC data.
559 __ RestoreCodePointer();
556 __ LeaveStubFrame(); 560 __ LeaveStubFrame();
557 561
558 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); 562 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
563 __ movq(RCX, FieldAddress(CODE_REG, Code::instructions_offset()));
559 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 564 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
560 __ jmp(RCX); 565 __ jmp(RCX);
561 } 566 }
562 567
563 568
564 // Called for inline allocation of arrays. 569 // Called for inline allocation of arrays.
565 // Input parameters: 570 // Input parameters:
566 // R10 : Array length as Smi. 571 // R10 : Array length as Smi.
567 // RBX : array element type (either NULL or an instantiated type). 572 // RBX : array element type (either NULL or an instantiated type).
568 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. 573 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 __ pushq(R10); // Array length as Smi. 689 __ pushq(R10); // Array length as Smi.
685 __ pushq(RBX); // Element type. 690 __ pushq(RBX); // Element type.
686 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 691 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
687 __ popq(RAX); // Pop element type argument. 692 __ popq(RAX); // Pop element type argument.
688 __ popq(R10); // Pop array length argument. 693 __ popq(R10); // Pop array length argument.
689 __ popq(RAX); // Pop return value from return slot. 694 __ popq(RAX); // Pop return value from return slot.
690 __ LeaveStubFrame(); 695 __ LeaveStubFrame();
691 __ ret(); 696 __ ret();
692 *patch_code_pc_offset = assembler->CodeSize(); 697 *patch_code_pc_offset = assembler->CodeSize();
693 StubCode* stub_code = Isolate::Current()->stub_code(); 698 StubCode* stub_code = Isolate::Current()->stub_code();
694 __ JmpPatchable(&stub_code->FixAllocateArrayStubTargetLabel(), new_pp); 699 __ JmpPatchable(Code::Handle(
700 stub_code->FixAllocateArrayStubTargetCode()), new_pp);
695 } 701 }
696 702
697 703
698 // Called when invoking Dart code from C++ (VM code). 704 // Called when invoking Dart code from C++ (VM code).
699 // Input parameters: 705 // Input parameters:
700 // RSP : points to return address. 706 // RSP : points to return address.
701 // RDI : entrypoint of the Dart function to call. 707 // RDI : target code
702 // RSI : arguments descriptor array. 708 // RSI : arguments descriptor array.
703 // RDX : arguments array. 709 // RDX : arguments array.
704 // RCX : current thread. 710 // RCX : current thread.
705 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 711 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
706 // Save frame pointer coming in. 712 // Save frame pointer coming in.
707 __ EnterFrame(0); 713 __ EnterFrame(0);
708 714
709 const Register kEntryPointReg = CallingConventions::kArg1Reg; 715 const Register kStubCodeReg = CallingConventions::kArg1Reg;
710 const Register kArgDescReg = CallingConventions::kArg2Reg; 716 const Register kTargetCodeReg = CallingConventions::kArg2Reg;
711 const Register kArgsReg = CallingConventions::kArg3Reg; 717 const Register kArgDescReg = CallingConventions::kArg3Reg;
712 const Register kThreadReg = CallingConventions::kArg4Reg; 718 const Register kArgsReg = CallingConventions::kArg4Reg;
719
720 // Set up THR, which caches the current thread in Dart code.
721 #if defined(_WIN64)
722 __ movq(THR, Address(RSP, 5 * kWordSize));
723 #else
724 const Register kThreadReg = CallingConventions::kArg5Reg;
725 if (THR != kThreadReg) {
726 __ movq(THR, kThreadReg);
727 }
728 #endif
713 729
714 // At this point, the stack looks like: 730 // At this point, the stack looks like:
715 // | saved RBP | <-- RBP 731 // | saved RBP | <-- RBP
716 // | saved PC (return to DartEntry::InvokeFunction) | 732 // | saved PC (return to DartEntry::InvokeFunction) |
717 733
718 const intptr_t kInitialOffset = 1; 734 const intptr_t kArgumentsDescOffset = -1 * kWordSize;
719 // Save arguments descriptor array. 735 const intptr_t kCodePointerOffset = -2 * kWordSize;
720 const intptr_t kArgumentsDescOffset = -(kInitialOffset) * kWordSize;
721 __ pushq(kArgDescReg); 736 __ pushq(kArgDescReg);
737 __ pushq(Address(kStubCodeReg, VMHandles::kOffsetOfRawPtrInHandle));
722 738
723 // Save C++ ABI callee-saved registers. 739 // Save C++ ABI callee-saved registers.
724 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters, 740 __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
725 CallingConventions::kCalleeSaveXmmRegisters); 741 CallingConventions::kCalleeSaveXmmRegisters);
726 742
727 // We now load the pool pointer(PP) as we are about to invoke dart code and we 743 // We now load the pool pointer(PP) as we are about to invoke dart code and we
728 // could potentially invoke some intrinsic functions which need the PP to be 744 // could potentially invoke some intrinsic functions which need the PP to be
729 // set up. 745 // set up.
746 __ movq(CODE_REG, Address(kStubCodeReg, VMHandles::kOffsetOfRawPtrInHandle));
730 __ LoadPoolPointer(PP); 747 __ LoadPoolPointer(PP);
731 748
732 // If any additional (or fewer) values are pushed, the offsets in 749 // If any additional (or fewer) values are pushed, the offsets in
733 // kExitLinkSlotFromEntryFp will need to be changed. 750 // kExitLinkSlotFromEntryFp will need to be changed.
734 751
735 // Set up THR, which caches the current thread in Dart code.
736 if (THR != kThreadReg) {
737 __ movq(THR, kThreadReg);
738 }
739 // Load Isolate pointer into kIsolateReg. 752 // Load Isolate pointer into kIsolateReg.
740 const Register kIsolateReg = RBX; 753 const Register kIsolateReg = RBX;
741 __ LoadIsolate(kIsolateReg); 754 __ LoadIsolate(kIsolateReg);
742 755
743 // Save the current VMTag on the stack. 756 // Save the current VMTag on the stack.
744 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset())); 757 __ movq(RAX, Address(kIsolateReg, Isolate::vm_tag_offset()));
745 __ pushq(RAX); 758 __ pushq(RAX);
746 759
747 // Mark that the isolate is executing Dart code. 760 // Mark that the isolate is executing Dart code.
748 __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()), 761 __ movq(Address(kIsolateReg, Isolate::vm_tag_offset()),
749 Immediate(VMTag::kDartTagId)); 762 Immediate(VMTag::kDartTagId));
750 763
751 // Save top resource and top exit frame info. Use RAX as a temporary register. 764 // Save top resource and top exit frame info. Use RAX as a temporary register.
752 // StackFrameIterator reads the top exit frame info saved in this frame. 765 // StackFrameIterator reads the top exit frame info saved in this frame.
753 __ movq(RAX, Address(kIsolateReg, Isolate::top_resource_offset())); 766 __ movq(RAX, Address(kIsolateReg, Isolate::top_resource_offset()));
754 __ pushq(RAX); 767 __ pushq(RAX);
755 __ movq(Address(kIsolateReg, Isolate::top_resource_offset()), 768 __ movq(Address(kIsolateReg, Isolate::top_resource_offset()),
756 Immediate(0)); 769 Immediate(0));
757 __ movq(RAX, Address(kIsolateReg, Isolate::top_exit_frame_info_offset())); 770 __ movq(RAX, Address(kIsolateReg, Isolate::top_exit_frame_info_offset()));
758 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the 771 // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
759 // code below. 772 // code below.
760 __ pushq(RAX); 773 __ pushq(RAX);
761 #if defined(DEBUG) 774 #if defined(DEBUG)
762 { 775 {
763 Label ok; 776 Label ok;
764 __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize)); 777 __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize));
765 __ cmpq(RAX, RSP); 778 __ cmpq(RAX, RSP);
766 __ j(EQUAL, &ok); 779 __ j(EQUAL, &ok);
780 __ int3();
767 __ Stop("kExitLinkSlotFromEntryFp mismatch"); 781 __ Stop("kExitLinkSlotFromEntryFp mismatch");
768 __ Bind(&ok); 782 __ Bind(&ok);
769 } 783 }
770 #endif 784 #endif
771 __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()), 785 __ movq(Address(kIsolateReg, Isolate::top_exit_frame_info_offset()),
772 Immediate(0)); 786 Immediate(0));
773 787
774 // Load arguments descriptor array into R10, which is passed to Dart code. 788 // Load arguments descriptor array into R10, which is passed to Dart code.
775 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); 789 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
776 790
777 // Push arguments. At this point we only need to preserve kEntryPointReg. 791 // Push arguments. At this point we only need to preserve kTargetCodeReg.
778 ASSERT(kEntryPointReg != RDX); 792 ASSERT(kTargetCodeReg != RDX);
779 793
780 // Load number of arguments into RBX. 794 // Load number of arguments into RBX.
781 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 795 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
782 __ SmiUntag(RBX); 796 __ SmiUntag(RBX);
783 797
784 // Compute address of 'arguments array' data area into RDX. 798 // Compute address of 'arguments array' data area into RDX.
785 __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle)); 799 __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle));
786 __ leaq(RDX, FieldAddress(RDX, Array::data_offset())); 800 __ leaq(RDX, FieldAddress(RDX, Array::data_offset()));
787 801
788 // Set up arguments for the Dart call. 802 // Set up arguments for the Dart call.
789 Label push_arguments; 803 Label push_arguments;
790 Label done_push_arguments; 804 Label done_push_arguments;
791 __ testq(RBX, RBX); // check if there are arguments. 805 __ testq(RBX, RBX); // check if there are arguments.
792 __ j(ZERO, &done_push_arguments, Assembler::kNearJump); 806 __ j(ZERO, &done_push_arguments, Assembler::kNearJump);
793 __ movq(RAX, Immediate(0)); 807 __ movq(RAX, Immediate(0));
794 __ Bind(&push_arguments); 808 __ Bind(&push_arguments);
795 __ pushq(Address(RDX, RAX, TIMES_8, 0)); 809 __ pushq(Address(RDX, RAX, TIMES_8, 0));
796 __ incq(RAX); 810 __ incq(RAX);
797 __ cmpq(RAX, RBX); 811 __ cmpq(RAX, RBX);
798 __ j(LESS, &push_arguments, Assembler::kNearJump); 812 __ j(LESS, &push_arguments, Assembler::kNearJump);
799 __ Bind(&done_push_arguments); 813 __ Bind(&done_push_arguments);
800 814
801 // Call the Dart code entrypoint. 815 // Call the Dart code entrypoint.
802 __ call(kEntryPointReg); // R10 is the arguments descriptor array. 816 __ movq(CODE_REG,
817 Address(kTargetCodeReg, VMHandles::kOffsetOfRawPtrInHandle));
818 __ movq(kTargetCodeReg, FieldAddress(CODE_REG, Code::instructions_offset()));
819 __ addq(kTargetCodeReg,
820 Immediate(Instructions::HeaderSize() - kHeapObjectTag));
821 __ call(kTargetCodeReg); // R10 is the arguments descriptor array.
822
823 // If we arrived here from JumpToExceptionHandler then PP would not be
824 // set correctly. Reload it from the code object.
825 // TODO(vegorov): set PP in the JumpToExceptionHandler to avoid reloading.
826 __ movq(CODE_REG, Address(RBP, kCodePointerOffset));
827 __ LoadPoolPointer(PP);
803 828
804 // Read the saved arguments descriptor array to obtain the number of passed 829 // Read the saved arguments descriptor array to obtain the number of passed
805 // arguments. 830 // arguments.
806 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset)); 831 __ movq(kArgDescReg, Address(RBP, kArgumentsDescOffset));
807 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle)); 832 __ movq(R10, Address(kArgDescReg, VMHandles::kOffsetOfRawPtrInHandle));
808 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 833 __ movq(RDX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
809 // Get rid of arguments pushed on the stack. 834 // Get rid of arguments pushed on the stack.
810 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi. 835 __ leaq(RSP, Address(RSP, RDX, TIMES_4, 0)); // RDX is a Smi.
811 836
812 // Restore the saved top exit frame info and top resource back into the 837 // Restore the saved top exit frame info and top resource back into the
(...skipping 15 matching lines...) Expand all
828 __ ret(); 853 __ ret();
829 } 854 }
830 855
831 856
832 // Called for inline allocation of contexts. 857 // Called for inline allocation of contexts.
833 // Input: 858 // Input:
834 // R10: number of context variables. 859 // R10: number of context variables.
835 // Output: 860 // Output:
836 // RAX: new allocated RawContext object. 861 // RAX: new allocated RawContext object.
837 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 862 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
838 __ LoadObject(R12, Object::null_object(), PP); 863 __ LoadObject(R9, Object::null_object(), PP);
839 if (FLAG_inline_alloc) { 864 if (FLAG_inline_alloc) {
840 Label slow_case; 865 Label slow_case;
841 Isolate* isolate = Isolate::Current(); 866 Isolate* isolate = Isolate::Current();
842 Heap* heap = isolate->heap(); 867 Heap* heap = isolate->heap();
843 // First compute the rounded instance size. 868 // First compute the rounded instance size.
844 // R10: number of context variables. 869 // R10: number of context variables.
845 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1); 870 intptr_t fixed_size = (sizeof(RawContext) + kObjectAlignment - 1);
846 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); 871 __ leaq(R13, Address(R10, TIMES_8, fixed_size));
847 __ andq(R13, Immediate(-kObjectAlignment)); 872 __ andq(R13, Immediate(-kObjectAlignment));
848 873
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 // RAX: new object. 931 // RAX: new object.
907 // R10: number of context variables as integer value (not object). 932 // R10: number of context variables as integer value (not object).
908 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); 933 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
909 934
910 // Setup the parent field. 935 // Setup the parent field.
911 // RAX: new object. 936 // RAX: new object.
912 // R10: number of context variables. 937 // R10: number of context variables.
913 // No generational barrier needed, since we are storing null. 938 // No generational barrier needed, since we are storing null.
914 __ InitializeFieldNoBarrier(RAX, 939 __ InitializeFieldNoBarrier(RAX,
915 FieldAddress(RAX, Context::parent_offset()), 940 FieldAddress(RAX, Context::parent_offset()),
916 R12); 941 R9);
917 942
918 // Initialize the context variables. 943 // Initialize the context variables.
919 // RAX: new object. 944 // RAX: new object.
920 // R10: number of context variables. 945 // R10: number of context variables.
921 { 946 {
922 Label loop, entry; 947 Label loop, entry;
923 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); 948 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
924 #if defined(DEBUG) 949 #if defined(DEBUG)
925 static const bool kJumpLength = Assembler::kFarJump; 950 static const bool kJumpLength = Assembler::kFarJump;
926 #else 951 #else
927 static const bool kJumpLength = Assembler::kNearJump; 952 static const bool kJumpLength = Assembler::kNearJump;
928 #endif // DEBUG 953 #endif // DEBUG
929 __ jmp(&entry, kJumpLength); 954 __ jmp(&entry, kJumpLength);
930 __ Bind(&loop); 955 __ Bind(&loop);
931 __ decq(R10); 956 __ decq(R10);
932 // No generational barrier needed, since we are storing null. 957 // No generational barrier needed, since we are storing null.
933 __ InitializeFieldNoBarrier(RAX, 958 __ InitializeFieldNoBarrier(RAX,
934 Address(R13, R10, TIMES_8, 0), 959 Address(R13, R10, TIMES_8, 0),
935 R12); 960 R9);
936 __ Bind(&entry); 961 __ Bind(&entry);
937 __ cmpq(R10, Immediate(0)); 962 __ cmpq(R10, Immediate(0));
938 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 963 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
939 } 964 }
940 965
941 // Done allocating and initializing the context. 966 // Done allocating and initializing the context.
942 // RAX: new object. 967 // RAX: new object.
943 __ ret(); 968 __ ret();
944 969
945 __ Bind(&slow_case); 970 __ Bind(&slow_case);
946 } 971 }
947 // Create a stub frame. 972 // Create a stub frame.
948 __ EnterStubFrame(); 973 __ EnterStubFrame();
949 __ pushq(R12); // Setup space on stack for the return value. 974 __ pushq(R9); // Setup space on stack for the return value.
950 __ SmiTag(R10); 975 __ SmiTag(R10);
951 __ pushq(R10); // Push number of context variables. 976 __ pushq(R10); // Push number of context variables.
952 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. 977 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
953 __ popq(RAX); // Pop number of context variables argument. 978 __ popq(RAX); // Pop number of context variables argument.
954 __ popq(RAX); // Pop the new context object. 979 __ popq(RAX); // Pop the new context object.
955 // RAX: new object 980 // RAX: new object
956 // Restore the frame pointer. 981 // Restore the frame pointer.
957 __ LeaveStubFrame(); 982 __ LeaveStubFrame();
958 __ ret(); 983 __ ret();
959 } 984 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 // The generated code is different if the class is parameterized. 1065 // The generated code is different if the class is parameterized.
1041 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1066 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1042 ASSERT(!is_cls_parameterized || 1067 ASSERT(!is_cls_parameterized ||
1043 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1068 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1044 // kInlineInstanceSize is a constant used as a threshold for determining 1069 // kInlineInstanceSize is a constant used as a threshold for determining
1045 // when the object initialization should be done as a loop or as 1070 // when the object initialization should be done as a loop or as
1046 // straight line code. 1071 // straight line code.
1047 const int kInlineInstanceSize = 12; // In words. 1072 const int kInlineInstanceSize = 12; // In words.
1048 const intptr_t instance_size = cls.instance_size(); 1073 const intptr_t instance_size = cls.instance_size();
1049 ASSERT(instance_size > 0); 1074 ASSERT(instance_size > 0);
1050 __ LoadObject(R12, Object::null_object(), PP); 1075 __ LoadObject(R9, Object::null_object(), PP);
1051 if (is_cls_parameterized) { 1076 if (is_cls_parameterized) {
1052 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset)); 1077 __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
1053 // RDX: instantiated type arguments. 1078 // RDX: instantiated type arguments.
1054 } 1079 }
1055 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { 1080 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
1056 Label slow_case; 1081 Label slow_case;
1057 // Allocate the object and update top to point to 1082 // Allocate the object and update top to point to
1058 // next object start and initialize the allocated object. 1083 // next object start and initialize the allocated object.
1059 // RDX: instantiated type arguments (if is_cls_parameterized). 1084 // RDX: instantiated type arguments (if is_cls_parameterized).
1060 Heap* heap = Isolate::Current()->heap(); 1085 Heap* heap = Isolate::Current()->heap();
(...skipping 23 matching lines...) Expand all
1084 tags = RawObject::SizeTag::update(instance_size, tags); 1109 tags = RawObject::SizeTag::update(instance_size, tags);
1085 ASSERT(cls.id() != kIllegalCid); 1110 ASSERT(cls.id() != kIllegalCid);
1086 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1111 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1087 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); 1112 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
1088 __ addq(RAX, Immediate(kHeapObjectTag)); 1113 __ addq(RAX, Immediate(kHeapObjectTag));
1089 1114
1090 // Initialize the remaining words of the object. 1115 // Initialize the remaining words of the object.
1091 // RAX: new object (tagged). 1116 // RAX: new object (tagged).
1092 // RBX: next object start. 1117 // RBX: next object start.
1093 // RDX: new object type arguments (if is_cls_parameterized). 1118 // RDX: new object type arguments (if is_cls_parameterized).
1094 // R12: raw null. 1119 // R9: raw null.
1095 // First try inlining the initialization without a loop. 1120 // First try inlining the initialization without a loop.
1096 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1121 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1097 // Check if the object contains any non-header fields. 1122 // Check if the object contains any non-header fields.
1098 // Small objects are initialized using a consecutive set of writes. 1123 // Small objects are initialized using a consecutive set of writes.
1099 for (intptr_t current_offset = Instance::NextFieldOffset(); 1124 for (intptr_t current_offset = Instance::NextFieldOffset();
1100 current_offset < instance_size; 1125 current_offset < instance_size;
1101 current_offset += kWordSize) { 1126 current_offset += kWordSize) {
1102 __ InitializeFieldNoBarrier(RAX, 1127 __ InitializeFieldNoBarrier(RAX,
1103 FieldAddress(RAX, current_offset), 1128 FieldAddress(RAX, current_offset),
1104 R12); 1129 R9);
1105 } 1130 }
1106 } else { 1131 } else {
1107 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); 1132 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset()));
1108 // Loop until the whole object is initialized. 1133 // Loop until the whole object is initialized.
1109 // RAX: new object (tagged). 1134 // RAX: new object (tagged).
1110 // RBX: next object start. 1135 // RBX: next object start.
1111 // RCX: next word to be initialized. 1136 // RCX: next word to be initialized.
1112 // RDX: new object type arguments (if is_cls_parameterized). 1137 // RDX: new object type arguments (if is_cls_parameterized).
1113 Label init_loop; 1138 Label init_loop;
1114 Label done; 1139 Label done;
1115 __ Bind(&init_loop); 1140 __ Bind(&init_loop);
1116 __ cmpq(RCX, RBX); 1141 __ cmpq(RCX, RBX);
1117 #if defined(DEBUG) 1142 #if defined(DEBUG)
1118 static const bool kJumpLength = Assembler::kFarJump; 1143 static const bool kJumpLength = Assembler::kFarJump;
1119 #else 1144 #else
1120 static const bool kJumpLength = Assembler::kNearJump; 1145 static const bool kJumpLength = Assembler::kNearJump;
1121 #endif // DEBUG 1146 #endif // DEBUG
1122 __ j(ABOVE_EQUAL, &done, kJumpLength); 1147 __ j(ABOVE_EQUAL, &done, kJumpLength);
1123 __ InitializeFieldNoBarrier(RAX, Address(RCX, 0), R12); 1148 __ InitializeFieldNoBarrier(RAX, Address(RCX, 0), R9);
1124 __ addq(RCX, Immediate(kWordSize)); 1149 __ addq(RCX, Immediate(kWordSize));
1125 __ jmp(&init_loop, Assembler::kNearJump); 1150 __ jmp(&init_loop, Assembler::kNearJump);
1126 __ Bind(&done); 1151 __ Bind(&done);
1127 } 1152 }
1128 if (is_cls_parameterized) { 1153 if (is_cls_parameterized) {
1129 // RDX: new object type arguments. 1154 // RDX: new object type arguments.
1130 // Set the type arguments in the new object. 1155 // Set the type arguments in the new object.
1131 intptr_t offset = cls.type_arguments_field_offset(); 1156 intptr_t offset = cls.type_arguments_field_offset();
1132 __ InitializeFieldNoBarrier(RAX, FieldAddress(RAX, offset), RDX); 1157 __ InitializeFieldNoBarrier(RAX, FieldAddress(RAX, offset), RDX);
1133 } 1158 }
1134 // Done allocating and initializing the instance. 1159 // Done allocating and initializing the instance.
1135 // RAX: new object (tagged). 1160 // RAX: new object (tagged).
1136 __ ret(); 1161 __ ret();
1137 1162
1138 __ Bind(&slow_case); 1163 __ Bind(&slow_case);
1139 } 1164 }
1140 // If is_cls_parameterized: 1165 // If is_cls_parameterized:
1141 // RDX: new object type arguments. 1166 // RDX: new object type arguments.
1142 // Create a stub frame. 1167 // Create a stub frame.
1143 __ EnterStubFrame(); // Uses PP to access class object. 1168 __ EnterStubFrame(); // Uses PP to access class object.
1144 __ pushq(R12); // Setup space on stack for return value. 1169 __ pushq(R9); // Setup space on stack for return value.
1145 __ PushObject(cls, PP); // Push class of object to be allocated. 1170 __ PushObject(cls, PP); // Push class of object to be allocated.
1146 if (is_cls_parameterized) { 1171 if (is_cls_parameterized) {
1147 __ pushq(RDX); // Push type arguments of object to be allocated. 1172 __ pushq(RDX); // Push type arguments of object to be allocated.
1148 } else { 1173 } else {
1149 __ pushq(R12); // Push null type arguments. 1174 __ pushq(R9); // Push null type arguments.
1150 } 1175 }
1151 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1176 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1152 __ popq(RAX); // Pop argument (type arguments of object). 1177 __ popq(RAX); // Pop argument (type arguments of object).
1153 __ popq(RAX); // Pop argument (class of object). 1178 __ popq(RAX); // Pop argument (class of object).
1154 __ popq(RAX); // Pop result (newly allocated object). 1179 __ popq(RAX); // Pop result (newly allocated object).
1155 // RAX: new object 1180 // RAX: new object
1156 // Restore the frame pointer. 1181 // Restore the frame pointer.
1157 __ LeaveStubFrame(); 1182 __ LeaveStubFrame();
1158 __ ret(); 1183 __ ret();
1159 *patch_code_pc_offset = assembler->CodeSize(); 1184 *patch_code_pc_offset = assembler->CodeSize();
1160 StubCode* stub_code = Isolate::Current()->stub_code(); 1185 StubCode* stub_code = Isolate::Current()->stub_code();
1161 __ JmpPatchable(&stub_code->FixAllocationStubTargetLabel(), new_pp); 1186 __ JmpPatchable(Code::Handle(
1187 stub_code->FixAllocationStubTargetCode()), new_pp);
1162 } 1188 }
1163 1189
1164 1190
1165 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function 1191 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
1166 // from the entry code of a dart function after an error in passed argument 1192 // from the entry code of a dart function after an error in passed argument
1167 // name or number is detected. 1193 // name or number is detected.
1168 // Input parameters: 1194 // Input parameters:
1169 // RSP : points to return address. 1195 // RSP : points to return address.
1170 // RSP + 8 : address of last argument. 1196 // RSP + 8 : address of last argument.
1171 // R10 : arguments descriptor array. 1197 // R10 : arguments descriptor array.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 Label* not_smi_or_overflow, 1263 Label* not_smi_or_overflow,
1238 bool should_update_result_range) { 1264 bool should_update_result_range) {
1239 __ Comment("Fast Smi op"); 1265 __ Comment("Fast Smi op");
1240 if (FLAG_throw_on_javascript_int_overflow) { 1266 if (FLAG_throw_on_javascript_int_overflow) {
1241 // The overflow check is more complex than implemented below. 1267 // The overflow check is more complex than implemented below.
1242 return; 1268 return;
1243 } 1269 }
1244 ASSERT(num_args == 2); 1270 ASSERT(num_args == 2);
1245 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right 1271 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right
1246 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. 1272 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left.
1247 __ movq(R12, RCX); 1273 __ movq(R13, RCX);
1248 __ orq(R12, RAX); 1274 __ orq(R13, RAX);
1249 __ testq(R12, Immediate(kSmiTagMask)); 1275 __ testq(R13, Immediate(kSmiTagMask));
1250 __ j(NOT_ZERO, not_smi_or_overflow); 1276 __ j(NOT_ZERO, not_smi_or_overflow);
1251 switch (kind) { 1277 switch (kind) {
1252 case Token::kADD: { 1278 case Token::kADD: {
1253 __ addq(RAX, RCX); 1279 __ addq(RAX, RCX);
1254 __ j(OVERFLOW, not_smi_or_overflow); 1280 __ j(OVERFLOW, not_smi_or_overflow);
1255 break; 1281 break;
1256 } 1282 }
1257 case Token::kSUB: { 1283 case Token::kSUB: {
1258 __ subq(RAX, RCX); 1284 __ subq(RAX, RCX);
1259 __ j(OVERFLOW, not_smi_or_overflow); 1285 __ j(OVERFLOW, not_smi_or_overflow);
(...skipping 15 matching lines...) Expand all
1275 1301
1276 1302
1277 if (should_update_result_range) { 1303 if (should_update_result_range) {
1278 Label done; 1304 Label done;
1279 __ movq(RSI, RAX); 1305 __ movq(RSI, RAX);
1280 __ UpdateRangeFeedback(RSI, 2, RBX, RCX, &done); 1306 __ UpdateRangeFeedback(RSI, 2, RBX, RCX, &done);
1281 __ Bind(&done); 1307 __ Bind(&done);
1282 } 1308 }
1283 1309
1284 // RBX: IC data object (preserved). 1310 // RBX: IC data object (preserved).
1285 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1311 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
1286 // R12: ic_data_array with check entries: classes and target functions. 1312 // R13: ic_data_array with check entries: classes and target functions.
1287 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1313 __ leaq(R13, FieldAddress(R13, Array::data_offset()));
1288 // R12: points directly to the first ic data array element. 1314 // R13: points directly to the first ic data array element.
1289 #if defined(DEBUG) 1315 #if defined(DEBUG)
1290 // Check that first entry is for Smi/Smi. 1316 // Check that first entry is for Smi/Smi.
1291 Label error, ok; 1317 Label error, ok;
1292 const Immediate& imm_smi_cid = 1318 const Immediate& imm_smi_cid =
1293 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid))); 1319 Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
1294 __ cmpq(Address(R12, 0 * kWordSize), imm_smi_cid); 1320 __ cmpq(Address(R13, 0 * kWordSize), imm_smi_cid);
1295 __ j(NOT_EQUAL, &error, Assembler::kNearJump); 1321 __ j(NOT_EQUAL, &error, Assembler::kNearJump);
1296 __ cmpq(Address(R12, 1 * kWordSize), imm_smi_cid); 1322 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid);
1297 __ j(EQUAL, &ok, Assembler::kNearJump); 1323 __ j(EQUAL, &ok, Assembler::kNearJump);
1298 __ Bind(&error); 1324 __ Bind(&error);
1299 __ Stop("Incorrect IC data"); 1325 __ Stop("Incorrect IC data");
1300 __ Bind(&ok); 1326 __ Bind(&ok);
1301 #endif 1327 #endif
1302 1328
1303 if (FLAG_optimization_counter_threshold >= 0) { 1329 if (FLAG_optimization_counter_threshold >= 0) {
1304 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1330 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1305 // Update counter. 1331 // Update counter.
1306 __ movq(R8, Address(R12, count_offset)); 1332 __ movq(R8, Address(R13, count_offset));
1307 __ addq(R8, Immediate(Smi::RawValue(1))); 1333 __ addq(R8, Immediate(Smi::RawValue(1)));
1308 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); 1334 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue)));
1309 __ cmovnoq(R13, R8); 1335 __ cmovnoq(R9, R8);
1310 __ StoreIntoSmiField(Address(R12, count_offset), R13); 1336 __ StoreIntoSmiField(Address(R13, count_offset), R9);
1311 } 1337 }
1312 1338
1313 __ ret(); 1339 __ ret();
1314 } 1340 }
1315 1341
1316 1342
1317 // Generate inline cache check for 'num_args'. 1343 // Generate inline cache check for 'num_args'.
1318 // RBX: Inline cache data object. 1344 // RBX: Inline cache data object.
1319 // TOS(0): return address 1345 // TOS(0): return address
1320 // Control flow: 1346 // Control flow:
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 range_collection_mode == kCollectRanges); 1402 range_collection_mode == kCollectRanges);
1377 } 1403 }
1378 __ Bind(&not_smi_or_overflow); 1404 __ Bind(&not_smi_or_overflow);
1379 1405
1380 __ Comment("Extract ICData initial values and receiver cid"); 1406 __ Comment("Extract ICData initial values and receiver cid");
1381 // Load arguments descriptor into R10. 1407 // Load arguments descriptor into R10.
1382 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1408 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1383 // Loop that checks if there is an IC data match. 1409 // Loop that checks if there is an IC data match.
1384 Label loop, update, test, found; 1410 Label loop, update, test, found;
1385 // RBX: IC data object (preserved). 1411 // RBX: IC data object (preserved).
1386 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1412 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
1387 // R12: ic_data_array with check entries: classes and target functions. 1413 // R13: ic_data_array with check entries: classes and target functions.
1388 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1414 __ leaq(R13, FieldAddress(R13, Array::data_offset()));
1389 // R12: points directly to the first ic data array element. 1415 // R13: points directly to the first ic data array element.
1390 1416
1391 // Get the receiver's class ID (first read number of arguments from 1417 // Get the receiver's class ID (first read number of arguments from
1392 // arguments descriptor array and then access the receiver from the stack). 1418 // arguments descriptor array and then access the receiver from the stack).
1393 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1419 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1394 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. 1420 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1395 __ LoadTaggedClassIdMayBeSmi(RAX, R13); 1421 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1396 // RAX: receiver's class ID as smi. 1422 // RAX: receiver's class ID as smi.
1397 __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check. 1423 __ movq(R9, Address(R13, 0)); // First class ID (Smi) to check.
1398 __ jmp(&test); 1424 __ jmp(&test);
1399 1425
1400 __ Comment("ICData loop"); 1426 __ Comment("ICData loop");
1401 __ Bind(&loop); 1427 __ Bind(&loop);
1402 for (int i = 0; i < num_args; i++) { 1428 for (int i = 0; i < num_args; i++) {
1403 if (i > 0) { 1429 if (i > 0) {
1404 // If not the first, load the next argument's class ID. 1430 // If not the first, load the next argument's class ID.
1405 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1431 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1406 __ movq(R13, Address(RSP, RAX, TIMES_4, - i * kWordSize)); 1432 __ movq(R9, Address(RSP, RAX, TIMES_4, - i * kWordSize));
1407 __ LoadTaggedClassIdMayBeSmi(RAX, R13); 1433 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1408 // RAX: next argument class ID (smi). 1434 // RAX: next argument class ID (smi).
1409 __ movq(R13, Address(R12, i * kWordSize)); 1435 __ movq(R9, Address(R13, i * kWordSize));
1410 // R13: next class ID to check (smi). 1436 // R9: next class ID to check (smi).
1411 } 1437 }
1412 __ cmpq(RAX, R13); // Class id match? 1438 __ cmpq(RAX, R9); // Class id match?
1413 if (i < (num_args - 1)) { 1439 if (i < (num_args - 1)) {
1414 __ j(NOT_EQUAL, &update); // Continue. 1440 __ j(NOT_EQUAL, &update); // Continue.
1415 } else { 1441 } else {
1416 // Last check, all checks before matched. 1442 // Last check, all checks before matched.
1417 __ j(EQUAL, &found); // Break. 1443 __ j(EQUAL, &found); // Break.
1418 } 1444 }
1419 } 1445 }
1420 __ Bind(&update); 1446 __ Bind(&update);
1421 // Reload receiver class ID. It has not been destroyed when num_args == 1. 1447 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1422 if (num_args > 1) { 1448 if (num_args > 1) {
1423 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1449 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1424 __ movq(R13, Address(RSP, RAX, TIMES_4, 0)); 1450 __ movq(R9, Address(RSP, RAX, TIMES_4, 0));
1425 __ LoadTaggedClassIdMayBeSmi(RAX, R13); 1451 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1426 } 1452 }
1427 1453
1428 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1454 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1429 __ addq(R12, Immediate(entry_size)); // Next entry. 1455 __ addq(R13, Immediate(entry_size)); // Next entry.
1430 __ movq(R13, Address(R12, 0)); // Next class ID. 1456 __ movq(R9, Address(R13, 0)); // Next class ID.
1431 1457
1432 __ Bind(&test); 1458 __ Bind(&test);
1433 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1459 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1434 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1460 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1435 1461
1436 __ Comment("IC miss"); 1462 __ Comment("IC miss");
1437 __ LoadObject(R12, Object::null_object(), PP); 1463 __ LoadObject(R13, Object::null_object(), PP);
1438 // Compute address of arguments (first read number of arguments from 1464 // Compute address of arguments (first read number of arguments from
1439 // arguments descriptor array and then compute address on the stack). 1465 // arguments descriptor array and then compute address on the stack).
1440 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1466 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1441 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1467 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1442 __ EnterStubFrame(); 1468 __ EnterStubFrame();
1443 __ pushq(R10); // Preserve arguments descriptor array. 1469 __ pushq(R10); // Preserve arguments descriptor array.
1444 __ pushq(RBX); // Preserve IC data object. 1470 __ pushq(RBX); // Preserve IC data object.
1445 __ pushq(R12); // Setup space on stack for result (target code object). 1471 __ pushq(R13); // Setup space on stack for result (target code object).
1446 // Push call arguments. 1472 // Push call arguments.
1447 for (intptr_t i = 0; i < num_args; i++) { 1473 for (intptr_t i = 0; i < num_args; i++) {
1448 __ movq(RCX, Address(RAX, -kWordSize * i)); 1474 __ movq(RCX, Address(RAX, -kWordSize * i));
1449 __ pushq(RCX); 1475 __ pushq(RCX);
1450 } 1476 }
1451 __ pushq(RBX); // Pass IC data object. 1477 __ pushq(RBX); // Pass IC data object.
1452 __ CallRuntime(handle_ic_miss, num_args + 1); 1478 __ CallRuntime(handle_ic_miss, num_args + 1);
1453 // Remove the call arguments pushed earlier, including the IC data object. 1479 // Remove the call arguments pushed earlier, including the IC data object.
1454 for (intptr_t i = 0; i < num_args + 1; i++) { 1480 for (intptr_t i = 0; i < num_args + 1; i++) {
1455 __ popq(RAX); 1481 __ popq(RAX);
1456 } 1482 }
1457 __ popq(RAX); // Pop returned function object into RAX. 1483 __ popq(RAX); // Pop returned function object into RAX.
1458 __ popq(RBX); // Restore IC data array. 1484 __ popq(RBX); // Restore IC data array.
1459 __ popq(R10); // Restore arguments descriptor array. 1485 __ popq(R10); // Restore arguments descriptor array.
1486 if (range_collection_mode == kCollectRanges) {
1487 __ RestoreCodePointer();
1488 }
1460 __ LeaveStubFrame(); 1489 __ LeaveStubFrame();
1461 Label call_target_function; 1490 Label call_target_function;
1462 __ jmp(&call_target_function); 1491 __ jmp(&call_target_function);
1463 1492
1464 __ Bind(&found); 1493 __ Bind(&found);
1465 // R12: Pointer to an IC data check group. 1494 // R13: Pointer to an IC data check group.
1466 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1495 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1467 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1496 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1468 __ movq(RAX, Address(R12, target_offset)); 1497 __ movq(RAX, Address(R13, target_offset));
1469 1498
1470 if (FLAG_optimization_counter_threshold >= 0) { 1499 if (FLAG_optimization_counter_threshold >= 0) {
1471 // Update counter. 1500 // Update counter.
1472 __ Comment("Update caller's counter"); 1501 __ Comment("Update caller's counter");
1473 __ movq(R8, Address(R12, count_offset)); 1502 __ movq(R8, Address(R13, count_offset));
1474 __ addq(R8, Immediate(Smi::RawValue(1))); 1503 __ addq(R8, Immediate(Smi::RawValue(1)));
1475 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); 1504 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue)));
1476 __ cmovnoq(R13, R8); 1505 __ cmovnoq(R9, R8);
1477 __ StoreIntoSmiField(Address(R12, count_offset), R13); 1506 __ StoreIntoSmiField(Address(R13, count_offset), R9);
1478 } 1507 }
1479 1508
1480 __ Comment("Call target"); 1509 __ Comment("Call target");
1481 __ Bind(&call_target_function); 1510 __ Bind(&call_target_function);
1482 // RAX: Target function. 1511 // RAX: Target function.
1483 Label is_compiled; 1512 Label is_compiled;
1484 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset()));
1485 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1486 if (range_collection_mode == kCollectRanges) { 1513 if (range_collection_mode == kCollectRanges) {
1514 __ movq(R13, FieldAddress(RAX, Function::code_offset()));
1515 __ movq(RCX, FieldAddress(R13, Code::instructions_offset()));
1516 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1487 __ movq(R8, Address(RSP, + 1 * kWordSize)); 1517 __ movq(R8, Address(RSP, + 1 * kWordSize));
1488 if (num_args == 2) { 1518 if (num_args == 2) {
1489 __ movq(R13, Address(RSP, + 2 * kWordSize)); 1519 __ movq(R9, Address(RSP, + 2 * kWordSize));
1490 } 1520 }
1491 __ EnterStubFrame(); 1521 __ EnterStubFrame();
1492 __ pushq(RBX); 1522 __ pushq(RBX);
1493 if (num_args == 2) { 1523 if (num_args == 2) {
1494 __ pushq(R13); 1524 __ pushq(R9);
1495 } 1525 }
1496 __ pushq(R8); 1526 __ pushq(R8);
1527 __ movq(CODE_REG, R13);
1497 __ call(RCX); 1528 __ call(RCX);
1498 1529
1499 Label done; 1530 Label done;
1500 __ movq(RDX, RAX); 1531 __ movq(RDX, RAX);
1501 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); 1532 __ movq(RBX, Address(RBP, kFirstLocalSlotFromFp * kWordSize));
1502 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done); 1533 __ UpdateRangeFeedback(RDX, 2, RBX, RCX, &done);
1503 __ Bind(&done); 1534 __ Bind(&done);
1504 __ LeaveStubFrame(); 1535 __ LeaveStubFrame();
1505 __ ret(); 1536 __ ret();
1506 } else { 1537 } else {
1538 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1539 __ movq(RCX, FieldAddress(CODE_REG, Code::instructions_offset()));
1540 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1507 __ jmp(RCX); 1541 __ jmp(RCX);
1508 } 1542 }
1509 1543
1510 if (FLAG_support_debugger && !optimized) { 1544 if (FLAG_support_debugger && !optimized) {
1511 __ Bind(&stepping); 1545 __ Bind(&stepping);
1512 __ EnterStubFrame(); 1546 __ EnterStubFrame();
1513 __ pushq(RBX); 1547 __ pushq(RBX);
1514 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1548 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1515 __ popq(RBX); 1549 __ popq(RBX);
1550 __ RestoreCodePointer();
1516 __ LeaveStubFrame(); 1551 __ LeaveStubFrame();
1517 __ jmp(&done_stepping); 1552 __ jmp(&done_stepping);
1518 } 1553 }
1519 } 1554 }
1520 1555
1521 1556
1522 // Use inline cache data array to invoke the target or continue in inline 1557 // Use inline cache data array to invoke the target or continue in inline
1523 // cache miss handler. Stub for 1-argument check (receiver class). 1558 // cache miss handler. Stub for 1-argument check (receiver class).
1524 // RBX: Inline cache data object. 1559 // RBX: Inline cache data object.
1525 // TOS(0): Return address. 1560 // TOS(0): Return address.
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1674 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue))); 1709 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue)));
1675 __ cmovnoq(R13, R8); 1710 __ cmovnoq(R13, R8);
1676 __ StoreIntoSmiField(Address(R12, count_offset), R13); 1711 __ StoreIntoSmiField(Address(R12, count_offset), R13);
1677 } 1712 }
1678 1713
1679 // Load arguments descriptor into R10. 1714 // Load arguments descriptor into R10.
1680 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1715 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1681 1716
1682 // Get function and call it, if possible. 1717 // Get function and call it, if possible.
1683 __ movq(RAX, Address(R12, target_offset)); 1718 __ movq(RAX, Address(R12, target_offset));
1684 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); 1719 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1720 __ movq(RCX, FieldAddress(CODE_REG, Code::instructions_offset()));
1685 // RCX: Target instructions. 1721 // RCX: Target instructions.
1686 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 1722 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1687 __ jmp(RCX); 1723 __ jmp(RCX);
1688 1724
1689 if (FLAG_support_debugger) { 1725 if (FLAG_support_debugger) {
1690 __ Bind(&stepping); 1726 __ Bind(&stepping);
1691 __ EnterStubFrame(); 1727 __ EnterStubFrame();
1692 __ pushq(RBX); // Preserve IC data object. 1728 __ pushq(RBX); // Preserve IC data object.
1693 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1729 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1694 __ popq(RBX); 1730 __ popq(RBX);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1727 __ EnterStubFrame(); 1763 __ EnterStubFrame();
1728 __ pushq(R10); // Preserve arguments descriptor array. 1764 __ pushq(R10); // Preserve arguments descriptor array.
1729 __ pushq(RBX); // Preserve IC data object. 1765 __ pushq(RBX); // Preserve IC data object.
1730 __ pushq(RAX); // Pass function. 1766 __ pushq(RAX); // Pass function.
1731 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1767 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1732 __ popq(RAX); // Restore function. 1768 __ popq(RAX); // Restore function.
1733 __ popq(RBX); // Restore IC data array. 1769 __ popq(RBX); // Restore IC data array.
1734 __ popq(R10); // Restore arguments descriptor array. 1770 __ popq(R10); // Restore arguments descriptor array.
1735 __ LeaveStubFrame(); 1771 __ LeaveStubFrame();
1736 1772
1737 __ movq(RAX, FieldAddress(RAX, Function::instructions_offset())); 1773 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1774 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
1738 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 1775 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1739 __ jmp(RAX); 1776 __ jmp(RAX);
1740 } 1777 }
1741 1778
1742 1779
1743 // RBX: Contains an ICData. 1780 // RBX: Contains an ICData.
1744 // TOS(0): return address (Dart code). 1781 // TOS(0): return address (Dart code).
1745 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1782 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1746 __ EnterStubFrame(); 1783 __ EnterStubFrame();
1747 // Preserve IC data. 1784 // Preserve IC data.
1748 __ pushq(RBX); 1785 __ pushq(RBX);
1749 // Room for result. Debugger stub returns address of the 1786 // Room for result. Debugger stub returns address of the
1750 // unpatched runtime stub. 1787 // unpatched runtime stub.
1751 __ LoadObject(R12, Object::null_object(), PP); 1788 __ LoadObject(R12, Object::null_object(), PP);
1752 __ pushq(R12); // Room for result. 1789 __ pushq(R12); // Room for result.
1753 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1790 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1754 __ popq(RAX); // Address of original. 1791 __ popq(CODE_REG); // Address of original.
1755 __ popq(RBX); // Restore IC data. 1792 __ popq(RBX); // Restore IC data.
1756 __ LeaveStubFrame(); 1793 __ LeaveStubFrame();
1794
1795 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
1796 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1757 __ jmp(RAX); // Jump to original stub. 1797 __ jmp(RAX); // Jump to original stub.
1758 } 1798 }
1759 1799
1760 1800
1761 // TOS(0): return address (Dart code). 1801 // TOS(0): return address (Dart code).
1762 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1802 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1763 __ EnterStubFrame(); 1803 __ EnterStubFrame();
1764 // Room for result. Debugger stub returns address of the 1804 // Room for result. Debugger stub returns address of the
1765 // unpatched runtime stub. 1805 // unpatched runtime stub.
1766 __ LoadObject(R12, Object::null_object(), PP); 1806 __ LoadObject(R12, Object::null_object(), PP);
1767 __ pushq(R12); // Room for result. 1807 __ pushq(R12); // Room for result.
1768 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1808 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1769 __ popq(RAX); // Address of original. 1809 __ popq(CODE_REG); // Address of original.
1770 __ LeaveStubFrame(); 1810 __ LeaveStubFrame();
1811
1812 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
1813 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1771 __ jmp(RAX); // Jump to original stub. 1814 __ jmp(RAX); // Jump to original stub.
1772 } 1815 }
1773 1816
1774 1817
1775 // Called only from unoptimized code. 1818 // Called only from unoptimized code.
1776 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { 1819 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
1777 // Check single stepping. 1820 // Check single stepping.
1778 Label stepping, done_stepping; 1821 Label stepping, done_stepping;
1779 __ LoadIsolate(RAX); 1822 __ LoadIsolate(RAX);
1780 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); 1823 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
(...skipping 15 matching lines...) Expand all
1796 // TOS + 1: instantiator type arguments (can be NULL). 1839 // TOS + 1: instantiator type arguments (can be NULL).
1797 // TOS + 2: instance. 1840 // TOS + 2: instance.
1798 // TOS + 3: SubtypeTestCache. 1841 // TOS + 3: SubtypeTestCache.
1799 // Result in RCX: null -> not found, otherwise result (true or false). 1842 // Result in RCX: null -> not found, otherwise result (true or false).
1800 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1843 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1801 ASSERT((1 <= n) && (n <= 3)); 1844 ASSERT((1 <= n) && (n <= 3));
1802 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; 1845 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize;
1803 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; 1846 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
1804 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1847 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1805 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); 1848 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes));
1806 __ LoadObject(R12, Object::null_object(), PP); 1849 __ LoadObject(R9, Object::null_object(), PP);
1807 if (n > 1) { 1850 if (n > 1) {
1808 __ LoadClass(R10, RAX, kNoRegister); 1851 __ LoadClass(R10, RAX, kNoRegister);
1809 // Compute instance type arguments into R13. 1852 // Compute instance type arguments into R13.
1810 Label has_no_type_arguments; 1853 Label has_no_type_arguments;
1811 __ movq(R13, R12); 1854 __ movq(R13, R9);
1812 __ movl(RDI, FieldAddress(R10, 1855 __ movl(RDI, FieldAddress(R10,
1813 Class::type_arguments_field_offset_in_words_offset())); 1856 Class::type_arguments_field_offset_in_words_offset()));
1814 __ cmpl(RDI, Immediate(Class::kNoTypeArguments)); 1857 __ cmpl(RDI, Immediate(Class::kNoTypeArguments));
1815 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1858 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
1816 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0)); 1859 __ movq(R13, FieldAddress(RAX, RDI, TIMES_8, 0));
1817 __ Bind(&has_no_type_arguments); 1860 __ Bind(&has_no_type_arguments);
1818 } 1861 }
1819 __ LoadClassId(R10, RAX); 1862 __ LoadClassId(R10, RAX);
1820 // RAX: instance, R10: instance class id. 1863 // RAX: instance, R10: instance class id.
1821 // R13: instance type arguments or null, used only if n > 1. 1864 // R13: instance type arguments or null, used only if n > 1.
1822 __ movq(RDX, Address(RSP, kCacheOffsetInBytes)); 1865 __ movq(RDX, Address(RSP, kCacheOffsetInBytes));
1823 // RDX: SubtypeTestCache. 1866 // RDX: SubtypeTestCache.
1824 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset())); 1867 __ movq(RDX, FieldAddress(RDX, SubtypeTestCache::cache_offset()));
1825 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag)); 1868 __ addq(RDX, Immediate(Array::data_offset() - kHeapObjectTag));
1826 // RDX: Entry start. 1869 // RDX: Entry start.
1827 // R10: instance class id. 1870 // R10: instance class id.
1828 // R13: instance type arguments. 1871 // R13: instance type arguments.
1829 Label loop, found, not_found, next_iteration; 1872 Label loop, found, not_found, next_iteration;
1830 __ SmiTag(R10); 1873 __ SmiTag(R10);
1831 __ Bind(&loop); 1874 __ Bind(&loop);
1832 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId)); 1875 __ movq(RDI, Address(RDX, kWordSize * SubtypeTestCache::kInstanceClassId));
1833 __ cmpq(RDI, R12); 1876 __ cmpq(RDI, R9);
1834 __ j(EQUAL, &not_found, Assembler::kNearJump); 1877 __ j(EQUAL, &not_found, Assembler::kNearJump);
1835 __ cmpq(RDI, R10); 1878 __ cmpq(RDI, R10);
1836 if (n == 1) { 1879 if (n == 1) {
1837 __ j(EQUAL, &found, Assembler::kNearJump); 1880 __ j(EQUAL, &found, Assembler::kNearJump);
1838 } else { 1881 } else {
1839 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1882 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1840 __ movq(RDI, 1883 __ movq(RDI,
1841 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1884 Address(RDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1842 __ cmpq(RDI, R13); 1885 __ cmpq(RDI, R13);
1843 if (n == 2) { 1886 if (n == 2) {
1844 __ j(EQUAL, &found, Assembler::kNearJump); 1887 __ j(EQUAL, &found, Assembler::kNearJump);
1845 } else { 1888 } else {
1846 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); 1889 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
1847 __ movq(RDI, 1890 __ movq(RDI,
1848 Address(RDX, 1891 Address(RDX,
1849 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments)); 1892 kWordSize * SubtypeTestCache::kInstantiatorTypeArguments));
1850 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes)); 1893 __ cmpq(RDI, Address(RSP, kInstantiatorTypeArgumentsInBytes));
1851 __ j(EQUAL, &found, Assembler::kNearJump); 1894 __ j(EQUAL, &found, Assembler::kNearJump);
1852 } 1895 }
1853 } 1896 }
1854 1897
1855 __ Bind(&next_iteration); 1898 __ Bind(&next_iteration);
1856 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1899 __ addq(RDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1857 __ jmp(&loop, Assembler::kNearJump); 1900 __ jmp(&loop, Assembler::kNearJump);
1858 // Fall through to not found. 1901 // Fall through to not found.
1859 __ Bind(&not_found); 1902 __ Bind(&not_found);
1860 __ movq(RCX, R12); 1903 __ movq(RCX, R9);
1861 __ ret(); 1904 __ ret();
1862 1905
1863 __ Bind(&found); 1906 __ Bind(&found);
1864 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult)); 1907 __ movq(RCX, Address(RDX, kWordSize * SubtypeTestCache::kTestResult));
1865 __ ret(); 1908 __ ret();
1866 } 1909 }
1867 1910
1868 1911
1869 // Used to check class and type arguments. Arguments passed on stack: 1912 // Used to check class and type arguments. Arguments passed on stack:
1870 // TOS + 0: return address. 1913 // TOS + 0: return address.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1953 // RDI: function to be reoptimized. 1996 // RDI: function to be reoptimized.
1954 // R10: argument descriptor (preserved). 1997 // R10: argument descriptor (preserved).
1955 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1998 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1956 __ EnterStubFrame(); 1999 __ EnterStubFrame();
1957 __ LoadObject(R12, Object::null_object(), PP); 2000 __ LoadObject(R12, Object::null_object(), PP);
1958 __ pushq(R10); 2001 __ pushq(R10);
1959 __ pushq(R12); // Setup space on stack for return value. 2002 __ pushq(R12); // Setup space on stack for return value.
1960 __ pushq(RDI); 2003 __ pushq(RDI);
1961 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 2004 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1962 __ popq(RAX); // Disard argument. 2005 __ popq(RAX); // Disard argument.
1963 __ popq(RAX); // Get Code object. 2006 __ popq(CODE_REG); // Get Code object.
1964 __ popq(R10); // Restore argument descriptor. 2007 __ popq(R10); // Restore argument descriptor.
1965 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); 2008 __ movq(RAX, FieldAddress(CODE_REG, Code::instructions_offset()));
1966 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 2009 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1967 __ LeaveStubFrame(); 2010 __ LeaveStubFrame();
1968 __ jmp(RAX); 2011 __ jmp(RAX);
1969 __ int3(); 2012 __ int3();
1970 } 2013 }
1971 2014
1972 2015
1973 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, 2016 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t,
1974 BigintCompare, 2017 BigintCompare,
1975 RawBigint* left, 2018 RawBigint* left,
(...skipping 15 matching lines...) Expand all
1991 // If any of the arguments is Smi do reference compare. 2034 // If any of the arguments is Smi do reference compare.
1992 __ testq(left, Immediate(kSmiTagMask)); 2035 __ testq(left, Immediate(kSmiTagMask));
1993 __ j(ZERO, &reference_compare); 2036 __ j(ZERO, &reference_compare);
1994 __ testq(right, Immediate(kSmiTagMask)); 2037 __ testq(right, Immediate(kSmiTagMask));
1995 __ j(ZERO, &reference_compare); 2038 __ j(ZERO, &reference_compare);
1996 2039
1997 // Value compare for two doubles. 2040 // Value compare for two doubles.
1998 __ CompareClassId(left, kDoubleCid); 2041 __ CompareClassId(left, kDoubleCid);
1999 __ j(NOT_EQUAL, &check_mint, Assembler::kNearJump); 2042 __ j(NOT_EQUAL, &check_mint, Assembler::kNearJump);
2000 __ CompareClassId(right, kDoubleCid); 2043 __ CompareClassId(right, kDoubleCid);
2001 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 2044 __ j(NOT_EQUAL, &done, Assembler::kFarJump);
2002 2045
2003 // Double values bitwise compare. 2046 // Double values bitwise compare.
2004 __ movq(left, FieldAddress(left, Double::value_offset())); 2047 __ movq(left, FieldAddress(left, Double::value_offset()));
2005 __ cmpq(left, FieldAddress(right, Double::value_offset())); 2048 __ cmpq(left, FieldAddress(right, Double::value_offset()));
2006 __ jmp(&done, Assembler::kNearJump); 2049 __ jmp(&done, Assembler::kFarJump);
2007 2050
2008 __ Bind(&check_mint); 2051 __ Bind(&check_mint);
2009 __ CompareClassId(left, kMintCid); 2052 __ CompareClassId(left, kMintCid);
2010 __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump); 2053 __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump);
2011 __ CompareClassId(right, kMintCid); 2054 __ CompareClassId(right, kMintCid);
2012 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 2055 __ j(NOT_EQUAL, &done, Assembler::kFarJump);
2013 __ movq(left, FieldAddress(left, Mint::value_offset())); 2056 __ movq(left, FieldAddress(left, Mint::value_offset()));
2014 __ cmpq(left, FieldAddress(right, Mint::value_offset())); 2057 __ cmpq(left, FieldAddress(right, Mint::value_offset()));
2015 __ jmp(&done, Assembler::kNearJump); 2058 __ jmp(&done, Assembler::kFarJump);
2016 2059
2017 __ Bind(&check_bigint); 2060 __ Bind(&check_bigint);
2018 __ CompareClassId(left, kBigintCid); 2061 __ CompareClassId(left, kBigintCid);
2019 __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump); 2062 __ j(NOT_EQUAL, &reference_compare, Assembler::kFarJump);
2020 __ CompareClassId(right, kBigintCid); 2063 __ CompareClassId(right, kBigintCid);
2021 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 2064 __ j(NOT_EQUAL, &done, Assembler::kFarJump);
2022 __ EnterStubFrame(); 2065 __ EnterStubFrame();
2023 __ ReserveAlignedFrameSpace(0); 2066 __ ReserveAlignedFrameSpace(0);
2024 __ movq(CallingConventions::kArg1Reg, left); 2067 __ movq(CallingConventions::kArg1Reg, left);
2025 __ movq(CallingConventions::kArg2Reg, right); 2068 __ movq(CallingConventions::kArg2Reg, right);
2026 __ CallRuntime(kBigintCompareRuntimeEntry, 2); 2069 __ CallRuntime(kBigintCompareRuntimeEntry, 2);
2027 // Result in RAX, 0 means equal. 2070 // Result in RAX, 0 means equal.
2028 __ LeaveStubFrame(); 2071 __ LeaveStubFrame();
2029 __ cmpq(RAX, Immediate(0)); 2072 __ cmpq(RAX, Immediate(0));
2030 __ jmp(&done); 2073 __ jmp(&done);
2031 2074
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2114 __ j(ZERO, &call_target_function, Assembler::kNearJump); 2157 __ j(ZERO, &call_target_function, Assembler::kNearJump);
2115 __ cmpq(RDX, RAX); 2158 __ cmpq(RDX, RAX);
2116 __ j(NOT_EQUAL, &update, Assembler::kNearJump); 2159 __ j(NOT_EQUAL, &update, Assembler::kNearJump);
2117 2160
2118 __ Bind(&call_target_function); 2161 __ Bind(&call_target_function);
2119 // Call the target found in the cache. For a class id match, this is a 2162 // Call the target found in the cache. For a class id match, this is a
2120 // proper target for the given name and arguments descriptor. If the 2163 // proper target for the given name and arguments descriptor. If the
2121 // illegal class id was found, the target is a cache miss handler that can 2164 // illegal class id was found, the target is a cache miss handler that can
2122 // be invoked as a normal Dart function. 2165 // be invoked as a normal Dart function.
2123 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); 2166 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize));
2124 __ movq(target, FieldAddress(RAX, Function::instructions_offset())); 2167 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
2168 __ movq(target, FieldAddress(CODE_REG, Code::instructions_offset()));
2125 // TODO(srdjan): Evaluate performance impact of moving the instruction below 2169 // TODO(srdjan): Evaluate performance impact of moving the instruction below
2126 // to the call site, instead of having it here. 2170 // to the call site, instead of having it here.
2127 __ AddImmediate( 2171 __ AddImmediate(
2128 target, Immediate(Instructions::HeaderSize() - kHeapObjectTag), PP); 2172 target, Immediate(Instructions::HeaderSize() - kHeapObjectTag), PP);
2129 } 2173 }
2130 2174
2131 2175
2132 // Called from megamorphic calls. 2176 // Called from megamorphic calls.
2133 // RDI: receiver. 2177 // RDI: receiver.
2134 // RBX: lookup cache. 2178 // RBX: lookup cache.
2135 // Result: 2179 // Result:
2136 // RCX: entry point. 2180 // RCX: entry point.
2137 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { 2181 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
2138 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); 2182 EmitMegamorphicLookup(assembler, RDI, RBX, RCX);
2139 __ ret(); 2183 __ ret();
2140 } 2184 }
2141 2185
2142 } // namespace dart 2186 } // namespace dart
2143 2187
2144 #endif // defined TARGET_ARCH_X64 2188 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/code_patcher_x64.cc ('K') | « runtime/vm/stub_code.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698