| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 Immediate(reinterpret_cast<int32_t>(Object::null())); | 179 Immediate(reinterpret_cast<int32_t>(Object::null())); |
| 180 __ movl(EAX, raw_null); | 180 __ movl(EAX, raw_null); |
| 181 __ ret(); | 181 __ ret(); |
| 182 __ Bind(&fall_through); | 182 __ Bind(&fall_through); |
| 183 } | 183 } |
| 184 | 184 |
| 185 | 185 |
| 186 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ | 186 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ |
| 187 Label fall_through; \ | 187 Label fall_through; \ |
| 188 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ | 188 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ |
| 189 __ MaybeTraceAllocation(cid, EDI, &fall_through, false); \ | 189 __ MaybeTraceAllocation(cid, EDI, &fall_through, false, \ |
| 190 /* inline_isolate = */ false); \ |
| 190 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \ | 191 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \ |
| 191 /* Check that length is a positive Smi. */ \ | 192 /* Check that length is a positive Smi. */ \ |
| 192 /* EDI: requested array length argument. */ \ | 193 /* EDI: requested array length argument. */ \ |
| 193 __ testl(EDI, Immediate(kSmiTagMask)); \ | 194 __ testl(EDI, Immediate(kSmiTagMask)); \ |
| 194 __ j(NOT_ZERO, &fall_through); \ | 195 __ j(NOT_ZERO, &fall_through); \ |
| 195 __ cmpl(EDI, Immediate(0)); \ | 196 __ cmpl(EDI, Immediate(0)); \ |
| 196 __ j(LESS, &fall_through); \ | 197 __ j(LESS, &fall_through); \ |
| 197 __ SmiUntag(EDI); \ | 198 __ SmiUntag(EDI); \ |
| 198 /* Check for maximum allowed length. */ \ | 199 /* Check for maximum allowed length. */ \ |
| 199 /* EDI: untagged array length. */ \ | 200 /* EDI: untagged array length. */ \ |
| 200 __ cmpl(EDI, Immediate(max_len)); \ | 201 __ cmpl(EDI, Immediate(max_len)); \ |
| 201 __ j(GREATER, &fall_through); \ | 202 __ j(GREATER, &fall_through); \ |
| 202 /* Special case for scaling by 16. */ \ | 203 /* Special case for scaling by 16. */ \ |
| 203 if (scale_factor == TIMES_16) { \ | 204 if (scale_factor == TIMES_16) { \ |
| 204 /* double length of array. */ \ | 205 /* double length of array. */ \ |
| 205 __ addl(EDI, EDI); \ | 206 __ addl(EDI, EDI); \ |
| 206 /* only scale by 8. */ \ | 207 /* only scale by 8. */ \ |
| 207 scale_factor = TIMES_8; \ | 208 scale_factor = TIMES_8; \ |
| 208 } \ | 209 } \ |
| 209 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ | 210 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ |
| 210 __ leal(EDI, Address(EDI, scale_factor, fixed_size)); \ | 211 __ leal(EDI, Address(EDI, scale_factor, fixed_size)); \ |
| 211 __ andl(EDI, Immediate(-kObjectAlignment)); \ | 212 __ andl(EDI, Immediate(-kObjectAlignment)); \ |
| 212 Heap* heap = Isolate::Current()->heap(); \ | 213 Heap::Space space = Heap::SpaceForAllocation(cid); \ |
| 213 Heap::Space space = heap->SpaceForAllocation(cid); \ | 214 __ movl(ECX, Address(THR, Thread::heap_offset())); \ |
| 214 __ movl(EAX, Address::Absolute(heap->TopAddress(space))); \ | 215 __ movl(EAX, Address(ECX, Heap::TopOffset(space))); \ |
| 215 __ movl(EBX, EAX); \ | 216 __ movl(EBX, EAX); \ |
| 216 \ | 217 \ |
| 217 /* EDI: allocation size. */ \ | 218 /* EDI: allocation size. */ \ |
| 218 __ addl(EBX, EDI); \ | 219 __ addl(EBX, EDI); \ |
| 219 __ j(CARRY, &fall_through); \ | 220 __ j(CARRY, &fall_through); \ |
| 220 \ | 221 \ |
| 221 /* Check if the allocation fits into the remaining space. */ \ | 222 /* Check if the allocation fits into the remaining space. */ \ |
| 222 /* EAX: potential new object start. */ \ | 223 /* EAX: potential new object start. */ \ |
| 223 /* EBX: potential next object start. */ \ | 224 /* EBX: potential next object start. */ \ |
| 224 /* EDI: allocation size. */ \ | 225 /* EDI: allocation size. */ \ |
| 225 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); \ | 226 /* ECX: heap. */ \ |
| 227 __ cmpl(EBX, Address(ECX, Heap::EndOffset(space))); \ |
| 226 __ j(ABOVE_EQUAL, &fall_through); \ | 228 __ j(ABOVE_EQUAL, &fall_through); \ |
| 227 \ | 229 \ |
| 228 /* Successfully allocated the object(s), now update top to point to */ \ | 230 /* Successfully allocated the object(s), now update top to point to */ \ |
| 229 /* next object start and initialize the object. */ \ | 231 /* next object start and initialize the object. */ \ |
| 230 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); \ | 232 __ movl(Address(ECX, Heap::TopOffset(space)), EBX); \ |
| 231 __ addl(EAX, Immediate(kHeapObjectTag)); \ | 233 __ addl(EAX, Immediate(kHeapObjectTag)); \ |
| 232 __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space); \ | 234 __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space, \ |
| 235 /* inline_isolate = */ false); \ |
| 233 \ | 236 \ |
| 234 /* Initialize the tags. */ \ | 237 /* Initialize the tags. */ \ |
| 235 /* EAX: new object start as a tagged pointer. */ \ | 238 /* EAX: new object start as a tagged pointer. */ \ |
| 236 /* EBX: new object end address. */ \ | 239 /* EBX: new object end address. */ \ |
| 237 /* EDI: allocation size. */ \ | 240 /* EDI: allocation size. */ \ |
| 238 { \ | 241 { \ |
| 239 Label size_tag_overflow, done; \ | 242 Label size_tag_overflow, done; \ |
| 240 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); \ | 243 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); \ |
| 241 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); \ | 244 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); \ |
| 242 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); \ | 245 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); \ |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 __ shll(EBX, ECX); | 584 __ shll(EBX, ECX); |
| 582 __ xorl(EDI, EDI); | 585 __ xorl(EDI, EDI); |
| 583 __ shldl(EDI, EAX, ECX); | 586 __ shldl(EDI, EAX, ECX); |
| 584 // Result in EDI (high) and EBX (low). | 587 // Result in EDI (high) and EBX (low). |
| 585 const Class& mint_class = Class::Handle( | 588 const Class& mint_class = Class::Handle( |
| 586 Isolate::Current()->object_store()->mint_class()); | 589 Isolate::Current()->object_store()->mint_class()); |
| 587 __ TryAllocate(mint_class, | 590 __ TryAllocate(mint_class, |
| 588 &fall_through, | 591 &fall_through, |
| 589 Assembler::kNearJump, | 592 Assembler::kNearJump, |
| 590 EAX, // Result register. | 593 EAX, // Result register. |
| 591 kNoRegister); | 594 ECX); // temp |
| 592 // EBX and EDI are not objects but integer values. | 595 // EBX and EDI are not objects but integer values. |
| 593 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); | 596 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); |
| 594 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); | 597 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); |
| 595 __ ret(); | 598 __ ret(); |
| 596 __ Bind(&fall_through); | 599 __ Bind(&fall_through); |
| 597 } | 600 } |
| 598 | 601 |
| 599 | 602 |
| 600 static void Push64SmiOrMint(Assembler* assembler, | 603 static void Push64SmiOrMint(Assembler* assembler, |
| 601 Register reg, | 604 Register reg, |
| (...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1862 } | 1865 } |
| 1863 | 1866 |
| 1864 | 1867 |
| 1865 // Allocates one-byte string of length 'end - start'. The content is not | 1868 // Allocates one-byte string of length 'end - start'. The content is not |
| 1866 // initialized. 'length-reg' contains tagged length. | 1869 // initialized. 'length-reg' contains tagged length. |
| 1867 // Returns new string as tagged pointer in EAX. | 1870 // Returns new string as tagged pointer in EAX. |
| 1868 static void TryAllocateOnebyteString(Assembler* assembler, | 1871 static void TryAllocateOnebyteString(Assembler* assembler, |
| 1869 Label* ok, | 1872 Label* ok, |
| 1870 Label* failure, | 1873 Label* failure, |
| 1871 Register length_reg) { | 1874 Register length_reg) { |
| 1872 __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false); | 1875 __ MaybeTraceAllocation(kOneByteStringCid, EAX, failure, false, |
| 1876 /* inline_isolate = */ false); |
| 1873 if (length_reg != EDI) { | 1877 if (length_reg != EDI) { |
| 1874 __ movl(EDI, length_reg); | 1878 __ movl(EDI, length_reg); |
| 1875 } | 1879 } |
| 1876 Label pop_and_fail; | 1880 Label pop_and_fail; |
| 1877 __ pushl(EDI); // Preserve length. | 1881 __ pushl(EDI); // Preserve length. |
| 1878 __ SmiUntag(EDI); | 1882 __ SmiUntag(EDI); |
| 1879 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1883 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
| 1880 __ leal(EDI, Address(EDI, TIMES_1, fixed_size)); // EDI is untagged. | 1884 __ leal(EDI, Address(EDI, TIMES_1, fixed_size)); // EDI is untagged. |
| 1881 __ andl(EDI, Immediate(-kObjectAlignment)); | 1885 __ andl(EDI, Immediate(-kObjectAlignment)); |
| 1882 | 1886 |
| 1883 Isolate* isolate = Isolate::Current(); | |
| 1884 Heap* heap = isolate->heap(); | |
| 1885 const intptr_t cid = kOneByteStringCid; | 1887 const intptr_t cid = kOneByteStringCid; |
| 1886 Heap::Space space = heap->SpaceForAllocation(cid); | 1888 Heap::Space space = Heap::SpaceForAllocation(cid); |
| 1887 __ movl(EAX, Address::Absolute(heap->TopAddress(space))); | 1889 __ movl(ECX, Address(THR, Thread::heap_offset())); |
| 1890 __ movl(EAX, Address(ECX, Heap::TopOffset(space))); |
| 1888 __ movl(EBX, EAX); | 1891 __ movl(EBX, EAX); |
| 1889 | 1892 |
| 1890 // EDI: allocation size. | 1893 // EDI: allocation size. |
| 1891 __ addl(EBX, EDI); | 1894 __ addl(EBX, EDI); |
| 1892 __ j(CARRY, &pop_and_fail); | 1895 __ j(CARRY, &pop_and_fail); |
| 1893 | 1896 |
| 1894 // Check if the allocation fits into the remaining space. | 1897 // Check if the allocation fits into the remaining space. |
| 1895 // EAX: potential new object start. | 1898 // EAX: potential new object start. |
| 1896 // EBX: potential next object start. | 1899 // EBX: potential next object start. |
| 1897 // EDI: allocation size. | 1900 // EDI: allocation size. |
| 1898 __ cmpl(EBX, Address::Absolute(heap->EndAddress(space))); | 1901 // ECX: heap. |
| 1902 __ cmpl(EBX, Address(ECX, Heap::EndOffset(space))); |
| 1899 __ j(ABOVE_EQUAL, &pop_and_fail); | 1903 __ j(ABOVE_EQUAL, &pop_and_fail); |
| 1900 | 1904 |
| 1901 // Successfully allocated the object(s), now update top to point to | 1905 // Successfully allocated the object(s), now update top to point to |
| 1902 // next object start and initialize the object. | 1906 // next object start and initialize the object. |
| 1903 __ movl(Address::Absolute(heap->TopAddress(space)), EBX); | 1907 __ movl(Address(ECX, Heap::TopOffset(space)), EBX); |
| 1904 __ addl(EAX, Immediate(kHeapObjectTag)); | 1908 __ addl(EAX, Immediate(kHeapObjectTag)); |
| 1905 | 1909 |
| 1906 __ UpdateAllocationStatsWithSize(cid, EDI, kNoRegister, space); | 1910 __ UpdateAllocationStatsWithSize(cid, EDI, ECX, space, |
| 1911 /* inline_isolate = */ false); |
| 1907 | 1912 |
| 1908 // Initialize the tags. | 1913 // Initialize the tags. |
| 1909 // EAX: new object start as a tagged pointer. | 1914 // EAX: new object start as a tagged pointer. |
| 1910 // EBX: new object end address. | 1915 // EBX: new object end address. |
| 1911 // EDI: allocation size. | 1916 // EDI: allocation size. |
| 1912 { | 1917 { |
| 1913 Label size_tag_overflow, done; | 1918 Label size_tag_overflow, done; |
| 1914 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 1919 __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1915 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 1920 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1916 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); | 1921 __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2142 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { | 2147 void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler) { |
| 2143 __ LoadIsolate(EAX); | 2148 __ LoadIsolate(EAX); |
| 2144 __ movl(EAX, Address(EAX, Isolate::current_tag_offset())); | 2149 __ movl(EAX, Address(EAX, Isolate::current_tag_offset())); |
| 2145 __ ret(); | 2150 __ ret(); |
| 2146 } | 2151 } |
| 2147 | 2152 |
| 2148 #undef __ | 2153 #undef __ |
| 2149 } // namespace dart | 2154 } // namespace dart |
| 2150 | 2155 |
| 2151 #endif // defined TARGET_ARCH_IA32 | 2156 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |