OLD | NEW |
1 // Copyright (c) 2012, 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 |
11 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 11 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
(...skipping 27 matching lines...) Expand all Loading... |
39 // Compute the size to be allocated, it is based on the array length | 39 // Compute the size to be allocated, it is based on the array length |
40 // and is computed as: | 40 // and is computed as: |
41 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 41 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
42 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. | 42 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. |
43 // Assert that length is a Smi. | 43 // Assert that length is a Smi. |
44 __ testl(EDI, Immediate(kSmiTagSize)); | 44 __ testl(EDI, Immediate(kSmiTagSize)); |
45 __ j(NOT_ZERO, &fall_through); | 45 __ j(NOT_ZERO, &fall_through); |
46 __ cmpl(EDI, Immediate(0)); | 46 __ cmpl(EDI, Immediate(0)); |
47 __ j(LESS, &fall_through); | 47 __ j(LESS, &fall_through); |
48 // Check for maximum allowed length. | 48 // Check for maximum allowed length. |
49 const Immediate max_len = | 49 const Immediate& max_len = |
50 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); | 50 Immediate(reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements))); |
51 __ cmpl(EDI, max_len); | 51 __ cmpl(EDI, max_len); |
52 __ j(GREATER, &fall_through); | 52 __ j(GREATER, &fall_through); |
53 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 53 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
54 __ leal(EDI, Address(EDI, TIMES_2, fixed_size)); // EDI is a Smi. | 54 __ leal(EDI, Address(EDI, TIMES_2, fixed_size)); // EDI is a Smi. |
55 ASSERT(kSmiTagShift == 1); | 55 ASSERT(kSmiTagShift == 1); |
56 __ andl(EDI, Immediate(-kObjectAlignment)); | 56 __ andl(EDI, Immediate(-kObjectAlignment)); |
57 | 57 |
58 Isolate* isolate = Isolate::Current(); | 58 Isolate* isolate = Isolate::Current(); |
59 Heap* heap = isolate->heap(); | 59 Heap* heap = isolate->heap(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. | 110 __ movl(EDI, Address(ESP, kArrayLengthOffset)); // Array Length. |
111 __ StoreIntoObjectNoBarrier(EAX, | 111 __ StoreIntoObjectNoBarrier(EAX, |
112 FieldAddress(EAX, Array::length_offset()), | 112 FieldAddress(EAX, Array::length_offset()), |
113 EDI); | 113 EDI); |
114 | 114 |
115 // Initialize all array elements to raw_null. | 115 // Initialize all array elements to raw_null. |
116 // EAX: new object start as a tagged pointer. | 116 // EAX: new object start as a tagged pointer. |
117 // EBX: new object end address. | 117 // EBX: new object end address. |
118 // EDI: iterator which initially points to the start of the variable | 118 // EDI: iterator which initially points to the start of the variable |
119 // data area to be initialized. | 119 // data area to be initialized. |
120 const Immediate raw_null = | 120 const Immediate& raw_null = |
121 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 121 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
122 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); | 122 __ leal(EDI, FieldAddress(EAX, sizeof(RawArray))); |
123 Label done; | 123 Label done; |
124 Label init_loop; | 124 Label init_loop; |
125 __ Bind(&init_loop); | 125 __ Bind(&init_loop); |
126 __ cmpl(EDI, EBX); | 126 __ cmpl(EDI, EBX); |
127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
128 __ movl(Address(EDI, 0), raw_null); | 128 __ movl(Address(EDI, 0), raw_null); |
129 __ addl(EDI, Immediate(kWordSize)); | 129 __ addl(EDI, Immediate(kWordSize)); |
130 __ jmp(&init_loop, Assembler::kNearJump); | 130 __ jmp(&init_loop, Assembler::kNearJump); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 | 187 |
188 | 188 |
189 // Intrinsify only for Smi value and index. Non-smi values need a store buffer | 189 // Intrinsify only for Smi value and index. Non-smi values need a store buffer |
190 // update. Array length is always a Smi. | 190 // update. Array length is always a Smi. |
191 bool Intrinsifier::Array_setIndexed(Assembler* assembler) { | 191 bool Intrinsifier::Array_setIndexed(Assembler* assembler) { |
192 Label fall_through; | 192 Label fall_through; |
193 if (FLAG_enable_type_checks) { | 193 if (FLAG_enable_type_checks) { |
194 const intptr_t type_args_field_offset = | 194 const intptr_t type_args_field_offset = |
195 ComputeObjectArrayTypeArgumentsOffset(); | 195 ComputeObjectArrayTypeArgumentsOffset(); |
196 // Inline simple tests (Smi, null), fallthrough if not positive. | 196 // Inline simple tests (Smi, null), fallthrough if not positive. |
197 const Immediate raw_null = | 197 const Immediate& raw_null = |
198 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 198 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
199 Label checked_ok; | 199 Label checked_ok; |
200 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. | 200 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. |
201 // Null value is valid for any type. | 201 // Null value is valid for any type. |
202 __ cmpl(EDI, raw_null); | 202 __ cmpl(EDI, raw_null); |
203 __ j(EQUAL, &checked_ok, Assembler::kNearJump); | 203 __ j(EQUAL, &checked_ok, Assembler::kNearJump); |
204 | 204 |
205 __ movl(EBX, Address(ESP, + 3 * kWordSize)); // Array. | 205 __ movl(EBX, Address(ESP, + 3 * kWordSize)); // Array. |
206 __ movl(EBX, FieldAddress(EBX, type_args_field_offset)); | 206 __ movl(EBX, FieldAddress(EBX, type_args_field_offset)); |
207 // EBX: Type arguments of array. | 207 // EBX: Type arguments of array. |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 if (FLAG_enable_type_checks) return false; | 434 if (FLAG_enable_type_checks) return false; |
435 Label fall_through; | 435 Label fall_through; |
436 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 436 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
437 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 437 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
438 // EBX: length. | 438 // EBX: length. |
439 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset())); | 439 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset())); |
440 // EDI: data. | 440 // EDI: data. |
441 // Compare length with capacity. | 441 // Compare length with capacity. |
442 __ cmpl(EBX, FieldAddress(EDI, Array::length_offset())); | 442 __ cmpl(EBX, FieldAddress(EDI, Array::length_offset())); |
443 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Must grow data. | 443 __ j(EQUAL, &fall_through, Assembler::kNearJump); // Must grow data. |
444 const Immediate value_one = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); | 444 const Immediate& value_one = |
| 445 Immediate(reinterpret_cast<int32_t>(Smi::New(1))); |
445 // len = len + 1; | 446 // len = len + 1; |
446 __ addl(FieldAddress(EAX, GrowableObjectArray::length_offset()), value_one); | 447 __ addl(FieldAddress(EAX, GrowableObjectArray::length_offset()), value_one); |
447 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value | 448 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value |
448 ASSERT(kSmiTagShift == 1); | 449 ASSERT(kSmiTagShift == 1); |
449 __ StoreIntoObject(EDI, | 450 __ StoreIntoObject(EDI, |
450 FieldAddress(EDI, EBX, TIMES_2, Array::data_offset()), | 451 FieldAddress(EDI, EBX, TIMES_2, Array::data_offset()), |
451 EAX); | 452 EAX); |
452 const Immediate raw_null = | 453 const Immediate& raw_null = |
453 Immediate(reinterpret_cast<int32_t>(Object::null())); | 454 Immediate(reinterpret_cast<int32_t>(Object::null())); |
454 __ movl(EAX, raw_null); | 455 __ movl(EAX, raw_null); |
455 __ ret(); | 456 __ ret(); |
456 __ Bind(&fall_through); | 457 __ Bind(&fall_through); |
457 return false; | 458 return false; |
458 } | 459 } |
459 | 460 |
460 | 461 |
461 // Gets the length of a ByteArray. | 462 // Gets the length of a ByteArray. |
462 bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) { | 463 bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) { |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 | 1249 |
1249 bool Intrinsifier::Integer_equal(Assembler* assembler) { | 1250 bool Intrinsifier::Integer_equal(Assembler* assembler) { |
1250 return Integer_equalToInteger(assembler); | 1251 return Integer_equalToInteger(assembler); |
1251 } | 1252 } |
1252 | 1253 |
1253 | 1254 |
1254 bool Intrinsifier::Integer_sar(Assembler* assembler) { | 1255 bool Intrinsifier::Integer_sar(Assembler* assembler) { |
1255 Label fall_through, shift_count_ok; | 1256 Label fall_through, shift_count_ok; |
1256 TestBothArgumentsSmis(assembler, &fall_through); | 1257 TestBothArgumentsSmis(assembler, &fall_through); |
1257 // Can destroy ECX since we are not falling through. | 1258 // Can destroy ECX since we are not falling through. |
1258 Immediate count_limit = Immediate(0x1F); | 1259 const Immediate& count_limit = Immediate(0x1F); |
1259 // Check that the count is not larger than what the hardware can handle. | 1260 // Check that the count is not larger than what the hardware can handle. |
1260 // For shifting right a Smi the result is the same for all numbers | 1261 // For shifting right a Smi the result is the same for all numbers |
1261 // >= count_limit. | 1262 // >= count_limit. |
1262 __ SmiUntag(EAX); | 1263 __ SmiUntag(EAX); |
1263 // Negative counts throw exception. | 1264 // Negative counts throw exception. |
1264 __ cmpl(EAX, Immediate(0)); | 1265 __ cmpl(EAX, Immediate(0)); |
1265 __ j(LESS, &fall_through, Assembler::kNearJump); | 1266 __ j(LESS, &fall_through, Assembler::kNearJump); |
1266 __ cmpl(EAX, count_limit); | 1267 __ cmpl(EAX, count_limit); |
1267 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); | 1268 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); |
1268 __ movl(EAX, count_limit); | 1269 __ movl(EAX, count_limit); |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1672 __ Bind(&is_true); | 1673 __ Bind(&is_true); |
1673 __ LoadObject(EAX, Bool::True()); | 1674 __ LoadObject(EAX, Bool::True()); |
1674 __ ret(); | 1675 __ ret(); |
1675 return true; | 1676 return true; |
1676 } | 1677 } |
1677 | 1678 |
1678 #undef __ | 1679 #undef __ |
1679 } // namespace dart | 1680 } // namespace dart |
1680 | 1681 |
1681 #endif // defined TARGET_ARCH_IA32 | 1682 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |