| 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 // The intrinsic code below is executed before a method has built its frame. | 5 // The intrinsic code below is executed before a method has built its frame. |
| 6 // The return address is on the stack and the arguments below it. | 6 // The return address is on the stack and the arguments below it. |
| 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. | 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. |
| 8 // Each intrinsification method returns true if the corresponding | 8 // Each intrinsification method returns true if the corresponding |
| 9 // Dart method was intrinsified. | 9 // Dart method was intrinsified. |
| 10 | 10 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 const intptr_t kArrayLengthOffset = 1 * kWordSize; | 98 const intptr_t kArrayLengthOffset = 1 * kWordSize; |
| 99 Label fall_through; | 99 Label fall_through; |
| 100 | 100 |
| 101 // Compute the size to be allocated, it is based on the array length | 101 // Compute the size to be allocated, it is based on the array length |
| 102 // and it computed as: | 102 // and it computed as: |
| 103 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 103 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 104 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. | 104 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. |
| 105 // Assert that length is a Smi. | 105 // Assert that length is a Smi. |
| 106 __ testl(EDI, Immediate(kSmiTagSize)); | 106 __ testl(EDI, Immediate(kSmiTagSize)); |
| 107 __ j(NOT_ZERO, &fall_through); | 107 __ j(NOT_ZERO, &fall_through); |
| 108 __ cmpl(EDI, Immediate(0)); |
| 109 __ j(LESS, &fall_through, Assembler::kNearJump); |
| 108 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 110 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 109 __ leal(EDI, Address(EDI, TIMES_2, fixed_size)); // EDI is a Smi. | 111 __ leal(EDI, Address(EDI, TIMES_2, fixed_size)); // EDI is a Smi. |
| 110 ASSERT(kSmiTagShift == 1); | 112 ASSERT(kSmiTagShift == 1); |
| 111 __ andl(EDI, Immediate(-kObjectAlignment)); | 113 __ andl(EDI, Immediate(-kObjectAlignment)); |
| 112 | 114 |
| 113 Heap* heap = Isolate::Current()->heap(); | 115 Heap* heap = Isolate::Current()->heap(); |
| 114 | 116 |
| 115 // EDI: allocation size. | 117 // EDI: allocation size. |
| 116 __ movl(EAX, Address::Absolute(heap->TopAddress())); | 118 __ movl(EAX, Address::Absolute(heap->TopAddress())); |
| 117 __ leal(EBX, Address(EAX, EDI, TIMES_1, 0)); | 119 __ leal(EBX, Address(EAX, EDI, TIMES_1, 0)); |
| 118 | 120 |
| 119 // Check if the allocation fits into the remaining space. | 121 // Check if the allocation fits into the remaining space. |
| 120 // EAX: potential new object start. | 122 // EAX: potential new object start. |
| 121 // EBX: potential next object start. | 123 // EBX: potential next object start. |
| 122 // EDI: allocation size. | 124 // EDI: allocation size. |
| 123 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); | 125 __ cmpl(EBX, Address::Absolute(heap->EndAddress())); |
| 124 __ j(ABOVE_EQUAL, &fall_through); | 126 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 125 | 127 |
| 126 // Successfully allocated the object(s), now update top to point to | 128 // Successfully allocated the object(s), now update top to point to |
| 127 // next object start and initialize the object. | 129 // next object start and initialize the object. |
| 128 __ movl(Address::Absolute(heap->TopAddress()), EBX); | 130 __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| 129 __ addl(EAX, Immediate(kHeapObjectTag)); | 131 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 130 | 132 |
| 131 // Initialize the tags. | 133 // Initialize the tags. |
| 132 // EAX: new object start as a tagged pointer. | 134 // EAX: new object start as a tagged pointer. |
| 133 // EBX: new object end address. | 135 // EBX: new object end address. |
| 134 // EDI: allocation size. | 136 // EDI: allocation size. |
| 135 { | 137 { |
| 136 Label size_tag_overflow, done; | 138 Label size_tag_overflow, done; |
| 137 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 139 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 138 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 140 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 139 __ shll(EDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 141 __ shll(EDI, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| 140 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. | 142 __ movl(FieldAddress(EAX, Array::tags_offset()), EDI); // Tags. |
| 141 __ jmp(&done); | 143 __ jmp(&done, Assembler::kNearJump); |
| 142 | 144 |
| 143 __ Bind(&size_tag_overflow); | 145 __ Bind(&size_tag_overflow); |
| 144 __ movl(FieldAddress(EAX, Array::tags_offset()), Immediate(0)); | 146 __ movl(FieldAddress(EAX, Array::tags_offset()), Immediate(0)); |
| 145 __ Bind(&done); | 147 __ Bind(&done); |
| 146 } | 148 } |
| 147 | 149 |
| 148 // Store class value for array. | 150 // Store class value for array. |
| 149 // EAX: new object start as a tagged pointer. | 151 // EAX: new object start as a tagged pointer. |
| 150 // EBX: new object end address. | 152 // EBX: new object end address. |
| 151 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); | 153 __ movl(EDI, FieldAddress(CTX, Context::isolate_offset())); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 return false; | 482 return false; |
| 481 } | 483 } |
| 482 | 484 |
| 483 | 485 |
| 484 // Simple implementation: for positive dividend values greater than divisor, | 486 // Simple implementation: for positive dividend values greater than divisor, |
| 485 // return dividend. | 487 // return dividend. |
| 486 static bool Integer_modulo(Assembler* assembler) { | 488 static bool Integer_modulo(Assembler* assembler) { |
| 487 Label fall_through, return_zero; | 489 Label fall_through, return_zero; |
| 488 TestBothArgumentsSmis(assembler, &fall_through); | 490 TestBothArgumentsSmis(assembler, &fall_through); |
| 489 // EAX: right argument (divisor) | 491 // EAX: right argument (divisor) |
| 492 // Check if modulo by zero -> exception thrown in main function. |
| 493 __ cmpl(EAX, Immediate(0)); |
| 494 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 490 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). | 495 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). |
| 491 __ cmpl(EBX, Immediate(0)); | 496 __ cmpl(EBX, Immediate(0)); |
| 492 __ j(LESS, &fall_through, Assembler::kNearJump); | 497 __ j(LESS, &fall_through, Assembler::kNearJump); |
| 493 __ cmpl(EBX, EAX); | 498 __ cmpl(EBX, EAX); |
| 494 __ j(EQUAL, &return_zero, Assembler::kNearJump); | 499 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
| 495 __ j(GREATER, &fall_through, Assembler::kNearJump); | 500 __ j(GREATER, &fall_through, Assembler::kNearJump); |
| 496 __ movl(EAX, EBX); // Return dividend. | 501 __ movl(EAX, EBX); // Return dividend. |
| 497 __ ret(); | 502 __ ret(); |
| 498 __ Bind(&return_zero); | 503 __ Bind(&return_zero); |
| 499 __ xorl(EAX, EAX); // Return zero. | 504 __ xorl(EAX, EAX); // Return zero. |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 | 733 |
| 729 static bool Integer_sar(Assembler* assembler) { | 734 static bool Integer_sar(Assembler* assembler) { |
| 730 Label fall_through, shift_count_ok; | 735 Label fall_through, shift_count_ok; |
| 731 TestBothArgumentsSmis(assembler, &fall_through); | 736 TestBothArgumentsSmis(assembler, &fall_through); |
| 732 // Can destroy ECX since we are not falling through. | 737 // Can destroy ECX since we are not falling through. |
| 733 Immediate count_limit = Immediate(0x1F); | 738 Immediate count_limit = Immediate(0x1F); |
| 734 // Check that the count is not larger than what the hardware can handle. | 739 // Check that the count is not larger than what the hardware can handle. |
| 735 // For shifting right a Smi the result is the same for all numbers | 740 // For shifting right a Smi the result is the same for all numbers |
| 736 // >= count_limit. | 741 // >= count_limit. |
| 737 __ SmiUntag(EAX); | 742 __ SmiUntag(EAX); |
| 743 // Negative counts throw exception. |
| 744 __ cmpl(EAX, Immediate(0)); |
| 745 __ j(LESS, &fall_through, Assembler::kNearJump); |
| 738 __ cmpl(EAX, count_limit); | 746 __ cmpl(EAX, count_limit); |
| 739 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); | 747 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); |
| 740 __ movl(EAX, count_limit); | 748 __ movl(EAX, count_limit); |
| 741 __ Bind(&shift_count_ok); | 749 __ Bind(&shift_count_ok); |
| 742 __ movl(ECX, EAX); // Shift amount must be in ECX. | 750 __ movl(ECX, EAX); // Shift amount must be in ECX. |
| 743 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value. | 751 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value. |
| 744 __ SmiUntag(EAX); // Value. | 752 __ SmiUntag(EAX); // Value. |
| 745 __ sarl(EAX, ECX); | 753 __ sarl(EAX, ECX); |
| 746 __ SmiTag(EAX); | 754 __ SmiTag(EAX); |
| 747 __ ret(); | 755 __ ret(); |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 } \ | 1297 } \ |
| 1290 | 1298 |
| 1291 INTRINSIC_LIST(FIND_INTRINSICS); | 1299 INTRINSIC_LIST(FIND_INTRINSICS); |
| 1292 #undef FIND_INTRINSICS | 1300 #undef FIND_INTRINSICS |
| 1293 return false; | 1301 return false; |
| 1294 } | 1302 } |
| 1295 | 1303 |
| 1296 } // namespace dart | 1304 } // namespace dart |
| 1297 | 1305 |
| 1298 #endif // defined TARGET_ARCH_IA32 | 1306 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |