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::GenerateInlineCache1Stub(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 camparison. | |
regis
2011/10/25 18:06:27
I'd rather have an orange peel than a Smi in my ca
srdjan
2011/10/25 18:28:50
:-) Done.
| |
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 |