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 |