| 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 25 matching lines...) Expand all Loading... |
| 36 const intptr_t argc_offset = NativeArguments::argc_offset(); | 36 const intptr_t argc_offset = NativeArguments::argc_offset(); |
| 37 const intptr_t argv_offset = NativeArguments::argv_offset(); | 37 const intptr_t argv_offset = NativeArguments::argv_offset(); |
| 38 const intptr_t retval_offset = NativeArguments::retval_offset(); | 38 const intptr_t retval_offset = NativeArguments::retval_offset(); |
| 39 | 39 |
| 40 __ EnterFrame(0); | 40 __ EnterFrame(0); |
| 41 | 41 |
| 42 // Load current Isolate pointer from Context structure into EAX. | 42 // Load current Isolate pointer from Context structure into EAX. |
| 43 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 43 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
| 44 | 44 |
| 45 // Save exit frame information to enable stack walking as we are about | 45 // Save exit frame information to enable stack walking as we are about |
| 46 // to transition to dart VM code. | 46 // to transition to Dart VM C++ code. |
| 47 __ movl(Address(EAX, Isolate::top_exit_frame_info_offset()), ESP); | 47 __ movl(Address(EAX, Isolate::top_exit_frame_info_offset()), ESP); |
| 48 | 48 |
| 49 // Save current Context pointer into Isolate structure. | 49 // Save current Context pointer into Isolate structure. |
| 50 __ movl(Address(EAX, Isolate::top_context_offset()), CTX); | 50 __ movl(Address(EAX, Isolate::top_context_offset()), CTX); |
| 51 | 51 |
| 52 // Cache Isolate pointer into CTX while executing runtime code. | 52 // Cache Isolate pointer into CTX while executing runtime code. |
| 53 __ movl(CTX, EAX); | 53 __ movl(CTX, EAX); |
| 54 | 54 |
| 55 // Reserve space for arguments and align frame before entering C++ world. | 55 // Reserve space for arguments and align frame before entering C++ world. |
| 56 __ AddImmediate(ESP, Immediate(-sizeof(NativeArguments))); | 56 __ AddImmediate(ESP, Immediate(-sizeof(NativeArguments))); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 71 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 71 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 72 | 72 |
| 73 // Load Context pointer from Isolate structure into ECX. | 73 // Load Context pointer from Isolate structure into ECX. |
| 74 __ movl(ECX, Address(CTX, Isolate::top_context_offset())); | 74 __ movl(ECX, Address(CTX, Isolate::top_context_offset())); |
| 75 | 75 |
| 76 // Reset Context pointer in Isolate structure. | 76 // Reset Context pointer in Isolate structure. |
| 77 const Immediate raw_null = | 77 const Immediate raw_null = |
| 78 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 78 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 79 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); | 79 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 80 | 80 |
| 81 // Cache Context pointer into CTX while executing dart code. | 81 // Cache Context pointer into CTX while executing Dart code. |
| 82 __ movl(CTX, ECX); | 82 __ movl(CTX, ECX); |
| 83 | 83 |
| 84 __ LeaveFrame(); | 84 __ LeaveFrame(); |
| 85 __ ret(); | 85 __ ret(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 // Input parameters: | 89 // Input parameters: |
| 90 // ESP : points to return address. | 90 // ESP : points to return address. |
| 91 // ESP + 4 : address of last argument in argument array. | 91 // ESP + 4 : address of last argument in argument array. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 __ movl(CTX, EDI); | 147 __ movl(CTX, EDI); |
| 148 | 148 |
| 149 // Reserve space for the native arguments structure, the outgoing parameter | 149 // Reserve space for the native arguments structure, the outgoing parameter |
| 150 // (pointer to the native arguments structure) and align frame before | 150 // (pointer to the native arguments structure) and align frame before |
| 151 // entering the C++ world. | 151 // entering the C++ world. |
| 152 __ AddImmediate(ESP, Immediate(-sizeof(NativeArguments) - kWordSize)); | 152 __ AddImmediate(ESP, Immediate(-sizeof(NativeArguments) - kWordSize)); |
| 153 if (OS::ActivationFrameAlignment() > 0) { | 153 if (OS::ActivationFrameAlignment() > 0) { |
| 154 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 154 __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 155 } | 155 } |
| 156 | 156 |
| 157 // Pass NativeArguments structure by value and call runtime. | 157 // Pass NativeArguments structure by value and call native function. |
| 158 __ movl(Address(ESP, isolate_offset), CTX); // Set isolate in NativeArgs. | 158 __ movl(Address(ESP, isolate_offset), CTX); // Set isolate in NativeArgs. |
| 159 __ movl(Address(ESP, argc_offset), EDX); // Set argc in NativeArguments. | 159 __ movl(Address(ESP, argc_offset), EDX); // Set argc in NativeArguments. |
| 160 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. | 160 __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments. |
| 161 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr. | 161 __ leal(EAX, Address(EBP, 2 * kWordSize)); // Compute return value addr. |
| 162 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. | 162 __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments. |
| 163 __ leal(EAX, Address(ESP, kWordSize)); // Pointer to the NativeArguments. | 163 __ leal(EAX, Address(ESP, kWordSize)); // Pointer to the NativeArguments. |
| 164 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. | 164 __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments. |
| 165 __ call(ECX); | 165 __ call(ECX); |
| 166 | 166 |
| 167 // Reset exit frame information in Isolate structure. | 167 // Reset exit frame information in Isolate structure. |
| 168 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); | 168 __ movl(Address(CTX, Isolate::top_exit_frame_info_offset()), Immediate(0)); |
| 169 | 169 |
| 170 // Load Context pointer from Isolate structure into EDI. | 170 // Load Context pointer from Isolate structure into EDI. |
| 171 __ movl(EDI, Address(CTX, Isolate::top_context_offset())); | 171 __ movl(EDI, Address(CTX, Isolate::top_context_offset())); |
| 172 | 172 |
| 173 // Reset Context pointer in Isolate structure. | 173 // Reset Context pointer in Isolate structure. |
| 174 const Immediate raw_null = | 174 const Immediate raw_null = |
| 175 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 175 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 176 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); | 176 __ movl(Address(CTX, Isolate::top_context_offset()), raw_null); |
| 177 | 177 |
| 178 // Cache Context pointer into CTX while executing dart code. | 178 // Cache Context pointer into CTX while executing Dart code. |
| 179 __ movl(CTX, EDI); | 179 __ movl(CTX, EDI); |
| 180 | 180 |
| 181 __ LeaveFrame(); | 181 __ LeaveFrame(); |
| 182 __ ret(); | 182 __ ret(); |
| 183 } | 183 } |
| 184 | 184 |
| 185 | 185 |
| 186 // Input parameters: | 186 // Input parameters: |
| 187 // ECX: function object. | 187 // ECX: function object. |
| 188 // EDX: arguments descriptor array (num_args is first Smi element). | 188 // EDX: arguments descriptor array (num_args is first Smi element). |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 __ LeaveFrame(); | 595 __ LeaveFrame(); |
| 596 __ ret(); | 596 __ ret(); |
| 597 } | 597 } |
| 598 | 598 |
| 599 | 599 |
| 600 // Called for inline allocation of arrays. | 600 // Called for inline allocation of arrays. |
| 601 // Input parameters: | 601 // Input parameters: |
| 602 // EDX : Array length as Smi. | 602 // EDX : Array length as Smi. |
| 603 // ECX : array element type (either NULL or an instantiated type). | 603 // ECX : array element type (either NULL or an instantiated type). |
| 604 // Uses EAX, EBX, ECX, EDI as temporary registers. | 604 // Uses EAX, EBX, ECX, EDI as temporary registers. |
| 605 // NOTE: EDX cannot be cloberred here as the caller relies on it | 605 // NOTE: EDX cannot be clobbered here as the caller relies on it being saved. |
| 606 // being saved. | |
| 607 // The newly allocated object is returned in EAX. | 606 // The newly allocated object is returned in EAX. |
| 608 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 607 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 609 Label slow_case; | 608 Label slow_case; |
| 610 const Immediate raw_null = | 609 const Immediate raw_null = |
| 611 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 610 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 612 | 611 |
| 613 if (FLAG_inline_alloc) { | 612 if (FLAG_inline_alloc) { |
| 614 // Compute the size to be allocated, it is based on the array length | 613 // Compute the size to be allocated, it is based on the array length |
| 615 // and it computed as: | 614 // and it computed as: |
| 616 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 615 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 617 // Assert that length is a Smi. | 616 // Assert that length is a Smi. |
| 618 __ testl(EDX, Immediate(kSmiTagSize)); | 617 __ testl(EDX, Immediate(kSmiTagSize)); |
| 619 if (FLAG_use_slow_path) { | 618 if (FLAG_use_slow_path) { |
| 620 __ jmp(&slow_case); | 619 __ jmp(&slow_case); |
| 621 } else { | 620 } else { |
| 622 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); | 621 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); |
| 623 } | 622 } |
| 624 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); | 623 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); |
| 625 __ movl(EDI, Address(EDI, Isolate::heap_offset())); | 624 __ movl(EDI, Address(EDI, Isolate::heap_offset())); |
| 626 __ movl(EDI, Address(EDI, Heap::new_space_offset())); | 625 __ movl(EDI, Address(EDI, Heap::new_space_offset())); |
| 627 | 626 |
| 628 // Calculate and align allocation size. | 627 // Calculate and align allocation size. |
| 629 // Load new object start and calculate next object start. | 628 // Load new object start and calculate next object start. |
| 630 // ECX: array element type. | 629 // ECX: array element type. |
| 631 // EDX: Array length as Smi. | 630 // EDX: Array length as Smi. |
| 632 // EDI: Points to new space object. | 631 // EDI: Points to new space object. |
| 633 __ movl(EAX, Address(EDI, Scavenger::top_offset())); | 632 __ movl(EAX, Address(EDI, Scavenger::top_offset())); |
| 634 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 633 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 635 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); | 634 __ leal(EBX, Address(EDX, TIMES_2, fixed_size)); // EDX is Smi. |
| 636 ASSERT(kSmiTagShift == 1); | 635 ASSERT(kSmiTagShift == 1); |
| 637 __ andl(EBX, Immediate(-kObjectAlignment)); | 636 __ andl(EBX, Immediate(-kObjectAlignment)); |
| 638 __ leal(EBX, Address(EAX, EBX, TIMES_1, 0)); | 637 __ leal(EBX, Address(EAX, EBX, TIMES_1, 0)); |
| 639 | 638 |
| 640 // Check if the allocation fits into the remaining space. | 639 // Check if the allocation fits into the remaining space. |
| 641 // EAX: potential new object start. | 640 // EAX: potential new object start. |
| 642 // EBX: potential next object start. | 641 // EBX: potential next object start. |
| 643 // ECX: array element type. | 642 // ECX: array element type. |
| 644 // EDX: Array length as Smi. | 643 // EDX: Array length as Smi. |
| 645 // EDI: Points to new space object. | 644 // EDI: Points to new space object. |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 // - If receiver is Smi -> load Smi class. | 1449 // - If receiver is Smi -> load Smi class. |
| 1451 // - If receiver is not-Smi -> load receiver's class. | 1450 // - If receiver is not-Smi -> load receiver's class. |
| 1452 // - Check if 'num_args' (including receiver) match any IC data group. | 1451 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1453 // - Match found -> jump to target. | 1452 // - Match found -> jump to target. |
| 1454 // - Match not found -> jump to IC miss. | 1453 // - Match not found -> jump to IC miss. |
| 1455 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1454 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1456 intptr_t num_args) { | 1455 intptr_t num_args) { |
| 1457 ASSERT(num_args > 0); | 1456 ASSERT(num_args > 0); |
| 1458 // Get receiver. | 1457 // Get receiver. |
| 1459 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1458 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1460 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); | 1459 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1461 | 1460 |
| 1462 Label get_class, ic_miss; | 1461 Label get_class, ic_miss; |
| 1463 __ call(&get_class); | 1462 __ call(&get_class); |
| 1464 // EAX: receiver's class | 1463 // EAX: receiver's class |
| 1465 // ECX: IC data array. | 1464 // ECX: IC data array. |
| 1466 | 1465 |
| 1467 #if defined(DEBUG) | 1466 #if defined(DEBUG) |
| 1468 { Label ok; | 1467 { Label ok; |
| 1469 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1468 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1470 __ movl(EBX, FieldAddress(ECX, | 1469 __ movl(EBX, FieldAddress(ECX, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1494 __ j(EQUAL, &found, Assembler::kNearJump); | 1493 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1495 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1494 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1496 __ cmpl(EDI, raw_null); // Done? | 1495 __ cmpl(EDI, raw_null); // Done? |
| 1497 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1496 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1498 } else if (num_args == 2) { | 1497 } else if (num_args == 2) { |
| 1499 Label no_match; | 1498 Label no_match; |
| 1500 __ Bind(&loop); | 1499 __ Bind(&loop); |
| 1501 __ movl(EDI, Address(EBX, 0)); // Get class from IC data to check. | 1500 __ movl(EDI, Address(EBX, 0)); // Get class from IC data to check. |
| 1502 // Get receiver. | 1501 // Get receiver. |
| 1503 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1502 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1504 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); | 1503 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1505 __ call(&get_class); | 1504 __ call(&get_class); |
| 1506 __ cmpl(EAX, EDI); // Match? | 1505 __ cmpl(EAX, EDI); // Match? |
| 1507 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1506 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1508 // Check second. | 1507 // Check second. |
| 1509 __ movl(EDI, Address(EBX, kWordSize)); // Get class from IC data to check. | 1508 __ movl(EDI, Address(EBX, kWordSize)); // Get class from IC data to check. |
| 1510 // Get next argument. | 1509 // Get next argument. |
| 1511 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1510 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1512 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); | 1511 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); // EAX is Smi. |
| 1513 __ call(&get_class); | 1512 __ call(&get_class); |
| 1514 __ cmpl(EAX, EDI); // Match? | 1513 __ cmpl(EAX, EDI); // Match? |
| 1515 __ j(EQUAL, &found, Assembler::kNearJump); | 1514 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1516 __ Bind(&no_match); | 1515 __ Bind(&no_match); |
| 1517 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1516 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1518 __ cmpl(EDI, raw_null); // Done? | 1517 __ cmpl(EDI, raw_null); // Done? |
| 1519 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1518 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1520 } | 1519 } |
| 1521 | 1520 |
| 1522 __ Bind(&ic_miss); | 1521 __ Bind(&ic_miss); |
| 1523 // Get receiver, again. | 1522 // Get receiver, again. |
| 1524 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1523 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1525 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); | 1524 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1526 __ EnterFrame(0); | 1525 __ EnterFrame(0); |
| 1527 // Setup space for return value on stack by pushing smi 0. | 1526 // Setup space for return value on stack by pushing smi 0. |
| 1528 __ pushl(EDX); // Preserve arguments array. | 1527 __ pushl(EDX); // Preserve arguments array. |
| 1529 __ pushl(ECX); // Preserve IC data array | 1528 __ pushl(ECX); // Preserve IC data array |
| 1530 __ pushl(Immediate(0)); // Space for result (target code object). | 1529 __ pushl(Immediate(0)); // Space for result (target code object). |
| 1531 __ movl(EDX, FieldAddress(EDX, Array::data_offset())); | 1530 __ movl(EDX, FieldAddress(EDX, Array::data_offset())); |
| 1532 // Push call arguments. | 1531 // Push call arguments. |
| 1533 for (intptr_t i = 0; i < num_args; i++) { | 1532 for (intptr_t i = 0; i < num_args; i++) { |
| 1534 __ movl(EDX, Address(EAX, -kWordSize * i)); | 1533 __ movl(EDX, Address(EAX, -kWordSize * i)); |
| 1535 __ pushl(EDX); | 1534 __ pushl(EDX); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 __ popl(EDX); | 1633 __ popl(EDX); |
| 1635 __ popl(ECX); | 1634 __ popl(ECX); |
| 1636 __ LeaveFrame(); | 1635 __ LeaveFrame(); |
| 1637 // Now call the dynamic function. | 1636 // Now call the dynamic function. |
| 1638 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1637 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1639 } | 1638 } |
| 1640 | 1639 |
| 1641 } // namespace dart | 1640 } // namespace dart |
| 1642 | 1641 |
| 1643 #endif // defined TARGET_ARCH_IA32 | 1642 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |