| 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 11 matching lines...) Expand all Loading... |
| 22 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
| 23 | 23 |
| 24 namespace dart { | 24 namespace dart { |
| 25 | 25 |
| 26 DECLARE_FLAG(bool, enable_type_checks); | 26 DECLARE_FLAG(bool, enable_type_checks); |
| 27 | 27 |
| 28 | 28 |
| 29 #define __ assembler-> | 29 #define __ assembler-> |
| 30 | 30 |
| 31 | 31 |
| 32 void Intrinsifier::Array_getLength(Assembler* assembler) { | 32 void Intrinsifier::ObjectArrayLength(Assembler* assembler) { |
| 33 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 33 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 34 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); | 34 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); |
| 35 __ ret(); | 35 __ ret(); |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { | 39 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) { |
| 40 Array_getLength(assembler); | 40 ObjectArrayLength(assembler); |
| 41 } | 41 } |
| 42 | 42 |
| 43 | 43 |
| 44 void Intrinsifier::Array_getIndexed(Assembler* assembler) { | 44 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) { |
| 45 Label fall_through; | 45 Label fall_through; |
| 46 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 46 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 47 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 47 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
| 48 __ testl(EBX, Immediate(kSmiTagMask)); | 48 __ testl(EBX, Immediate(kSmiTagMask)); |
| 49 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 49 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 50 // Range check. | 50 // Range check. |
| 51 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); | 51 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); |
| 52 // Runtime throws exception. | 52 // Runtime throws exception. |
| 53 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 53 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 54 // Note that EBX is Smi, i.e, times 2. | 54 // Note that EBX is Smi, i.e, times 2. |
| 55 ASSERT(kSmiTagShift == 1); | 55 ASSERT(kSmiTagShift == 1); |
| 56 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); | 56 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); |
| 57 __ ret(); | 57 __ ret(); |
| 58 __ Bind(&fall_through); | 58 __ Bind(&fall_through); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { | 62 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) { |
| 63 Array_getIndexed(assembler); | 63 ObjectArrayGetIndexed(assembler); |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { | 67 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { |
| 68 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 68 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 69 const Class& cls = Class::Handle( | 69 const Class& cls = Class::Handle( |
| 70 core_lib.LookupClassAllowPrivate(Symbols::_List())); | 70 core_lib.LookupClassAllowPrivate(Symbols::_List())); |
| 71 ASSERT(!cls.IsNull()); | 71 ASSERT(!cls.IsNull()); |
| 72 ASSERT(cls.NumTypeArguments() == 1); | 72 ASSERT(cls.NumTypeArguments() == 1); |
| 73 const intptr_t field_offset = cls.type_arguments_field_offset(); | 73 const intptr_t field_offset = cls.type_arguments_field_offset(); |
| 74 ASSERT(field_offset != Class::kNoTypeArguments); | 74 ASSERT(field_offset != Class::kNoTypeArguments); |
| 75 return field_offset; | 75 return field_offset; |
| 76 } | 76 } |
| 77 | 77 |
| 78 | 78 |
| 79 // Intrinsify only for Smi value and index. Non-smi values need a store buffer | 79 // Intrinsify only for Smi value and index. Non-smi values need a store buffer |
| 80 // update. Array length is always a Smi. | 80 // update. Array length is always a Smi. |
| 81 void Intrinsifier::Array_setIndexed(Assembler* assembler) { | 81 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) { |
| 82 Label fall_through; | 82 Label fall_through; |
| 83 if (FLAG_enable_type_checks) { | 83 if (FLAG_enable_type_checks) { |
| 84 const intptr_t type_args_field_offset = | 84 const intptr_t type_args_field_offset = |
| 85 ComputeObjectArrayTypeArgumentsOffset(); | 85 ComputeObjectArrayTypeArgumentsOffset(); |
| 86 // Inline simple tests (Smi, null), fallthrough if not positive. | 86 // Inline simple tests (Smi, null), fallthrough if not positive. |
| 87 const Immediate& raw_null = | 87 const Immediate& raw_null = |
| 88 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 88 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 89 Label checked_ok; | 89 Label checked_ok; |
| 90 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. | 90 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. |
| 91 // Null value is valid for any type. | 91 // Null value is valid for any type. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), | 128 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), |
| 129 ECX); | 129 ECX); |
| 130 // Caller is responsible of preserving the value if necessary. | 130 // Caller is responsible of preserving the value if necessary. |
| 131 __ ret(); | 131 __ ret(); |
| 132 __ Bind(&fall_through); | 132 __ Bind(&fall_through); |
| 133 } | 133 } |
| 134 | 134 |
| 135 | 135 |
| 136 // Allocate a GrowableObjectArray using the backing array specified. | 136 // Allocate a GrowableObjectArray using the backing array specified. |
| 137 // On stack: type argument (+2), data (+1), return-address (+0). | 137 // On stack: type argument (+2), data (+1), return-address (+0). |
| 138 void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { | 138 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { |
| 139 // This snippet of inlined code uses the following registers: | 139 // This snippet of inlined code uses the following registers: |
| 140 // EAX, EBX | 140 // EAX, EBX |
| 141 // and the newly allocated object is returned in EAX. | 141 // and the newly allocated object is returned in EAX. |
| 142 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; | 142 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; |
| 143 const intptr_t kArrayOffset = 1 * kWordSize; | 143 const intptr_t kArrayOffset = 1 * kWordSize; |
| 144 Label fall_through; | 144 Label fall_through; |
| 145 | 145 |
| 146 // Try allocating in new space. | 146 // Try allocating in new space. |
| 147 const Class& cls = Class::Handle( | 147 const Class& cls = Class::Handle( |
| 148 Isolate::Current()->object_store()->growable_object_array_class()); | 148 Isolate::Current()->object_store()->growable_object_array_class()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 168 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), | 168 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), |
| 169 Immediate(0)); | 169 Immediate(0)); |
| 170 __ ret(); // returns the newly allocated object in EAX. | 170 __ ret(); // returns the newly allocated object in EAX. |
| 171 | 171 |
| 172 __ Bind(&fall_through); | 172 __ Bind(&fall_through); |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 // Get length of growable object array. | 176 // Get length of growable object array. |
| 177 // On stack: growable array (+1), return-address (+0). | 177 // On stack: growable array (+1), return-address (+0). |
| 178 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 178 void Intrinsifier::GrowableArrayLength(Assembler* assembler) { |
| 179 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 179 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 180 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 180 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| 181 __ ret(); | 181 __ ret(); |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| 185 // Get capacity of growable object array. | 185 // Get capacity of growable object array. |
| 186 // On stack: growable array (+1), return-address (+0). | 186 // On stack: growable array (+1), return-address (+0). |
| 187 void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { | 187 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) { |
| 188 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 188 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 189 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); | 189 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); |
| 190 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); | 190 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); |
| 191 __ ret(); | 191 __ ret(); |
| 192 } | 192 } |
| 193 | 193 |
| 194 | 194 |
| 195 // Access growable object array at specified index. | 195 // Access growable object array at specified index. |
| 196 // On stack: growable array (+2), index (+1), return-address (+0). | 196 // On stack: growable array (+2), index (+1), return-address (+0). |
| 197 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { | 197 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { |
| 198 Label fall_through; | 198 Label fall_through; |
| 199 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 199 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 200 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. | 200 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. |
| 201 __ testl(EBX, Immediate(kSmiTagMask)); | 201 __ testl(EBX, Immediate(kSmiTagMask)); |
| 202 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 202 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 203 // Range check using _length field. | 203 // Range check using _length field. |
| 204 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 204 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| 205 // Runtime throws exception. | 205 // Runtime throws exception. |
| 206 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 206 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 207 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. | 207 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. |
| 208 | 208 |
| 209 // Note that EBX is Smi, i.e, times 2. | 209 // Note that EBX is Smi, i.e, times 2. |
| 210 ASSERT(kSmiTagShift == 1); | 210 ASSERT(kSmiTagShift == 1); |
| 211 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); | 211 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); |
| 212 __ ret(); | 212 __ ret(); |
| 213 __ Bind(&fall_through); | 213 __ Bind(&fall_through); |
| 214 } | 214 } |
| 215 | 215 |
| 216 | 216 |
| 217 // Set value into growable object array at specified index. | 217 // Set value into growable object array at specified index. |
| 218 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). | 218 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). |
| 219 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { | 219 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) { |
| 220 if (FLAG_enable_type_checks) { | 220 if (FLAG_enable_type_checks) { |
| 221 return; | 221 return; |
| 222 } | 222 } |
| 223 Label fall_through; | 223 Label fall_through; |
| 224 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. | 224 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. |
| 225 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // GrowableArray. | 225 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // GrowableArray. |
| 226 __ testl(EBX, Immediate(kSmiTagMask)); | 226 __ testl(EBX, Immediate(kSmiTagMask)); |
| 227 __ j(NOT_ZERO, &fall_through); // Non-smi index. | 227 __ j(NOT_ZERO, &fall_through); // Non-smi index. |
| 228 // Range check using _length field. | 228 // Range check using _length field. |
| 229 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 229 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| 230 // Runtime throws exception. | 230 // Runtime throws exception. |
| 231 __ j(ABOVE_EQUAL, &fall_through); | 231 __ j(ABOVE_EQUAL, &fall_through); |
| 232 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. | 232 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. |
| 233 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. | 233 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. |
| 234 // Note that EBX is Smi, i.e, times 2. | 234 // Note that EBX is Smi, i.e, times 2. |
| 235 ASSERT(kSmiTagShift == 1); | 235 ASSERT(kSmiTagShift == 1); |
| 236 __ StoreIntoObject(EAX, | 236 __ StoreIntoObject(EAX, |
| 237 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), | 237 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), |
| 238 EDI); | 238 EDI); |
| 239 __ ret(); | 239 __ ret(); |
| 240 __ Bind(&fall_through); | 240 __ Bind(&fall_through); |
| 241 } | 241 } |
| 242 | 242 |
| 243 | 243 |
| 244 // Set length of growable object array. The length cannot | 244 // Set length of growable object array. The length cannot |
| 245 // be greater than the length of the data container. | 245 // be greater than the length of the data container. |
| 246 // On stack: growable array (+2), length (+1), return-address (+0). | 246 // On stack: growable array (+2), length (+1), return-address (+0). |
| 247 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { | 247 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) { |
| 248 Label fall_through; | 248 Label fall_through; |
| 249 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. | 249 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. |
| 250 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value. | 250 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value. |
| 251 __ testl(EBX, Immediate(kSmiTagMask)); | 251 __ testl(EBX, Immediate(kSmiTagMask)); |
| 252 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. | 252 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. |
| 253 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), EBX); | 253 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), EBX); |
| 254 __ ret(); | 254 __ ret(); |
| 255 __ Bind(&fall_through); | 255 __ Bind(&fall_through); |
| 256 } | 256 } |
| 257 | 257 |
| 258 | 258 |
| 259 // Set data of growable object array. | 259 // Set data of growable object array. |
| 260 // On stack: growable array (+2), data (+1), return-address (+0). | 260 // On stack: growable array (+2), data (+1), return-address (+0). |
| 261 void Intrinsifier::GrowableList_setData(Assembler* assembler) { | 261 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { |
| 262 if (FLAG_enable_type_checks) { | 262 if (FLAG_enable_type_checks) { |
| 263 return; | 263 return; |
| 264 } | 264 } |
| 265 Label fall_through; | 265 Label fall_through; |
| 266 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Data. | 266 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Data. |
| 267 // Check that data is an ObjectArray. | 267 // Check that data is an ObjectArray. |
| 268 __ testl(EBX, Immediate(kSmiTagMask)); | 268 __ testl(EBX, Immediate(kSmiTagMask)); |
| 269 __ j(ZERO, &fall_through); // Data is Smi. | 269 __ j(ZERO, &fall_through); // Data is Smi. |
| 270 __ CompareClassId(EBX, kArrayCid, EAX); | 270 __ CompareClassId(EBX, kArrayCid, EAX); |
| 271 __ j(NOT_EQUAL, &fall_through); | 271 __ j(NOT_EQUAL, &fall_through); |
| 272 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. | 272 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. |
| 273 __ StoreIntoObject(EAX, | 273 __ StoreIntoObject(EAX, |
| 274 FieldAddress(EAX, GrowableObjectArray::data_offset()), | 274 FieldAddress(EAX, GrowableObjectArray::data_offset()), |
| 275 EBX); | 275 EBX); |
| 276 __ ret(); | 276 __ ret(); |
| 277 __ Bind(&fall_through); | 277 __ Bind(&fall_through); |
| 278 } | 278 } |
| 279 | 279 |
| 280 | 280 |
| 281 // Add an element to growable array if it doesn't need to grow, otherwise | 281 // Add an element to growable array if it doesn't need to grow, otherwise |
| 282 // call into regular code. | 282 // call into regular code. |
| 283 // On stack: growable array (+2), value (+1), return-address (+0). | 283 // On stack: growable array (+2), value (+1), return-address (+0). |
| 284 void Intrinsifier::GrowableList_add(Assembler* assembler) { | 284 void Intrinsifier::GrowableArray_add(Assembler* assembler) { |
| 285 // In checked mode we need to type-check the incoming argument. | 285 // In checked mode we need to type-check the incoming argument. |
| 286 if (FLAG_enable_type_checks) return; | 286 if (FLAG_enable_type_checks) return; |
| 287 | 287 |
| 288 Label fall_through; | 288 Label fall_through; |
| 289 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 289 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
| 290 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 290 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| 291 // EBX: length. | 291 // EBX: length. |
| 292 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset())); | 292 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset())); |
| 293 // EDI: data. | 293 // EDI: data. |
| 294 // Compare length with capacity. | 294 // Compare length with capacity. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 __ addl(EDI, Immediate(kWordSize)); \ | 400 __ addl(EDI, Immediate(kWordSize)); \ |
| 401 __ jmp(&init_loop, Assembler::kNearJump); \ | 401 __ jmp(&init_loop, Assembler::kNearJump); \ |
| 402 __ Bind(&done); \ | 402 __ Bind(&done); \ |
| 403 \ | 403 \ |
| 404 __ ret(); \ | 404 __ ret(); \ |
| 405 __ Bind(&fall_through); \ | 405 __ Bind(&fall_through); \ |
| 406 | 406 |
| 407 | 407 |
| 408 | 408 |
| 409 // Gets the length of a TypedData. | 409 // Gets the length of a TypedData. |
| 410 void Intrinsifier::TypedData_getLength(Assembler* assembler) { | 410 void Intrinsifier::TypedDataLength(Assembler* assembler) { |
| 411 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 411 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 412 __ movl(EAX, FieldAddress(EAX, TypedData::length_offset())); | 412 __ movl(EAX, FieldAddress(EAX, TypedData::length_offset())); |
| 413 __ ret(); | 413 __ ret(); |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) { | 417 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) { |
| 418 Label fall_through; | 418 Label fall_through; |
| 419 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 419 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 420 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 420 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
| 421 __ testl(EBX, Immediate(kSmiTagMask)); | 421 __ testl(EBX, Immediate(kSmiTagMask)); |
| 422 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 422 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 423 // Range check. | 423 // Range check. |
| 424 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | 424 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); |
| 425 // Runtime throws exception. | 425 // Runtime throws exception. |
| 426 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 426 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 427 | 427 |
| 428 __ SmiUntag(EBX); | 428 __ SmiUntag(EBX); |
| 429 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, TypedData::data_offset())); | 429 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, TypedData::data_offset())); |
| 430 __ SmiTag(EAX); | 430 __ SmiTag(EAX); |
| 431 __ ret(); | 431 __ ret(); |
| 432 __ Bind(&fall_through); | 432 __ Bind(&fall_through); |
| 433 } | 433 } |
| 434 | 434 |
| 435 | 435 |
| 436 void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) { | 436 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) { |
| 437 Label fall_through; | 437 Label fall_through; |
| 438 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 438 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 439 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 439 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
| 440 __ testl(EBX, Immediate(kSmiTagMask)); | 440 __ testl(EBX, Immediate(kSmiTagMask)); |
| 441 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 441 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 442 // Range check. | 442 // Range check. |
| 443 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | 443 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); |
| 444 // Runtime throws exception. | 444 // Runtime throws exception. |
| 445 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 445 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 446 | 446 |
| 447 __ movl(EAX, FieldAddress(EAX, ExternalTypedData::data_offset())); | 447 __ movl(EAX, FieldAddress(EAX, ExternalTypedData::data_offset())); |
| 448 __ SmiUntag(EBX); | 448 __ SmiUntag(EBX); |
| 449 __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0)); | 449 __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0)); |
| 450 __ SmiTag(EAX); | 450 __ SmiTag(EAX); |
| 451 __ ret(); | 451 __ ret(); |
| 452 __ Bind(&fall_through); | 452 __ Bind(&fall_through); |
| 453 } | 453 } |
| 454 | 454 |
| 455 | 455 |
| 456 void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) { | 456 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) { |
| 457 Label fall_through; | 457 Label fall_through; |
| 458 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 458 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 459 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | 459 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. |
| 460 __ testl(EBX, Immediate(kSmiTagMask)); | 460 __ testl(EBX, Immediate(kSmiTagMask)); |
| 461 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 461 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 462 // Range check. | 462 // Range check. |
| 463 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | 463 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); |
| 464 // Runtime throws exception. | 464 // Runtime throws exception. |
| 465 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 465 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 466 | 466 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 479 &fall_through, | 479 &fall_through, |
| 480 Assembler::kNearJump, | 480 Assembler::kNearJump, |
| 481 EAX, // Result register. | 481 EAX, // Result register. |
| 482 EBX); | 482 EBX); |
| 483 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | 483 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); |
| 484 __ ret(); | 484 __ ret(); |
| 485 __ Bind(&fall_through); | 485 __ Bind(&fall_through); |
| 486 } | 486 } |
| 487 | 487 |
| 488 | 488 |
| 489 void Intrinsifier::Float64Array_setIndexed(Assembler* assembler) { | 489 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) { |
| 490 Label fall_through; | 490 Label fall_through; |
| 491 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. | 491 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. |
| 492 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // Array. | 492 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // Array. |
| 493 __ testl(EBX, Immediate(kSmiTagMask)); | 493 __ testl(EBX, Immediate(kSmiTagMask)); |
| 494 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 494 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 495 // Range check. | 495 // Range check. |
| 496 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | 496 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); |
| 497 // Runtime throws exception. | 497 // Runtime throws exception. |
| 498 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 498 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 499 | 499 |
| (...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 __ ret(); | 1255 __ ret(); |
| 1256 __ Bind(&is_zero); | 1256 __ Bind(&is_zero); |
| 1257 // Check for negative zero (get the sign bit). | 1257 // Check for negative zero (get the sign bit). |
| 1258 __ movmskpd(EAX, XMM0); | 1258 __ movmskpd(EAX, XMM0); |
| 1259 __ testl(EAX, Immediate(1)); | 1259 __ testl(EAX, Immediate(1)); |
| 1260 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1260 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| 1261 __ jmp(&is_false, Assembler::kNearJump); | 1261 __ jmp(&is_false, Assembler::kNearJump); |
| 1262 } | 1262 } |
| 1263 | 1263 |
| 1264 | 1264 |
| 1265 void Intrinsifier::Double_toInt(Assembler* assembler) { | 1265 void Intrinsifier::DoubleToInteger(Assembler* assembler) { |
| 1266 __ movl(EAX, Address(ESP, +1 * kWordSize)); | 1266 __ movl(EAX, Address(ESP, +1 * kWordSize)); |
| 1267 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); | 1267 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
| 1268 __ cvttsd2si(EAX, XMM0); | 1268 __ cvttsd2si(EAX, XMM0); |
| 1269 // Overflow is signalled with minint. | 1269 // Overflow is signalled with minint. |
| 1270 Label fall_through; | 1270 Label fall_through; |
| 1271 // Check for overflow and that it fits into Smi. | 1271 // Check for overflow and that it fits into Smi. |
| 1272 __ cmpl(EAX, Immediate(0xC0000000)); | 1272 __ cmpl(EAX, Immediate(0xC0000000)); |
| 1273 __ j(NEGATIVE, &fall_through, Assembler::kNearJump); | 1273 __ j(NEGATIVE, &fall_through, Assembler::kNearJump); |
| 1274 __ SmiTag(EAX); | 1274 __ SmiTag(EAX); |
| 1275 __ ret(); | 1275 __ ret(); |
| 1276 __ Bind(&fall_through); | 1276 __ Bind(&fall_through); |
| 1277 } | 1277 } |
| 1278 | 1278 |
| 1279 | 1279 |
| 1280 // Argument type is not known | 1280 // Argument type is not known |
| 1281 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1281 void Intrinsifier::MathSqrt(Assembler* assembler) { |
| 1282 Label fall_through, is_smi, double_op; | 1282 Label fall_through, is_smi, double_op; |
| 1283 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1283 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1284 // Argument is double and is in EAX. | 1284 // Argument is double and is in EAX. |
| 1285 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); | 1285 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); |
| 1286 __ Bind(&double_op); | 1286 __ Bind(&double_op); |
| 1287 __ sqrtsd(XMM0, XMM1); | 1287 __ sqrtsd(XMM0, XMM1); |
| 1288 const Class& double_class = Class::Handle( | 1288 const Class& double_class = Class::Handle( |
| 1289 Isolate::Current()->object_store()->double_class()); | 1289 Isolate::Current()->object_store()->double_class()); |
| 1290 __ TryAllocate(double_class, | 1290 __ TryAllocate(double_class, |
| 1291 &fall_through, | 1291 &fall_through, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 __ mull(addr_0); | 1335 __ mull(addr_0); |
| 1336 __ addl(EAX, addr_1); | 1336 __ addl(EAX, addr_1); |
| 1337 __ adcl(EDX, Immediate(0)); | 1337 __ adcl(EDX, Immediate(0)); |
| 1338 __ movl(addr_1, EDX); | 1338 __ movl(addr_1, EDX); |
| 1339 __ movl(addr_0, EAX); | 1339 __ movl(addr_0, EAX); |
| 1340 __ ret(); | 1340 __ ret(); |
| 1341 } | 1341 } |
| 1342 | 1342 |
| 1343 | 1343 |
| 1344 // Identity comparison. | 1344 // Identity comparison. |
| 1345 void Intrinsifier::Object_equal(Assembler* assembler) { | 1345 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
| 1346 Label is_true; | 1346 Label is_true; |
| 1347 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | 1347 __ movl(EAX, Address(ESP, + 1 * kWordSize)); |
| 1348 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); | 1348 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); |
| 1349 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1349 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1350 __ LoadObject(EAX, Bool::False()); | 1350 __ LoadObject(EAX, Bool::False()); |
| 1351 __ ret(); | 1351 __ ret(); |
| 1352 __ Bind(&is_true); | 1352 __ Bind(&is_true); |
| 1353 __ LoadObject(EAX, Bool::True()); | 1353 __ LoadObject(EAX, Bool::True()); |
| 1354 __ ret(); | 1354 __ ret(); |
| 1355 } | 1355 } |
| 1356 | 1356 |
| 1357 | 1357 |
| 1358 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1358 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
| 1359 Label fall_through; | 1359 Label fall_through; |
| 1360 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1360 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 1361 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); | 1361 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); |
| 1362 __ cmpl(EAX, Immediate(0)); | 1362 __ cmpl(EAX, Immediate(0)); |
| 1363 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1363 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 1364 __ ret(); | 1364 __ ret(); |
| 1365 __ Bind(&fall_through); | 1365 __ Bind(&fall_through); |
| 1366 // Hash not yet computed. | 1366 // Hash not yet computed. |
| 1367 } | 1367 } |
| 1368 | 1368 |
| 1369 | 1369 |
| 1370 void Intrinsifier::String_getLength(Assembler* assembler) { | 1370 void Intrinsifier::StringBaseLength(Assembler* assembler) { |
| 1371 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1371 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 1372 __ movl(EAX, FieldAddress(EAX, String::length_offset())); | 1372 __ movl(EAX, FieldAddress(EAX, String::length_offset())); |
| 1373 __ ret(); | 1373 __ ret(); |
| 1374 } | 1374 } |
| 1375 | 1375 |
| 1376 | 1376 |
| 1377 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { | 1377 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { |
| 1378 Label fall_through, try_two_byte_string; | 1378 Label fall_through, try_two_byte_string; |
| 1379 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 1379 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 1380 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. | 1380 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. |
| 1381 __ testl(EBX, Immediate(kSmiTagMask)); | 1381 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1382 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 1382 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 1383 // Range check. | 1383 // Range check. |
| 1384 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); | 1384 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); |
| 1385 // Runtime throws exception. | 1385 // Runtime throws exception. |
| 1386 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 1386 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 1387 __ CompareClassId(EAX, kOneByteStringCid, EDI); | 1387 __ CompareClassId(EAX, kOneByteStringCid, EDI); |
| 1388 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); | 1388 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); |
| 1389 __ SmiUntag(EBX); | 1389 __ SmiUntag(EBX); |
| 1390 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); | 1390 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); |
| 1391 __ SmiTag(EAX); | 1391 __ SmiTag(EAX); |
| 1392 __ ret(); | 1392 __ ret(); |
| 1393 | 1393 |
| 1394 __ Bind(&try_two_byte_string); | 1394 __ Bind(&try_two_byte_string); |
| 1395 __ CompareClassId(EAX, kTwoByteStringCid, EDI); | 1395 __ CompareClassId(EAX, kTwoByteStringCid, EDI); |
| 1396 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1396 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
| 1397 ASSERT(kSmiTagShift == 1); | 1397 ASSERT(kSmiTagShift == 1); |
| 1398 __ movzxw(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); | 1398 __ movzxw(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); |
| 1399 __ SmiTag(EAX); | 1399 __ SmiTag(EAX); |
| 1400 __ ret(); | 1400 __ ret(); |
| 1401 | 1401 |
| 1402 __ Bind(&fall_through); | 1402 __ Bind(&fall_through); |
| 1403 } | 1403 } |
| 1404 | 1404 |
| 1405 | 1405 |
| 1406 void Intrinsifier::String_getIsEmpty(Assembler* assembler) { | 1406 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { |
| 1407 Label is_true; | 1407 Label is_true; |
| 1408 // Get length. | 1408 // Get length. |
| 1409 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1409 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 1410 __ movl(EAX, FieldAddress(EAX, String::length_offset())); | 1410 __ movl(EAX, FieldAddress(EAX, String::length_offset())); |
| 1411 __ cmpl(EAX, Immediate(Smi::RawValue(0))); | 1411 __ cmpl(EAX, Immediate(Smi::RawValue(0))); |
| 1412 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1412 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1413 __ LoadObject(EAX, Bool::False()); | 1413 __ LoadObject(EAX, Bool::False()); |
| 1414 __ ret(); | 1414 __ ret(); |
| 1415 __ Bind(&is_true); | 1415 __ Bind(&is_true); |
| 1416 __ LoadObject(EAX, Bool::True()); | 1416 __ LoadObject(EAX, Bool::True()); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1607 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL); | 1607 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL); |
| 1608 __ incl(EDX); | 1608 __ incl(EDX); |
| 1609 __ Bind(&check); | 1609 __ Bind(&check); |
| 1610 __ cmpl(EDX, ECX); | 1610 __ cmpl(EDX, ECX); |
| 1611 __ j(LESS, &loop, Assembler::kNearJump); | 1611 __ j(LESS, &loop, Assembler::kNearJump); |
| 1612 __ ret(); | 1612 __ ret(); |
| 1613 __ Bind(&fall_through); | 1613 __ Bind(&fall_through); |
| 1614 } | 1614 } |
| 1615 | 1615 |
| 1616 | 1616 |
| 1617 void Intrinsifier::OneByteString_setAt(Assembler* assembler) { | 1617 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { |
| 1618 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. | 1618 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. |
| 1619 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. | 1619 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. |
| 1620 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // OneByteString. | 1620 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // OneByteString. |
| 1621 __ SmiUntag(EBX); | 1621 __ SmiUntag(EBX); |
| 1622 __ SmiUntag(ECX); | 1622 __ SmiUntag(ECX); |
| 1623 __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL); | 1623 __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL); |
| 1624 __ ret(); | 1624 __ ret(); |
| 1625 } | 1625 } |
| 1626 | 1626 |
| 1627 | 1627 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 Isolate::current_tag_offset()); | 1747 Isolate::current_tag_offset()); |
| 1748 // Set return value to Isolate::current_tag_. | 1748 // Set return value to Isolate::current_tag_. |
| 1749 __ movl(EAX, current_tag_addr); | 1749 __ movl(EAX, current_tag_addr); |
| 1750 __ ret(); | 1750 __ ret(); |
| 1751 } | 1751 } |
| 1752 | 1752 |
| 1753 #undef __ | 1753 #undef __ |
| 1754 } // namespace dart | 1754 } // namespace dart |
| 1755 | 1755 |
| 1756 #endif // defined TARGET_ARCH_IA32 | 1756 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |