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

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

Issue 9395016: First part of new ICData infrastructure: use a wrapper object instead of an array. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/raw_object_snapshot.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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, &not_found, Assembler::kNearJump); 364 __ j(EQUAL, &not_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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/raw_object_snapshot.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698