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" | 10 #include "vm/ic_data.h" |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 __ popl(EAX); | 592 __ popl(EAX); |
593 __ popl(EAX); | 593 __ popl(EAX); |
594 __ popl(EAX); // Get result into EAX. | 594 __ popl(EAX); // Get result into EAX. |
595 | 595 |
596 // Remove the stub frame as we are about to return. | 596 // Remove the stub frame as we are about to return. |
597 __ LeaveFrame(); | 597 __ LeaveFrame(); |
598 __ ret(); | 598 __ ret(); |
599 } | 599 } |
600 | 600 |
601 | 601 |
602 void StubCode::GenerateCallInstanceFunctionStub(Assembler* assembler) { | |
603 __ EnterFrame(0); | |
604 // Stack at this point: | |
605 // TOS + 0: Saved EBP of previous frame. <== EBP | |
606 // TOS + 1: Dart code return address | |
607 // TOS + 2: Last argument of caller. | |
608 // .... | |
609 // Total number of args is the first Smi in args descriptor array (EDX). | |
610 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); // EAX is a Smi. | |
611 __ movl(EAX, Address(ESP, EAX, TIMES_2, kWordSize)); // Load receiver. | |
612 __ pushl(EDX); // Preserve arguments descriptor array. | |
613 __ pushl(ECX); // Preserve ic-data array. | |
614 __ pushl(EAX); // Push receiver. | |
615 __ CallRuntimeFromStub(kResolvePatchInstanceCallRuntimeEntry); | |
616 __ popl(EAX); // Remove receiver pushed earlier. | |
617 // Pop preserved values | |
618 __ popl(ECX); // Restore ic-data array. | |
619 __ popl(EDX); // Restore arguments descriptor array. | |
620 __ LeaveFrame(); | |
621 __ popl(EAX); | |
622 // Reexecute call. | |
623 __ subl(EAX, Immediate(Assembler::kCallExternalLabelSize)); | |
624 __ jmp(EAX); | |
625 } | |
626 | |
627 | |
628 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 602 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
629 __ EnterFrame(0); | 603 __ EnterFrame(0); |
630 // Stack at this point: | 604 // Stack at this point: |
631 // TOS + 0: Saved EBP of function frame that will be deoptimized. <== EBP | 605 // TOS + 0: Saved EBP of function frame that will be deoptimized. <== EBP |
632 // TOS + 1: Deoptimization point (return address), will be patched. | 606 // TOS + 1: Deoptimization point (return address), will be patched. |
633 // TOS + 2: top-of-stack at deoptimization point (all arguments on stack). | 607 // TOS + 2: top-of-stack at deoptimization point (all arguments on stack). |
634 __ CallRuntimeFromStub(kDeoptimizeRuntimeEntry); | 608 __ CallRuntimeFromStub(kDeoptimizeRuntimeEntry); |
635 __ LeaveFrame(); | 609 __ LeaveFrame(); |
636 __ ret(); | 610 __ ret(); |
637 } | 611 } |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 __ popl(EAX); | 1419 __ popl(EAX); |
1446 __ popl(EAX); | 1420 __ popl(EAX); |
1447 __ popl(EAX); | 1421 __ popl(EAX); |
1448 __ popl(EAX); // Get result into EAX. | 1422 __ popl(EAX); // Get result into EAX. |
1449 | 1423 |
1450 // Remove the stub frame as we are about to return. | 1424 // Remove the stub frame as we are about to return. |
1451 __ LeaveFrame(); | 1425 __ LeaveFrame(); |
1452 __ ret(); | 1426 __ ret(); |
1453 } | 1427 } |
1454 | 1428 |
| 1429 |
| 1430 // Use inline cache data array to invoke the target or continue in inline |
| 1431 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1432 // ECX: Inline cache data array |
| 1433 // EDX: Arguments array |
| 1434 // TOS(0): return address |
| 1435 void StubCode::GenerateInlineCacheStub(Assembler* assembler) { |
| 1436 Label ic_miss, is_smi, test_class; |
| 1437 // Get receiver. |
| 1438 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1439 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
| 1440 |
| 1441 __ CompareObject(EAX, Instance::ZoneHandle(Instance::null())); |
| 1442 __ j(EQUAL, &ic_miss, Assembler::kNearJump); // Null receiver -> IC miss. |
| 1443 |
| 1444 // Test if Smi -> load Smi class for comparison. |
| 1445 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1446 __ j(ZERO, &is_smi, Assembler::kNearJump); |
| 1447 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); |
| 1448 __ jmp(&test_class); |
| 1449 __ Bind(&is_smi); |
| 1450 const Class& smi_class = |
| 1451 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
| 1452 __ LoadObject(EAX, smi_class); |
| 1453 |
| 1454 __ Bind(&test_class); |
| 1455 // EAX: receiver's class |
| 1456 // ECX: IC data array. |
| 1457 |
| 1458 #if defined(DEBUG) |
| 1459 { Label ok; |
| 1460 // Check that the IC data array has NumberOfArgumentsChecked() == 1. |
| 1461 __ movl(EBX, FieldAddress(ECX, |
| 1462 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); |
| 1463 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); |
| 1464 __ cmpl(EBX, value); |
| 1465 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1466 __ Stop("Incorrect stub for IC data"); |
| 1467 __ Bind(&ok); |
| 1468 } |
| 1469 #endif // DEBUG |
| 1470 |
| 1471 const Immediate raw_null = |
| 1472 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1473 __ leal(EBX, FieldAddress(ECX, |
| 1474 Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); |
| 1475 Label loop, found, call_target_function; |
| 1476 __ Bind(&loop); |
| 1477 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1478 __ cmpl(EAX, EDI); // Match? |
| 1479 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1480 __ addl(EBX, Immediate(kWordSize * 2)); // next element (class + target). |
| 1481 __ cmpl(EDI, raw_null); // Done? |
| 1482 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1483 |
| 1484 __ Bind(&ic_miss); |
| 1485 |
| 1486 // Get receiver. |
| 1487 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1488 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
| 1489 __ EnterFrame(0); |
| 1490 // Setup space for return value on stack by pushing smi 0. |
| 1491 __ pushl(EDX); // Preserve arguments array. |
| 1492 __ pushl(ECX); // Preserve IC data array |
| 1493 __ pushl(Immediate(0)); |
| 1494 __ pushl(EAX); // Push receiver. |
| 1495 __ CallRuntimeFromStub(kInlineCacheMissHandlerRuntimeEntry); |
| 1496 __ popl(EAX); // Remove receiver pushed earlier. |
| 1497 __ popl(EAX); // Pop returned code object into EAX. |
| 1498 __ popl(ECX); // Restore IC data array. |
| 1499 __ popl(EDX); // Restore arguments array. |
| 1500 __ LeaveFrame(); |
| 1501 __ cmpl(EAX, raw_null); |
| 1502 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
| 1503 // NoSuchMethod or closure. |
| 1504 __ jmp(&StubCode::MegamorphicLookupLabel()); |
| 1505 |
| 1506 __ Bind(&found); |
| 1507 __ movl(EAX, Address(EBX, kWordSize)); // Target function. |
| 1508 |
| 1509 __ Bind(&call_target_function); |
| 1510 // EAX: Target function. |
| 1511 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 1512 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1513 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1514 __ jmp(EAX); |
| 1515 } |
| 1516 |
1455 } // namespace dart | 1517 } // namespace dart |
1456 | 1518 |
1457 #endif // defined TARGET_ARCH_IA32 | 1519 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |