| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/ic_data.h" | |
| 11 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 12 #include "vm/pages.h" | 11 #include "vm/pages.h" |
| 13 #include "vm/resolver.h" | 12 #include "vm/resolver.h" |
| 14 #include "vm/scavenger.h" | 13 #include "vm/scavenger.h" |
| 15 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
| 16 | 15 |
| 17 | 16 |
| 18 #define __ assembler-> | 17 #define __ assembler-> |
| 19 | 18 |
| 20 namespace dart { | 19 namespace dart { |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 314 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 316 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 315 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 317 __ LeaveFrame(); | 316 __ LeaveFrame(); |
| 318 __ jmp(RAX); | 317 __ jmp(RAX); |
| 319 __ int3(); | 318 __ int3(); |
| 320 } | 319 } |
| 321 | 320 |
| 322 | 321 |
| 323 // Lookup for [function-name, arg count] in 'functions_map_'. | 322 // Lookup for [function-name, arg count] in 'functions_map_'. |
| 324 // Input parameters (to be treated as read only, unless calling to target!): | 323 // Input parameters (to be treated as read only, unless calling to target!): |
| 325 // RBX: ic-data array. | 324 // RBX: ic-data. |
| 326 // R10: arguments descriptor array (num_args is first Smi element). | 325 // R10: arguments descriptor array (num_args is first Smi element). |
| 327 // Stack: return address, arguments. | 326 // Stack: return address, arguments. |
| 328 // If the lookup succeeds we jump to the target method from here, otherwise | 327 // If the lookup succeeds we jump to the target method from here, otherwise |
| 329 // we continue in code generated by the caller of 'MegamorphicLookup'. | 328 // we continue in code generated by the caller of 'MegamorphicLookup'. |
| 330 static void MegamorphicLookup(Assembler* assembler) { | 329 static void MegamorphicLookup(Assembler* assembler) { |
| 331 const Immediate raw_null = | 330 const Immediate raw_null = |
| 332 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 331 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 333 Label class_in_rax, smi_receiver, null_receiver, not_found; | 332 Label class_in_rax, smi_receiver, null_receiver, not_found; |
| 334 // Total number of args is the first Smi in args descriptor array (R10). | 333 // Total number of args is the first Smi in args descriptor array (R10). |
| 335 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 334 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 364 // Iterate and search for identical name. | 363 // Iterate and search for identical name. |
| 365 __ leaq(R12, FieldAddress(RAX, Array::data_offset())); | 364 __ leaq(R12, FieldAddress(RAX, Array::data_offset())); |
| 366 | 365 |
| 367 // R12 is pointing into content of functions_map_ array. | 366 // R12 is pointing into content of functions_map_ array. |
| 368 __ Bind(&loop); | 367 __ Bind(&loop); |
| 369 __ movq(R13, Address(R12, FunctionsCache::kFunctionName * kWordSize)); | 368 __ movq(R13, Address(R12, FunctionsCache::kFunctionName * kWordSize)); |
| 370 | 369 |
| 371 __ cmpq(R13, raw_null); | 370 __ cmpq(R13, raw_null); |
| 372 __ j(EQUAL, ¬_found, Assembler::kNearJump); | 371 __ j(EQUAL, ¬_found, Assembler::kNearJump); |
| 373 | 372 |
| 374 ASSERT(ICData::kNameIndex == 0); | 373 __ cmpq(R13, FieldAddress(RBX, ICData::target_name_offset())); |
| 375 __ cmpq(R13, FieldAddress(RBX, Array::data_offset())); | |
| 376 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 374 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 377 | 375 |
| 378 // Name found, check total argument count and named argument count. | 376 // Name found, check total argument count and named argument count. |
| 379 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 377 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 380 // RAX is total argument count as Smi. | 378 // RAX is total argument count as Smi. |
| 381 __ movq(R13, Address(R12, FunctionsCache::kArgCount * kWordSize)); | 379 __ movq(R13, Address(R12, FunctionsCache::kArgCount * kWordSize)); |
| 382 __ cmpq(RAX, R13); // Compare total argument counts. | 380 __ cmpq(RAX, R13); // Compare total argument counts. |
| 383 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 381 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 384 __ subq(RAX, FieldAddress(R10, Array::data_offset() + kWordSize)); | 382 __ subq(RAX, FieldAddress(R10, Array::data_offset() + kWordSize)); |
| 385 // RAX is named argument count as Smi. | 383 // RAX is named argument count as Smi. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 __ movq(Address(RBX, 0), RAX); | 425 __ movq(Address(RBX, 0), RAX); |
| 428 __ AddImmediate(RBX, Immediate(kWordSize)); | 426 __ AddImmediate(RBX, Immediate(kWordSize)); |
| 429 __ AddImmediate(R12, Immediate(-kWordSize)); | 427 __ AddImmediate(R12, Immediate(-kWordSize)); |
| 430 __ Bind(&loop_condition); | 428 __ Bind(&loop_condition); |
| 431 __ decq(R10); | 429 __ decq(R10); |
| 432 __ j(POSITIVE, &loop, Assembler::kNearJump); | 430 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 433 } | 431 } |
| 434 | 432 |
| 435 | 433 |
| 436 // Input parameters: | 434 // Input parameters: |
| 437 // RBX: ic-data array. | 435 // RBX: ic-data. |
| 438 // R10: arguments descriptor array (num_args is first Smi element). | 436 // R10: arguments descriptor array (num_args is first Smi element). |
| 439 // Note: The receiver object is the first argument to the function being | 437 // Note: The receiver object is the first argument to the function being |
| 440 // called, the stub accesses the receiver from this location directly | 438 // called, the stub accesses the receiver from this location directly |
| 441 // when trying to resolve the call. | 439 // when trying to resolve the call. |
| 442 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 440 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 443 const Immediate raw_null = | 441 const Immediate raw_null = |
| 444 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 442 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 445 | 443 |
| 446 MegamorphicLookup(assembler); | 444 MegamorphicLookup(assembler); |
| 447 // Lookup in function_table_ failed, resolve, compile and enter function | 445 // Lookup in function_table_ failed, resolve, compile and enter function |
| 448 // into function_table_. | 446 // into function_table_. |
| 449 | 447 |
| 450 // Create a stub frame as we are pushing some objects on the stack before | 448 // Create a stub frame as we are pushing some objects on the stack before |
| 451 // calling into the runtime. | 449 // calling into the runtime. |
| 452 __ EnterFrame(0); | 450 __ EnterFrame(0); |
| 453 | 451 |
| 454 // Preserve values across call to resolving. | 452 // Preserve values across call to resolving. |
| 455 // Stack at this point: | 453 // Stack at this point: |
| 456 // TOS + 0: Saved RBP of previous frame. <== RBP | 454 // TOS + 0: Saved RBP of previous frame. <== RBP |
| 457 // TOS + 1: Dart code return address | 455 // TOS + 1: Dart code return address |
| 458 // TOS + 2: Last argument of caller. | 456 // TOS + 2: Last argument of caller. |
| 459 // .... | 457 // .... |
| 460 // Total number of args is the first Smi in args descriptor array (R10). | 458 // Total number of args is the first Smi in args descriptor array (R10). |
| 461 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 459 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 462 __ movq(RAX, Address(RSP, RAX, TIMES_4, kWordSize)); // Get receiver. | 460 __ movq(RAX, Address(RSP, RAX, TIMES_4, kWordSize)); // Get receiver. |
| 463 __ pushq(R10); // Preserve arguments descriptor array. | 461 __ pushq(R10); // Preserve arguments descriptor array. |
| 464 __ pushq(RAX); // Preserve receiver. | 462 __ pushq(RAX); // Preserve receiver. |
| 465 __ pushq(RBX); // Preserve ic-data array. | 463 __ pushq(RBX); // Preserve ic-data. |
| 466 // First resolve the function to get the function object. | 464 // First resolve the function to get the function object. |
| 467 | 465 |
| 468 __ pushq(raw_null); // Setup space on stack for return value. | 466 __ pushq(raw_null); // Setup space on stack for return value. |
| 469 __ pushq(RAX); // Push receiver. | 467 __ pushq(RAX); // Push receiver. |
| 470 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); | 468 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); |
| 471 __ popq(RAX); // Remove receiver pushed earlier. | 469 __ popq(RAX); // Remove receiver pushed earlier. |
| 472 __ popq(RBX); // Pop returned code object into RBX. | 470 __ popq(RBX); // Pop returned code object into RBX. |
| 473 // Pop preserved values | 471 // Pop preserved values |
| 474 __ popq(R10); // Restore ic-data array. | 472 __ popq(R10); // Restore ic-data. |
| 475 __ popq(RAX); // Restore receiver. | 473 __ popq(RAX); // Restore receiver. |
| 476 __ popq(R13); // Restore arguments descriptor array. | 474 __ popq(R13); // Restore arguments descriptor array. |
| 477 | 475 |
| 478 __ cmpq(RBX, raw_null); | 476 __ cmpq(RBX, raw_null); |
| 479 Label check_implicit_closure; | 477 Label check_implicit_closure; |
| 480 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); | 478 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); |
| 481 | 479 |
| 482 // Remove the stub frame as we are about to jump to the dart function. | 480 // Remove the stub frame as we are about to jump to the dart function. |
| 483 __ LeaveFrame(); | 481 __ LeaveFrame(); |
| 484 | 482 |
| 485 __ movq(R10, R13); | 483 __ movq(R10, R13); |
| 486 __ movq(RBX, FieldAddress(RBX, Code::instructions_offset())); | 484 __ movq(RBX, FieldAddress(RBX, Code::instructions_offset())); |
| 487 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 485 __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 488 __ jmp(RBX); | 486 __ jmp(RBX); |
| 489 | 487 |
| 490 __ Bind(&check_implicit_closure); | 488 __ Bind(&check_implicit_closure); |
| 491 // RAX: receiver. | 489 // RAX: receiver. |
| 492 // R10: ic-data array. | 490 // R10: ic-data. |
| 493 // RBX: raw_null. | 491 // RBX: raw_null. |
| 494 // R13: arguments descriptor array. | 492 // R13: arguments descriptor array. |
| 495 // The target function was not found. | 493 // The target function was not found. |
| 496 // First check to see if this is a getter function and we are | 494 // First check to see if this is a getter function and we are |
| 497 // trying to create a closure of an instance function. | 495 // trying to create a closure of an instance function. |
| 498 // Push values that need to be preserved across runtime call. | 496 // Push values that need to be preserved across runtime call. |
| 499 __ pushq(RAX); // Preserve receiver. | 497 __ pushq(RAX); // Preserve receiver. |
| 500 __ pushq(R10); // Preserve ic-data array. | 498 __ pushq(R10); // Preserve ic-data. |
| 501 __ pushq(R13); // Preserve arguments descriptor array. | 499 __ pushq(R13); // Preserve arguments descriptor array. |
| 502 | 500 |
| 503 __ pushq(raw_null); // Setup space on stack for return value. | 501 __ pushq(raw_null); // Setup space on stack for return value. |
| 504 __ pushq(RAX); // Push receiver. | 502 __ pushq(RAX); // Push receiver. |
| 505 __ pushq(R10); // Ic-data array. | 503 __ pushq(R10); // Ic-data array. |
| 506 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); | 504 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); |
| 507 __ popq(RAX); | 505 __ popq(RAX); |
| 508 __ popq(RAX); | 506 __ popq(RAX); |
| 509 __ popq(RBX); // Get return value into RBX, might be Closure object. | 507 __ popq(RBX); // Get return value into RBX, might be Closure object. |
| 510 | 508 |
| 511 // Pop preserved values. | 509 // Pop preserved values. |
| 512 __ popq(R13); // Restore arguments descriptor array. | 510 __ popq(R13); // Restore arguments descriptor array. |
| 513 __ popq(R10); // Restore ic-data array. | 511 __ popq(R10); // Restore ic-data. |
| 514 __ popq(RAX); // Restore receiver. | 512 __ popq(RAX); // Restore receiver. |
| 515 | 513 |
| 516 __ cmpq(RBX, raw_null); | 514 __ cmpq(RBX, raw_null); |
| 517 Label check_implicit_closure_through_getter; | 515 Label check_implicit_closure_through_getter; |
| 518 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); | 516 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); |
| 519 | 517 |
| 520 __ movq(RAX, RBX); // Return value is the closure object. | 518 __ movq(RAX, RBX); // Return value is the closure object. |
| 521 // Remove the stub frame as we are about return. | 519 // Remove the stub frame as we are about return. |
| 522 __ LeaveFrame(); | 520 __ LeaveFrame(); |
| 523 __ ret(); | 521 __ ret(); |
| 524 | 522 |
| 525 __ Bind(&check_implicit_closure_through_getter); | 523 __ Bind(&check_implicit_closure_through_getter); |
| 526 // RAX: receiver. | 524 // RAX: receiver. |
| 527 // R10: ic-data array. | 525 // R10: ic-data. |
| 528 // RBX: raw_null. | 526 // RBX: raw_null. |
| 529 // R13: arguments descriptor array. | 527 // R13: arguments descriptor array. |
| 530 // This is not the case of an instance so invoke the getter of the | 528 // This is not the case of an instance so invoke the getter of the |
| 531 // same name and see if we get a closure back which we are then | 529 // same name and see if we get a closure back which we are then |
| 532 // supposed to invoke. | 530 // supposed to invoke. |
| 533 // Push values that need to be preserved across runtime call. | 531 // Push values that need to be preserved across runtime call. |
| 534 __ pushq(RAX); // Preserve receiver. | 532 __ pushq(RAX); // Preserve receiver. |
| 535 __ pushq(R10); // Preserve ic-data array. | 533 __ pushq(R10); // Preserve ic-data. |
| 536 __ pushq(R13); // Preserve arguments descriptor array. | 534 __ pushq(R13); // Preserve arguments descriptor array. |
| 537 | 535 |
| 538 __ pushq(raw_null); // Setup space on stack for return value. | 536 __ pushq(raw_null); // Setup space on stack for return value. |
| 539 __ pushq(RAX); // Push receiver. | 537 __ pushq(RAX); // Push receiver. |
| 540 __ pushq(R10); // Ic-data array. | 538 __ pushq(R10); // Ic-data array. |
| 541 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); | 539 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); |
| 542 __ popq(R10); // Pop argument. | 540 __ popq(R10); // Pop argument. |
| 543 __ popq(RAX); // Pop argument. | 541 __ popq(RAX); // Pop argument. |
| 544 __ popq(RBX); // get return value into RBX, might be Closure object. | 542 __ popq(RBX); // get return value into RBX, might be Closure object. |
| 545 | 543 |
| 546 // Pop preserved values. | 544 // Pop preserved values. |
| 547 __ popq(R13); // Restore arguments descriptor array. | 545 __ popq(R13); // Restore arguments descriptor array. |
| 548 __ popq(R10); // Restore ic-data array. | 546 __ popq(R10); // Restore ic-data. |
| 549 __ popq(RAX); // Restore receiver. | 547 __ popq(RAX); // Restore receiver. |
| 550 | 548 |
| 551 __ cmpq(RBX, raw_null); | 549 __ cmpq(RBX, raw_null); |
| 552 Label function_not_found; | 550 Label function_not_found; |
| 553 __ j(EQUAL, &function_not_found); | 551 __ j(EQUAL, &function_not_found); |
| 554 | 552 |
| 555 // RBX: Closure object. | 553 // RBX: Closure object. |
| 556 // R13: Arguments descriptor array. | 554 // R13: Arguments descriptor array. |
| 557 __ pushq(raw_null); // Setup space on stack for result from invoking Closure. | 555 __ pushq(raw_null); // Setup space on stack for result from invoking Closure. |
| 558 __ pushq(RBX); // Closure object. | 556 __ pushq(RBX); // Closure object. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 579 __ popq(RAX); // Get result into RAX. | 577 __ popq(RAX); // Get result into RAX. |
| 580 | 578 |
| 581 // Remove the stub frame as we are about to return. | 579 // Remove the stub frame as we are about to return. |
| 582 __ LeaveFrame(); | 580 __ LeaveFrame(); |
| 583 __ ret(); | 581 __ ret(); |
| 584 | 582 |
| 585 __ Bind(&function_not_found); | 583 __ Bind(&function_not_found); |
| 586 // The target function was not found, so invoke method | 584 // The target function was not found, so invoke method |
| 587 // "void noSuchMethod(function_name, args_array)". | 585 // "void noSuchMethod(function_name, args_array)". |
| 588 // RAX: receiver. | 586 // RAX: receiver. |
| 589 // R10: ic-data array. | 587 // R10: ic-data. |
| 590 // RBX: raw_null. | 588 // RBX: raw_null. |
| 591 // R13: argument descriptor array. | 589 // R13: argument descriptor array. |
| 592 | 590 |
| 593 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. | 591 __ pushq(raw_null); // Setup space on stack for result from noSuchMethod. |
| 594 __ pushq(RAX); // Receiver. | 592 __ pushq(RAX); // Receiver. |
| 595 __ pushq(R10); // IC-data array. | 593 __ pushq(R10); // IC-data array. |
| 596 __ pushq(R13); // Argument descriptor array. | 594 __ pushq(R13); // Argument descriptor array. |
| 597 __ movq(R13, FieldAddress(R13, Array::data_offset())); | 595 __ movq(R13, FieldAddress(R13, Array::data_offset())); |
| 598 __ SmiUntag(R13); | 596 __ SmiUntag(R13); |
| 599 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. | 597 __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver. |
| (...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 } | 1472 } |
| 1475 | 1473 |
| 1476 | 1474 |
| 1477 // Called for invoking noSuchMethod function from the entry code of a dart | 1475 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1478 // function after an error in passed named arguments is detected. | 1476 // function after an error in passed named arguments is detected. |
| 1479 // Input parameters: | 1477 // Input parameters: |
| 1480 // RBP : points to previous frame pointer. | 1478 // RBP : points to previous frame pointer. |
| 1481 // RBP + 8 : points to return address. | 1479 // RBP + 8 : points to return address. |
| 1482 // RBP + 16 : address of last argument (arg n-1). | 1480 // RBP + 16 : address of last argument (arg n-1). |
| 1483 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). | 1481 // RBP + 16 + 8*(n-1) : address of first argument (arg 0). |
| 1484 // RBX : ic-data array. | 1482 // RBX : ic-data. |
| 1485 // R10 : arguments descriptor array. | 1483 // R10 : arguments descriptor array. |
| 1486 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1484 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1487 // The target function was not found, so invoke method | 1485 // The target function was not found, so invoke method |
| 1488 // "void noSuchMethod(function_name, Array arguments)". | 1486 // "void noSuchMethod(function_name, Array arguments)". |
| 1489 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1487 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1490 // and named, as the argument array. This is not correct if out-of-order | 1488 // and named, as the argument array. This is not correct if out-of-order |
| 1491 // named arguments were passed. | 1489 // named arguments were passed. |
| 1492 // The signature of the "noSuchMethod" method has to change from | 1490 // The signature of the "noSuchMethod" method has to change from |
| 1493 // noSuchMethod(String name, Array arguments) to something like | 1491 // noSuchMethod(String name, Array arguments) to something like |
| 1494 // noSuchMethod(InvocationMirror call). | 1492 // noSuchMethod(InvocationMirror call). |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1530 __ popq(RAX); // Get result into RAX. | 1528 __ popq(RAX); // Get result into RAX. |
| 1531 | 1529 |
| 1532 // Remove the stub frame as we are about to return. | 1530 // Remove the stub frame as we are about to return. |
| 1533 __ LeaveFrame(); | 1531 __ LeaveFrame(); |
| 1534 __ ret(); | 1532 __ ret(); |
| 1535 } | 1533 } |
| 1536 | 1534 |
| 1537 | 1535 |
| 1538 | 1536 |
| 1539 // Generate inline cache check for 'num_args'. | 1537 // Generate inline cache check for 'num_args'. |
| 1540 // RBX: Inline cache data array. | 1538 // RBX: Inline cache data object. |
| 1541 // R10: Arguments array. | 1539 // R10: Arguments array. |
| 1542 // TOS(0): return address | 1540 // TOS(0): return address |
| 1543 // Control flow: | 1541 // Control flow: |
| 1544 // - If receiver is null -> jump to IC miss. | 1542 // - If receiver is null -> jump to IC miss. |
| 1545 // - If receiver is Smi -> load Smi class. | 1543 // - If receiver is Smi -> load Smi class. |
| 1546 // - If receiver is not-Smi -> load receiver's class. | 1544 // - If receiver is not-Smi -> load receiver's class. |
| 1547 // - Check if 'num_args' (including receiver) match any IC data group. | 1545 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1548 // - Match found -> jump to target. | 1546 // - Match found -> jump to target. |
| 1549 // - Match not found -> jump to IC miss. | 1547 // - Match not found -> jump to IC miss. |
| 1550 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1548 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1551 intptr_t num_args) { | 1549 intptr_t num_args) { |
| 1552 ASSERT(num_args > 0); | 1550 ASSERT(num_args > 0); |
| 1553 // Get receiver. | 1551 // Get receiver. |
| 1554 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1552 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 1555 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1553 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. |
| 1556 | 1554 |
| 1557 Label get_class, ic_miss; | 1555 Label get_class, ic_miss; |
| 1558 __ call(&get_class); | 1556 __ call(&get_class); |
| 1559 // RAX: receiver's class | 1557 // RAX: receiver's class |
| 1560 // RBX: IC data array. | 1558 // RBX: IC data array. |
| 1561 | 1559 |
| 1562 #if defined(DEBUG) | 1560 #if defined(DEBUG) |
| 1563 { Label ok; | 1561 { Label ok; |
| 1564 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1562 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1565 __ movq(RCX, FieldAddress(RBX, | 1563 // 'num_args_tested' is stored as an untagged int. |
| 1566 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); | 1564 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
| 1567 const Immediate value = | 1565 __ cmpq(RCX, Immediate(num_args)); |
| 1568 Immediate(reinterpret_cast<int64_t>(Smi::New(num_args))); | |
| 1569 __ cmpq(RCX, value); | |
| 1570 __ j(EQUAL, &ok, Assembler::kNearJump); | 1566 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1571 __ Stop("Incorrect stub for IC data"); | 1567 __ Stop("Incorrect stub for IC data"); |
| 1572 __ Bind(&ok); | 1568 __ Bind(&ok); |
| 1573 } | 1569 } |
| 1574 #endif // DEBUG | 1570 #endif // DEBUG |
| 1575 | 1571 |
| 1576 // Loop that checks if there is an IC data match. | 1572 // Loop that checks if there is an IC data match. |
| 1577 // RAX: receiver's class. | 1573 // RAX: receiver's class. |
| 1578 // RBX: IC data array (preserved). | 1574 // RBX: IC data object (preserved). |
| 1579 __ leaq(R12, FieldAddress(RBX, | 1575 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1580 Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); | 1576 // R12: ic_data_array with check entries: classes and target functions. |
| 1581 // R12: pointing to a class to check against (into IC data array). | 1577 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1578 // R12: points directly to the first ic data array element. |
| 1582 const Immediate raw_null = | 1579 const Immediate raw_null = |
| 1583 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1580 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1584 Label loop, found; | 1581 Label loop, found; |
| 1585 if (num_args == 1) { | 1582 if (num_args == 1) { |
| 1586 __ Bind(&loop); | 1583 __ Bind(&loop); |
| 1587 __ movq(R13, Address(R12, 0)); // Get class to check. | 1584 __ movq(R13, Address(R12, 0)); // Get class to check. |
| 1588 __ cmpq(RAX, R13); // Match? | 1585 __ cmpq(RAX, R13); // Match? |
| 1589 __ j(EQUAL, &found, Assembler::kNearJump); | 1586 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1590 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). | 1587 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1591 __ cmpq(R13, raw_null); // Done? | 1588 __ cmpq(R13, raw_null); // Done? |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 __ popq(R10); | 1727 __ popq(R10); |
| 1731 __ popq(RBX); | 1728 __ popq(RBX); |
| 1732 __ LeaveFrame(); | 1729 __ LeaveFrame(); |
| 1733 // Now call the dynamic function. | 1730 // Now call the dynamic function. |
| 1734 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1731 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1735 } | 1732 } |
| 1736 | 1733 |
| 1737 } // namespace dart | 1734 } // namespace dart |
| 1738 | 1735 |
| 1739 #endif // defined TARGET_ARCH_X64 | 1736 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |