| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 307 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 309 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 308 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 310 __ LeaveFrame(); | 309 __ LeaveFrame(); |
| 311 __ jmp(EAX); | 310 __ jmp(EAX); |
| 312 __ int3(); | 311 __ int3(); |
| 313 } | 312 } |
| 314 | 313 |
| 315 | 314 |
| 316 // Lookup for [function-name, arg count] in 'functions_map_'. | 315 // Lookup for [function-name, arg count] in 'functions_map_'. |
| 317 // Input parameters (to be treated as read only, unless calling to target!): | 316 // Input parameters (to be treated as read only, unless calling to target!): |
| 318 // ECX: ic-data array. | 317 // ECX: ic-data. |
| 319 // EDX: arguments descriptor array (num_args is first Smi element). | 318 // EDX: arguments descriptor array (num_args is first Smi element). |
| 320 // Stack: return address, arguments. | 319 // Stack: return address, arguments. |
| 321 // If the lookup succeeds we jump to the target method from here, otherwise | 320 // If the lookup succeeds we jump to the target method from here, otherwise |
| 322 // we continue in code generated by the caller of 'MegamorphicLookup'. | 321 // we continue in code generated by the caller of 'MegamorphicLookup'. |
| 323 static void MegamorphicLookup(Assembler* assembler) { | 322 static void MegamorphicLookup(Assembler* assembler) { |
| 324 const Immediate raw_null = | 323 const Immediate raw_null = |
| 325 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 324 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 326 Label class_in_eax, smi_receiver, null_receiver, not_found; | 325 Label class_in_eax, smi_receiver, null_receiver, not_found; |
| 327 // Total number of args is the first Smi in args descriptor array (EDX). | 326 // Total number of args is the first Smi in args descriptor array (EDX). |
| 328 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 327 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 357 // Iterate and search for identical name. | 356 // Iterate and search for identical name. |
| 358 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); | 357 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); |
| 359 | 358 |
| 360 // EBX is pointing into content of functions_map_ array. | 359 // EBX is pointing into content of functions_map_ array. |
| 361 __ Bind(&loop); | 360 __ Bind(&loop); |
| 362 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); | 361 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); |
| 363 | 362 |
| 364 __ cmpl(EDI, raw_null); | 363 __ cmpl(EDI, raw_null); |
| 365 __ j(EQUAL, ¬_found, Assembler::kNearJump); | 364 __ j(EQUAL, ¬_found, Assembler::kNearJump); |
| 366 | 365 |
| 367 ASSERT(ICData::kNameIndex == 0); | 366 __ cmpl(EDI, FieldAddress(ECX, ICData::target_name_offset())); |
| 368 __ cmpl(EDI, FieldAddress(ECX, Array::data_offset())); | |
| 369 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 367 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 370 | 368 |
| 371 // Name found, check total argument count and named argument count. | 369 // Name found, check total argument count and named argument count. |
| 372 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 370 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 373 // EAX is total argument count as Smi. | 371 // EAX is total argument count as Smi. |
| 374 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); | 372 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); |
| 375 __ cmpl(EAX, EDI); // Compare total argument counts. | 373 __ cmpl(EAX, EDI); // Compare total argument counts. |
| 376 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 374 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 377 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); | 375 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); |
| 378 // EAX is named argument count as Smi. | 376 // EAX is named argument count as Smi. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 __ movl(Address(ECX, 0), EAX); | 419 __ movl(Address(ECX, 0), EAX); |
| 422 __ AddImmediate(ECX, Immediate(kWordSize)); | 420 __ AddImmediate(ECX, Immediate(kWordSize)); |
| 423 __ AddImmediate(EBX, Immediate(-kWordSize)); | 421 __ AddImmediate(EBX, Immediate(-kWordSize)); |
| 424 __ Bind(&loop_condition); | 422 __ Bind(&loop_condition); |
| 425 __ decl(EDX); | 423 __ decl(EDX); |
| 426 __ j(POSITIVE, &loop, Assembler::kNearJump); | 424 __ j(POSITIVE, &loop, Assembler::kNearJump); |
| 427 } | 425 } |
| 428 | 426 |
| 429 | 427 |
| 430 // Input parameters: | 428 // Input parameters: |
| 431 // ECX: ic-data array. | 429 // ECX: ic-data. |
| 432 // EDX: arguments descriptor array (num_args is first Smi element). | 430 // EDX: arguments descriptor array (num_args is first Smi element). |
| 433 // Note: The receiver object is the first argument to the function being | 431 // Note: The receiver object is the first argument to the function being |
| 434 // called, the stub accesses the receiver from this location directly | 432 // called, the stub accesses the receiver from this location directly |
| 435 // when trying to resolve the call. | 433 // when trying to resolve the call. |
| 436 // Uses EDI. | 434 // Uses EDI. |
| 437 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 435 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
| 438 const Immediate raw_null = | 436 const Immediate raw_null = |
| 439 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 437 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 440 | 438 |
| 441 MegamorphicLookup(assembler); | 439 MegamorphicLookup(assembler); |
| 442 // Lookup in function_table_ failed, resolve, compile and enter function | 440 // Lookup in function_table_ failed, resolve, compile and enter function |
| 443 // into function_table_. | 441 // into function_table_. |
| 444 | 442 |
| 445 // Create a stub frame as we are pushing some objects on the stack before | 443 // Create a stub frame as we are pushing some objects on the stack before |
| 446 // calling into the runtime. | 444 // calling into the runtime. |
| 447 __ EnterFrame(0); | 445 __ EnterFrame(0); |
| 448 | 446 |
| 449 // Preserve values across call to resolving. | 447 // Preserve values across call to resolving. |
| 450 // Stack at this point: | 448 // Stack at this point: |
| 451 // TOS + 0: Saved EBP of previous frame. <== EBP | 449 // TOS + 0: Saved EBP of previous frame. <== EBP |
| 452 // TOS + 1: Dart code return address | 450 // TOS + 1: Dart code return address |
| 453 // TOS + 2: Last argument of caller. | 451 // TOS + 2: Last argument of caller. |
| 454 // .... | 452 // .... |
| 455 // Total number of args is the first Smi in args descriptor array (EDX). | 453 // Total number of args is the first Smi in args descriptor array (EDX). |
| 456 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 454 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 457 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. | 455 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Get receiver. |
| 458 __ pushl(EDX); // Preserve arguments descriptor array. | 456 __ pushl(EDX); // Preserve arguments descriptor array. |
| 459 __ pushl(EAX); // Preserve receiver. | 457 __ pushl(EAX); // Preserve receiver. |
| 460 __ pushl(ECX); // Preserve ic-data array. | 458 __ pushl(ECX); // Preserve ic-data. |
| 461 // First resolve the function to get the function object. | 459 // First resolve the function to get the function object. |
| 462 | 460 |
| 463 __ pushl(raw_null); // Setup space on stack for return value. | 461 __ pushl(raw_null); // Setup space on stack for return value. |
| 464 __ pushl(EAX); // Push receiver. | 462 __ pushl(EAX); // Push receiver. |
| 465 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); | 463 __ CallRuntimeFromStub(kResolveCompileInstanceFunctionRuntimeEntry); |
| 466 __ popl(EAX); // Remove receiver pushed earlier. | 464 __ popl(EAX); // Remove receiver pushed earlier. |
| 467 __ popl(ECX); // Pop returned code object into ECX. | 465 __ popl(ECX); // Pop returned code object into ECX. |
| 468 // Pop preserved values | 466 // Pop preserved values |
| 469 __ popl(EDX); // Restore ic-data array. | 467 __ popl(EDX); // Restore ic-data. |
| 470 __ popl(EAX); // Restore receiver. | 468 __ popl(EAX); // Restore receiver. |
| 471 __ popl(EDI); // Restore arguments descriptor array. | 469 __ popl(EDI); // Restore arguments descriptor array. |
| 472 | 470 |
| 473 __ cmpl(ECX, raw_null); | 471 __ cmpl(ECX, raw_null); |
| 474 Label check_implicit_closure; | 472 Label check_implicit_closure; |
| 475 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); | 473 __ j(EQUAL, &check_implicit_closure, Assembler::kNearJump); |
| 476 | 474 |
| 477 // Remove the stub frame as we are about to jump to the dart function. | 475 // Remove the stub frame as we are about to jump to the dart function. |
| 478 __ LeaveFrame(); | 476 __ LeaveFrame(); |
| 479 | 477 |
| 480 __ movl(EDX, EDI); | 478 __ movl(EDX, EDI); |
| 481 __ movl(ECX, FieldAddress(ECX, Code::instructions_offset())); | 479 __ movl(ECX, FieldAddress(ECX, Code::instructions_offset())); |
| 482 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 480 __ addl(ECX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 483 __ jmp(ECX); | 481 __ jmp(ECX); |
| 484 | 482 |
| 485 __ Bind(&check_implicit_closure); | 483 __ Bind(&check_implicit_closure); |
| 486 // EAX: receiver. | 484 // EAX: receiver. |
| 487 // EDX: ic-data array. | 485 // EDX: ic-data. |
| 488 // ECX: raw_null. | 486 // ECX: raw_null. |
| 489 // EDI: arguments descriptor array. | 487 // EDI: arguments descriptor array. |
| 490 // The target function was not found. | 488 // The target function was not found. |
| 491 // First check to see if this is a getter function and we are | 489 // First check to see if this is a getter function and we are |
| 492 // trying to create a closure of an instance function. | 490 // trying to create a closure of an instance function. |
| 493 // Push values that need to be preserved across runtime call. | 491 // Push values that need to be preserved across runtime call. |
| 494 __ pushl(EAX); // Preserve receiver. | 492 __ pushl(EAX); // Preserve receiver. |
| 495 __ pushl(EDX); // Preserve ic-data array. | 493 __ pushl(EDX); // Preserve ic-data. |
| 496 __ pushl(EDI); // Preserve arguments descriptor array. | 494 __ pushl(EDI); // Preserve arguments descriptor array. |
| 497 | 495 |
| 498 __ pushl(raw_null); // Setup space on stack for return value. | 496 __ pushl(raw_null); // Setup space on stack for return value. |
| 499 __ pushl(EAX); // Push receiver. | 497 __ pushl(EAX); // Push receiver. |
| 500 __ pushl(EDX); // Ic-data array. | 498 __ pushl(EDX); // Ic-data. |
| 501 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); | 499 __ CallRuntimeFromStub(kResolveImplicitClosureFunctionRuntimeEntry); |
| 502 __ popl(EAX); | 500 __ popl(EAX); |
| 503 __ popl(EAX); | 501 __ popl(EAX); |
| 504 __ popl(ECX); // Get return value into ECX, might be Closure object. | 502 __ popl(ECX); // Get return value into ECX, might be Closure object. |
| 505 | 503 |
| 506 // Pop preserved values. | 504 // Pop preserved values. |
| 507 __ popl(EDI); // Restore arguments descriptor array. | 505 __ popl(EDI); // Restore arguments descriptor array. |
| 508 __ popl(EDX); // Restore ic-data array. | 506 __ popl(EDX); // Restore ic-data. |
| 509 __ popl(EAX); // Restore receiver. | 507 __ popl(EAX); // Restore receiver. |
| 510 | 508 |
| 511 __ cmpl(ECX, raw_null); | 509 __ cmpl(ECX, raw_null); |
| 512 Label check_implicit_closure_through_getter; | 510 Label check_implicit_closure_through_getter; |
| 513 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); | 511 __ j(EQUAL, &check_implicit_closure_through_getter, Assembler::kNearJump); |
| 514 | 512 |
| 515 __ movl(EAX, ECX); // Return value is the closure object. | 513 __ movl(EAX, ECX); // Return value is the closure object. |
| 516 // Remove the stub frame as we are about return. | 514 // Remove the stub frame as we are about return. |
| 517 __ LeaveFrame(); | 515 __ LeaveFrame(); |
| 518 __ ret(); | 516 __ ret(); |
| 519 | 517 |
| 520 __ Bind(&check_implicit_closure_through_getter); | 518 __ Bind(&check_implicit_closure_through_getter); |
| 521 // EAX: receiver. | 519 // EAX: receiver. |
| 522 // EDX: ic-data array. | 520 // EDX: ic-data. |
| 523 // ECX: raw_null. | 521 // ECX: raw_null. |
| 524 // EDI: arguments descriptor array. | 522 // EDI: arguments descriptor array. |
| 525 // This is not the case of an instance so invoke the getter of the | 523 // This is not the case of an instance so invoke the getter of the |
| 526 // same name and see if we get a closure back which we are then | 524 // same name and see if we get a closure back which we are then |
| 527 // supposed to invoke. | 525 // supposed to invoke. |
| 528 // Push values that need to be preserved across runtime call. | 526 // Push values that need to be preserved across runtime call. |
| 529 __ pushl(EAX); // Preserve receiver. | 527 __ pushl(EAX); // Preserve receiver. |
| 530 __ pushl(EDX); // Preserve ic-data array. | 528 __ pushl(EDX); // Preserve ic-data. |
| 531 __ pushl(EDI); // Preserve arguments descriptor array. | 529 __ pushl(EDI); // Preserve arguments descriptor array. |
| 532 | 530 |
| 533 __ pushl(raw_null); // Setup space on stack for return value. | 531 __ pushl(raw_null); // Setup space on stack for return value. |
| 534 __ pushl(EAX); // Push receiver. | 532 __ pushl(EAX); // Push receiver. |
| 535 __ pushl(EDX); // Ic-data array. | 533 __ pushl(EDX); // Ic-data. |
| 536 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); | 534 __ CallRuntimeFromStub(kResolveImplicitClosureThroughGetterRuntimeEntry); |
| 537 __ popl(EDX); // Pop argument. | 535 __ popl(EDX); // Pop argument. |
| 538 __ popl(EAX); // Pop argument. | 536 __ popl(EAX); // Pop argument. |
| 539 __ popl(ECX); // get return value into ECX, might be Closure object. | 537 __ popl(ECX); // get return value into ECX, might be Closure object. |
| 540 | 538 |
| 541 // Pop preserved values. | 539 // Pop preserved values. |
| 542 __ popl(EDI); // Restore arguments descriptor array. | 540 __ popl(EDI); // Restore arguments descriptor array. |
| 543 __ popl(EDX); // Restore ic-data array. | 541 __ popl(EDX); // Restore ic-data. |
| 544 __ popl(EAX); // Restore receiver. | 542 __ popl(EAX); // Restore receiver. |
| 545 | 543 |
| 546 __ cmpl(ECX, raw_null); | 544 __ cmpl(ECX, raw_null); |
| 547 Label function_not_found; | 545 Label function_not_found; |
| 548 __ j(EQUAL, &function_not_found, Assembler::kNearJump); | 546 __ j(EQUAL, &function_not_found, Assembler::kNearJump); |
| 549 | 547 |
| 550 // ECX: Closure object. | 548 // ECX: Closure object. |
| 551 // EDI: Arguments descriptor array. | 549 // EDI: Arguments descriptor array. |
| 552 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. | 550 __ pushl(raw_null); // Setup space on stack for result from invoking Closure. |
| 553 __ pushl(ECX); // Closure object. | 551 __ pushl(ECX); // Closure object. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 574 __ popl(EAX); // Get result into EAX. | 572 __ popl(EAX); // Get result into EAX. |
| 575 | 573 |
| 576 // Remove the stub frame as we are about to return. | 574 // Remove the stub frame as we are about to return. |
| 577 __ LeaveFrame(); | 575 __ LeaveFrame(); |
| 578 __ ret(); | 576 __ ret(); |
| 579 | 577 |
| 580 __ Bind(&function_not_found); | 578 __ Bind(&function_not_found); |
| 581 // The target function was not found, so invoke method | 579 // The target function was not found, so invoke method |
| 582 // "void noSuchMethod(function_name, args_array)". | 580 // "void noSuchMethod(function_name, args_array)". |
| 583 // EAX: receiver. | 581 // EAX: receiver. |
| 584 // EDX: ic-data array. | 582 // EDX: ic-data. |
| 585 // ECX: raw_null. | 583 // ECX: raw_null. |
| 586 // EDI: argument descriptor array. | 584 // EDI: argument descriptor array. |
| 587 | 585 |
| 588 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. | 586 __ pushl(raw_null); // Setup space on stack for result from noSuchMethod. |
| 589 __ pushl(EAX); // Receiver. | 587 __ pushl(EAX); // Receiver. |
| 590 __ pushl(EDX); // IC-data array. | 588 __ pushl(EDX); // IC-data. |
| 591 __ pushl(EDI); // Argument descriptor array. | 589 __ pushl(EDI); // Argument descriptor array. |
| 592 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); | 590 __ movl(EDI, FieldAddress(EDI, Array::data_offset())); |
| 593 __ SmiUntag(EDI); | 591 __ SmiUntag(EDI); |
| 594 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 592 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 595 // See stack layout below explaining "wordSize * 6" offset. | 593 // See stack layout below explaining "wordSize * 6" offset. |
| 596 PushArgumentsArray(assembler, (kWordSize * 6)); | 594 PushArgumentsArray(assembler, (kWordSize * 6)); |
| 597 | 595 |
| 598 // Stack: | 596 // Stack: |
| 599 // TOS + 0: Argument array. | 597 // TOS + 0: Argument array. |
| 600 // TOS + 1: Argument descriptor array. | 598 // TOS + 1: Argument descriptor array. |
| 601 // TOS + 2: IC-data array. | 599 // TOS + 2: IC-data. |
| 602 // TOS + 3: Receiver. | 600 // TOS + 3: Receiver. |
| 603 // TOS + 4: Place for result from noSuchMethod. | 601 // TOS + 4: Place for result from noSuchMethod. |
| 604 // TOS + 5: Saved EBP of previous frame. <== EBP | 602 // TOS + 5: Saved EBP of previous frame. <== EBP |
| 605 // TOS + 6: Dart code return address | 603 // TOS + 6: Dart code return address |
| 606 // TOS + 7: Last argument of caller. | 604 // TOS + 7: Last argument of caller. |
| 607 // .... | 605 // .... |
| 608 | 606 |
| 609 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); | 607 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 610 // Remove arguments. | 608 // Remove arguments. |
| 611 __ popl(EAX); | 609 __ popl(EAX); |
| (...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 } | 1470 } |
| 1473 | 1471 |
| 1474 | 1472 |
| 1475 // Called for invoking noSuchMethod function from the entry code of a dart | 1473 // Called for invoking noSuchMethod function from the entry code of a dart |
| 1476 // function after an error in passed named arguments is detected. | 1474 // function after an error in passed named arguments is detected. |
| 1477 // Input parameters: | 1475 // Input parameters: |
| 1478 // EBP : points to previous frame pointer. | 1476 // EBP : points to previous frame pointer. |
| 1479 // EBP + 4 : points to return address. | 1477 // EBP + 4 : points to return address. |
| 1480 // EBP + 8 : address of last argument (arg n-1). | 1478 // EBP + 8 : address of last argument (arg n-1). |
| 1481 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). | 1479 // EBP + 8 + 4*(n-1) : address of first argument (arg 0). |
| 1482 // ECX : ic-data array. | 1480 // ECX : ic-data. |
| 1483 // EDX : arguments descriptor array. | 1481 // EDX : arguments descriptor array. |
| 1484 // Uses EAX, EBX, EDI as temporary registers. | 1482 // Uses EAX, EBX, EDI as temporary registers. |
| 1485 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { | 1483 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { |
| 1486 // The target function was not found, so invoke method | 1484 // The target function was not found, so invoke method |
| 1487 // "void noSuchMethod(function_name, Array arguments)". | 1485 // "void noSuchMethod(function_name, Array arguments)". |
| 1488 // TODO(regis): For now, we simply pass the actual arguments, both positional | 1486 // TODO(regis): For now, we simply pass the actual arguments, both positional |
| 1489 // and named, as the argument array. This is not correct if out-of-order | 1487 // and named, as the argument array. This is not correct if out-of-order |
| 1490 // named arguments were passed. | 1488 // named arguments were passed. |
| 1491 // The signature of the "noSuchMethod" method has to change from | 1489 // The signature of the "noSuchMethod" method has to change from |
| 1492 // noSuchMethod(String name, Array arguments) to something like | 1490 // noSuchMethod(String name, Array arguments) to something like |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1504 __ pushl(EAX); // Receiver. | 1502 __ pushl(EAX); // Receiver. |
| 1505 __ pushl(ECX); // IC data array. | 1503 __ pushl(ECX); // IC data array. |
| 1506 __ pushl(EDX); // Arguments descriptor array. | 1504 __ pushl(EDX); // Arguments descriptor array. |
| 1507 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. | 1505 __ subl(EDI, Immediate(1)); // Arguments array length, minus the receiver. |
| 1508 // See stack layout below explaining "wordSize * 8" offset. | 1506 // See stack layout below explaining "wordSize * 8" offset. |
| 1509 PushArgumentsArray(assembler, (kWordSize * 8)); | 1507 PushArgumentsArray(assembler, (kWordSize * 8)); |
| 1510 | 1508 |
| 1511 // Stack: | 1509 // Stack: |
| 1512 // TOS + 0: Argument array. | 1510 // TOS + 0: Argument array. |
| 1513 // TOS + 1: Arguments descriptor array. | 1511 // TOS + 1: Arguments descriptor array. |
| 1514 // TOS + 2: Ic-data array. | 1512 // TOS + 2: Ic-data. |
| 1515 // TOS + 3: Receiver. | 1513 // TOS + 3: Receiver. |
| 1516 // TOS + 4: Place for result from noSuchMethod. | 1514 // TOS + 4: Place for result from noSuchMethod. |
| 1517 // TOS + 5: Saved EBP of previous frame. <== EBP | 1515 // TOS + 5: Saved EBP of previous frame. <== EBP |
| 1518 // TOS + 6: Dart callee (or stub) code return address | 1516 // TOS + 6: Dart callee (or stub) code return address |
| 1519 // TOS + 7: Saved EBP of dart caller frame. | 1517 // TOS + 7: Saved EBP of dart caller frame. |
| 1520 // TOS + 8: Dart caller code return address | 1518 // TOS + 8: Dart caller code return address |
| 1521 // TOS + 9: Last argument of caller. | 1519 // TOS + 9: Last argument of caller. |
| 1522 // .... | 1520 // .... |
| 1523 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); | 1521 __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry); |
| 1524 // Remove arguments. | 1522 // Remove arguments. |
| 1525 __ popl(EAX); | 1523 __ popl(EAX); |
| 1526 __ popl(EAX); | 1524 __ popl(EAX); |
| 1527 __ popl(EAX); | 1525 __ popl(EAX); |
| 1528 __ popl(EAX); | 1526 __ popl(EAX); |
| 1529 __ popl(EAX); // Get result into EAX. | 1527 __ popl(EAX); // Get result into EAX. |
| 1530 | 1528 |
| 1531 // Remove the stub frame as we are about to return. | 1529 // Remove the stub frame as we are about to return. |
| 1532 __ LeaveFrame(); | 1530 __ LeaveFrame(); |
| 1533 __ ret(); | 1531 __ ret(); |
| 1534 } | 1532 } |
| 1535 | 1533 |
| 1536 | 1534 |
| 1537 | 1535 |
| 1538 // Generate inline cache check for 'num_args'. | 1536 // Generate inline cache check for 'num_args'. |
| 1539 // ECX: Inline cache data array. | 1537 // ECX: Inline cache data object. |
| 1540 // EDX: Arguments array. | 1538 // EDX: Arguments array. |
| 1541 // TOS(0): return address | 1539 // TOS(0): return address |
| 1542 // Control flow: | 1540 // Control flow: |
| 1543 // - If receiver is null -> jump to IC miss. | 1541 // - If receiver is null -> jump to IC miss. |
| 1544 // - If receiver is Smi -> load Smi class. | 1542 // - If receiver is Smi -> load Smi class. |
| 1545 // - If receiver is not-Smi -> load receiver's class. | 1543 // - If receiver is not-Smi -> load receiver's class. |
| 1546 // - Check if 'num_args' (including receiver) match any IC data group. | 1544 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1547 // - Match found -> jump to target. | 1545 // - Match found -> jump to target. |
| 1548 // - Match not found -> jump to IC miss. | 1546 // - Match not found -> jump to IC miss. |
| 1549 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1547 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1550 intptr_t num_args) { | 1548 intptr_t num_args) { |
| 1551 ASSERT(num_args > 0); | 1549 ASSERT(num_args > 0); |
| 1552 // Get receiver. | 1550 // Get receiver. |
| 1553 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1551 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1554 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1552 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. |
| 1555 | 1553 |
| 1556 Label get_class, ic_miss; | 1554 Label get_class, ic_miss; |
| 1557 __ call(&get_class); | 1555 __ call(&get_class); |
| 1558 // EAX: receiver's class | 1556 // EAX: receiver's class |
| 1559 // ECX: IC data array. | 1557 // ECX: IC data array. |
| 1560 | 1558 |
| 1561 #if defined(DEBUG) | 1559 #if defined(DEBUG) |
| 1562 { Label ok; | 1560 { Label ok; |
| 1563 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1561 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1564 __ movl(EBX, FieldAddress(ECX, | 1562 // 'num_args_tested' is stored as an untagged int. |
| 1565 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); | 1563 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1566 const Immediate value = | 1564 __ cmpl(EBX, Immediate(num_args)); |
| 1567 Immediate(reinterpret_cast<int32_t>(Smi::New(num_args))); | |
| 1568 __ cmpl(EBX, value); | |
| 1569 __ j(EQUAL, &ok, Assembler::kNearJump); | 1565 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1570 __ Stop("Incorrect stub for IC data"); | 1566 __ Stop("Incorrect stub for IC data"); |
| 1571 __ Bind(&ok); | 1567 __ Bind(&ok); |
| 1572 } | 1568 } |
| 1573 #endif // DEBUG | 1569 #endif // DEBUG |
| 1574 | 1570 |
| 1575 // Loop that checks if there is an IC data match. | 1571 // Loop that checks if there is an IC data match. |
| 1576 // EAX: receiver's class. | 1572 // EAX: receiver's class. |
| 1577 // ECX: IC data array (preserved). | 1573 // ECX: IC data object (preserved). |
| 1578 __ leal(EBX, FieldAddress(ECX, | 1574 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1579 Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); | 1575 // EBX: ic_data_array with check entries: classes and target functions. |
| 1580 // EBX: pointing to a class to check against (into IC data array). | 1576 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1577 // EBX: points directly to the first ic data array element. |
| 1581 const Immediate raw_null = | 1578 const Immediate raw_null = |
| 1582 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1579 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1583 Label loop, found; | 1580 Label loop, found; |
| 1584 if (num_args == 1) { | 1581 if (num_args == 1) { |
| 1585 __ Bind(&loop); | 1582 __ Bind(&loop); |
| 1586 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1583 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1587 __ cmpl(EAX, EDI); // Match? | 1584 __ cmpl(EAX, EDI); // Match? |
| 1588 __ j(EQUAL, &found, Assembler::kNearJump); | 1585 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1589 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1586 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1590 __ cmpl(EDI, raw_null); // Done? | 1587 __ cmpl(EDI, raw_null); // Done? |
| 1591 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1588 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1592 } else if (num_args == 2) { | 1589 } else if (num_args == 2) { |
| 1590 // EDI: class to check. |
| 1593 Label no_match; | 1591 Label no_match; |
| 1594 __ Bind(&loop); | 1592 __ Bind(&loop); |
| 1595 __ movl(EDI, Address(EBX, 0)); // Get class from IC data to check. | 1593 // Get class from IC data to check. |
| 1596 // Get receiver. | 1594 __ movl(EDI, Address(EBX, 0)); |
| 1595 // Get receiver using argument descriptor in EDX. |
| 1597 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1596 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1598 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1597 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. |
| 1599 __ call(&get_class); | 1598 __ call(&get_class); |
| 1600 __ cmpl(EAX, EDI); // Match? | 1599 __ cmpl(EAX, EDI); // Match? |
| 1601 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1600 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1602 // Check second. | 1601 // Check second class/argument. |
| 1603 __ movl(EDI, Address(EBX, kWordSize)); // Get class from IC data to check. | 1602 // Get class from IC data to check. |
| 1603 __ movl(EDI, Address(EBX, kWordSize)); |
| 1604 // Get next argument. | 1604 // Get next argument. |
| 1605 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1605 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1606 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); // EAX is Smi. | 1606 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); |
| 1607 // EAX (argument count) is Smi. |
| 1607 __ call(&get_class); | 1608 __ call(&get_class); |
| 1608 __ cmpl(EAX, EDI); // Match? | 1609 __ cmpl(EAX, EDI); // Match? |
| 1609 __ j(EQUAL, &found, Assembler::kNearJump); | 1610 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1610 __ Bind(&no_match); | 1611 __ Bind(&no_match); |
| 1612 // Each test entry has (1 + num_args) array elements. |
| 1611 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1613 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1612 __ cmpl(EDI, raw_null); // Done? | 1614 __ cmpl(EDI, raw_null); // Done? |
| 1613 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1615 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1614 } | 1616 } |
| 1615 | 1617 |
| 1616 __ Bind(&ic_miss); | 1618 __ Bind(&ic_miss); |
| 1617 // Get receiver, again. | 1619 // Get receiver, again. |
| 1618 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1620 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1619 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1621 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1620 __ EnterFrame(0); | 1622 __ EnterFrame(0); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1727 __ popl(EDX); | 1729 __ popl(EDX); |
| 1728 __ popl(ECX); | 1730 __ popl(ECX); |
| 1729 __ LeaveFrame(); | 1731 __ LeaveFrame(); |
| 1730 // Now call the dynamic function. | 1732 // Now call the dynamic function. |
| 1731 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1733 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1732 } | 1734 } |
| 1733 | 1735 |
| 1734 } // namespace dart | 1736 } // namespace dart |
| 1735 | 1737 |
| 1736 #endif // defined TARGET_ARCH_IA32 | 1738 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |