| 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/instructions.h" | 12 #include "vm/instructions.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 DECLARE_FLAG(bool, enable_type_checks); | 18 DECLARE_FLAG(bool, enable_type_checks); |
| 19 | 19 |
| 20 // When entering intrinsics code: | 20 // When entering intrinsics code: |
| 21 // RBX: IC Data | 21 // RBX: IC Data |
| 22 // R10: Arguments descriptor | 22 // R10: Arguments descriptor |
| 23 // TOS: Return address | 23 // TOS: Return address |
| 24 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e., | 24 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e., |
| 25 // the methods returns true). | 25 // the methods returns true). |
| 26 | 26 |
| 27 #define __ assembler-> | 27 #define __ assembler-> |
| 28 | 28 |
| 29 | 29 |
| 30 void Intrinsifier::Array_getLength(Assembler* assembler) { | 30 void Intrinsifier::ObjectArrayLength(Assembler* assembler) { |
| 31 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 31 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 32 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); | 32 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); |
| 33 __ ret(); | 33 __ ret(); |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { | 37 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) { |
| 38 Array_getLength(assembler); | 38 ObjectArrayLength(assembler); |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 void Intrinsifier::Array_getIndexed(Assembler* assembler) { | 42 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) { |
| 43 Label fall_through; | 43 Label fall_through; |
| 44 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 44 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 45 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 45 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 46 __ testq(RCX, Immediate(kSmiTagMask)); | 46 __ testq(RCX, Immediate(kSmiTagMask)); |
| 47 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 47 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 48 // Range check. | 48 // Range check. |
| 49 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); | 49 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); |
| 50 // Runtime throws exception. | 50 // Runtime throws exception. |
| 51 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 51 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 52 // Note that RBX is Smi, i.e, times 2. | 52 // Note that RBX is Smi, i.e, times 2. |
| 53 ASSERT(kSmiTagShift == 1); | 53 ASSERT(kSmiTagShift == 1); |
| 54 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); | 54 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); |
| 55 __ ret(); | 55 __ ret(); |
| 56 __ Bind(&fall_through); | 56 __ Bind(&fall_through); |
| 57 } | 57 } |
| 58 | 58 |
| 59 | 59 |
| 60 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { | 60 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) { |
| 61 Array_getIndexed(assembler); | 61 ObjectArrayGetIndexed(assembler); |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| 65 void Intrinsifier::Array_setIndexed(Assembler* assembler) { | 65 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) { |
| 66 if (FLAG_enable_type_checks) { | 66 if (FLAG_enable_type_checks) { |
| 67 return; | 67 return; |
| 68 } | 68 } |
| 69 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. | 69 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. |
| 70 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. | 70 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. |
| 71 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array. | 71 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array. |
| 72 Label fall_through; | 72 Label fall_through; |
| 73 __ testq(RCX, Immediate(kSmiTagMask)); | 73 __ testq(RCX, Immediate(kSmiTagMask)); |
| 74 __ j(NOT_ZERO, &fall_through); | 74 __ j(NOT_ZERO, &fall_through); |
| 75 // Range check. | 75 // Range check. |
| 76 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); | 76 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); |
| 77 // Runtime throws exception. | 77 // Runtime throws exception. |
| 78 __ j(ABOVE_EQUAL, &fall_through); | 78 __ j(ABOVE_EQUAL, &fall_through); |
| 79 // Note that RBX is Smi, i.e, times 2. | 79 // Note that RBX is Smi, i.e, times 2. |
| 80 ASSERT(kSmiTagShift == 1); | 80 ASSERT(kSmiTagShift == 1); |
| 81 // Destroy RCX (ic data) as we will not continue in the function. | 81 // Destroy RCX (ic data) as we will not continue in the function. |
| 82 __ StoreIntoObject(RAX, | 82 __ StoreIntoObject(RAX, |
| 83 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), | 83 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), |
| 84 RDX); | 84 RDX); |
| 85 // Caller is responsible of preserving the value if necessary. | 85 // Caller is responsible of preserving the value if necessary. |
| 86 __ ret(); | 86 __ ret(); |
| 87 __ Bind(&fall_through); | 87 __ Bind(&fall_through); |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 // Allocate a GrowableObjectArray using the backing array specified. | 91 // Allocate a GrowableObjectArray using the backing array specified. |
| 92 // On stack: type argument (+2), data (+1), return-address (+0). | 92 // On stack: type argument (+2), data (+1), return-address (+0). |
| 93 void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { | 93 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { |
| 94 // This snippet of inlined code uses the following registers: | 94 // This snippet of inlined code uses the following registers: |
| 95 // RAX, RCX, R13 | 95 // RAX, RCX, R13 |
| 96 // and the newly allocated object is returned in RAX. | 96 // and the newly allocated object is returned in RAX. |
| 97 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; | 97 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; |
| 98 const intptr_t kArrayOffset = 1 * kWordSize; | 98 const intptr_t kArrayOffset = 1 * kWordSize; |
| 99 Label fall_through; | 99 Label fall_through; |
| 100 | 100 |
| 101 // Try allocating in new space. | 101 // Try allocating in new space. |
| 102 const Class& cls = Class::Handle( | 102 const Class& cls = Class::Handle( |
| 103 Isolate::Current()->object_store()->growable_object_array_class()); | 103 Isolate::Current()->object_store()->growable_object_array_class()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 123 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), | 123 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), |
| 124 Immediate(0)); | 124 Immediate(0)); |
| 125 __ ret(); // returns the newly allocated object in RAX. | 125 __ ret(); // returns the newly allocated object in RAX. |
| 126 | 126 |
| 127 __ Bind(&fall_through); | 127 __ Bind(&fall_through); |
| 128 } | 128 } |
| 129 | 129 |
| 130 | 130 |
| 131 // Get length of growable object array. | 131 // Get length of growable object array. |
| 132 // On stack: growable array (+1), return-address (+0). | 132 // On stack: growable array (+1), return-address (+0). |
| 133 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { | 133 void Intrinsifier::GrowableArrayLength(Assembler* assembler) { |
| 134 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 134 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 135 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset())); | 135 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset())); |
| 136 __ ret(); | 136 __ ret(); |
| 137 } | 137 } |
| 138 | 138 |
| 139 | 139 |
| 140 void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { | 140 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) { |
| 141 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 141 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 142 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); | 142 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); |
| 143 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); | 143 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); |
| 144 __ ret(); | 144 __ ret(); |
| 145 } | 145 } |
| 146 | 146 |
| 147 | 147 |
| 148 // Access growable object array at specified index. | 148 // Access growable object array at specified index. |
| 149 // On stack: growable array (+2), index (+1), return-address (+0). | 149 // On stack: growable array (+2), index (+1), return-address (+0). |
| 150 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { | 150 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { |
| 151 Label fall_through; | 151 Label fall_through; |
| 152 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 152 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 153 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // GrowableArray. | 153 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // GrowableArray. |
| 154 __ testq(RCX, Immediate(kSmiTagMask)); | 154 __ testq(RCX, Immediate(kSmiTagMask)); |
| 155 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 155 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 156 // Range check using _length field. | 156 // Range check using _length field. |
| 157 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); | 157 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); |
| 158 // Runtime throws exception. | 158 // Runtime throws exception. |
| 159 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 159 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 160 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. | 160 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. |
| 161 | 161 |
| 162 // Note that RCX is Smi, i.e, times 4. | 162 // Note that RCX is Smi, i.e, times 4. |
| 163 ASSERT(kSmiTagShift == 1); | 163 ASSERT(kSmiTagShift == 1); |
| 164 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); | 164 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); |
| 165 __ ret(); | 165 __ ret(); |
| 166 __ Bind(&fall_through); | 166 __ Bind(&fall_through); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 // Set value into growable object array at specified index. | 170 // Set value into growable object array at specified index. |
| 171 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). | 171 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). |
| 172 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { | 172 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) { |
| 173 if (FLAG_enable_type_checks) { | 173 if (FLAG_enable_type_checks) { |
| 174 return; | 174 return; |
| 175 } | 175 } |
| 176 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. | 176 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. |
| 177 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. | 177 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. |
| 178 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // GrowableArray. | 178 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // GrowableArray. |
| 179 Label fall_through; | 179 Label fall_through; |
| 180 __ testq(RCX, Immediate(kSmiTagMask)); | 180 __ testq(RCX, Immediate(kSmiTagMask)); |
| 181 __ j(NOT_ZERO, &fall_through); // Non-smi index. | 181 __ j(NOT_ZERO, &fall_through); // Non-smi index. |
| 182 // Range check using _length field. | 182 // Range check using _length field. |
| 183 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); | 183 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); |
| 184 // Runtime throws exception. | 184 // Runtime throws exception. |
| 185 __ j(ABOVE_EQUAL, &fall_through); | 185 __ j(ABOVE_EQUAL, &fall_through); |
| 186 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. | 186 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. |
| 187 // Note that RCX is Smi, i.e, times 4. | 187 // Note that RCX is Smi, i.e, times 4. |
| 188 ASSERT(kSmiTagShift == 1); | 188 ASSERT(kSmiTagShift == 1); |
| 189 __ StoreIntoObject(RAX, | 189 __ StoreIntoObject(RAX, |
| 190 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), | 190 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), |
| 191 RDX); | 191 RDX); |
| 192 __ ret(); | 192 __ ret(); |
| 193 __ Bind(&fall_through); | 193 __ Bind(&fall_through); |
| 194 } | 194 } |
| 195 | 195 |
| 196 | 196 |
| 197 // Set length of growable object array. The length cannot | 197 // Set length of growable object array. The length cannot |
| 198 // be greater than the length of the data container. | 198 // be greater than the length of the data container. |
| 199 // On stack: growable array (+2), length (+1), return-address (+0). | 199 // On stack: growable array (+2), length (+1), return-address (+0). |
| 200 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { | 200 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) { |
| 201 Label fall_through; | 201 Label fall_through; |
| 202 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. | 202 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. |
| 203 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value. | 203 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value. |
| 204 __ testq(RCX, Immediate(kSmiTagMask)); | 204 __ testq(RCX, Immediate(kSmiTagMask)); |
| 205 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. | 205 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. |
| 206 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), RCX); | 206 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), RCX); |
| 207 __ ret(); | 207 __ ret(); |
| 208 __ Bind(&fall_through); | 208 __ Bind(&fall_through); |
| 209 } | 209 } |
| 210 | 210 |
| 211 | 211 |
| 212 // Set data of growable object array. | 212 // Set data of growable object array. |
| 213 // On stack: growable array (+2), data (+1), return-address (+0). | 213 // On stack: growable array (+2), data (+1), return-address (+0). |
| 214 void Intrinsifier::GrowableList_setData(Assembler* assembler) { | 214 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { |
| 215 if (FLAG_enable_type_checks) { | 215 if (FLAG_enable_type_checks) { |
| 216 return; | 216 return; |
| 217 } | 217 } |
| 218 Label fall_through; | 218 Label fall_through; |
| 219 __ movq(RBX, Address(RSP, + 1 * kWordSize)); /// Data. | 219 __ movq(RBX, Address(RSP, + 1 * kWordSize)); /// Data. |
| 220 __ testq(RBX, Immediate(kSmiTagMask)); | 220 __ testq(RBX, Immediate(kSmiTagMask)); |
| 221 __ j(ZERO, &fall_through); // Data is Smi. | 221 __ j(ZERO, &fall_through); // Data is Smi. |
| 222 __ CompareClassId(RBX, kArrayCid); | 222 __ CompareClassId(RBX, kArrayCid); |
| 223 __ j(NOT_EQUAL, &fall_through); | 223 __ j(NOT_EQUAL, &fall_through); |
| 224 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. | 224 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. |
| 225 __ StoreIntoObject(RAX, | 225 __ StoreIntoObject(RAX, |
| 226 FieldAddress(RAX, GrowableObjectArray::data_offset()), | 226 FieldAddress(RAX, GrowableObjectArray::data_offset()), |
| 227 RBX); | 227 RBX); |
| 228 __ ret(); | 228 __ ret(); |
| 229 __ Bind(&fall_through); | 229 __ Bind(&fall_through); |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 // Add an element to growable array if it doesn't need to grow, otherwise | 233 // Add an element to growable array if it doesn't need to grow, otherwise |
| 234 // call into regular code. | 234 // call into regular code. |
| 235 // On stack: growable array (+2), value (+1), return-address (+0). | 235 // On stack: growable array (+2), value (+1), return-address (+0). |
| 236 void Intrinsifier::GrowableList_add(Assembler* assembler) { | 236 void Intrinsifier::GrowableArray_add(Assembler* assembler) { |
| 237 // In checked mode we need to check the incoming argument. | 237 // In checked mode we need to check the incoming argument. |
| 238 if (FLAG_enable_type_checks) return; | 238 if (FLAG_enable_type_checks) return; |
| 239 Label fall_through; | 239 Label fall_through; |
| 240 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 240 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 241 __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); | 241 __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); |
| 242 // RCX: length. | 242 // RCX: length. |
| 243 __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset())); | 243 __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset())); |
| 244 // RDX: data. | 244 // RDX: data. |
| 245 // Compare length with capacity. | 245 // Compare length with capacity. |
| 246 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset())); | 246 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset())); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 __ movq(Address(RDI, 0), RBX); \ | 352 __ movq(Address(RDI, 0), RBX); \ |
| 353 __ addq(RDI, Immediate(kWordSize)); \ | 353 __ addq(RDI, Immediate(kWordSize)); \ |
| 354 __ jmp(&init_loop, Assembler::kNearJump); \ | 354 __ jmp(&init_loop, Assembler::kNearJump); \ |
| 355 __ Bind(&done); \ | 355 __ Bind(&done); \ |
| 356 \ | 356 \ |
| 357 __ ret(); \ | 357 __ ret(); \ |
| 358 __ Bind(&fall_through); \ | 358 __ Bind(&fall_through); \ |
| 359 | 359 |
| 360 | 360 |
| 361 // Gets the length of a TypedData. | 361 // Gets the length of a TypedData. |
| 362 void Intrinsifier::TypedData_getLength(Assembler* assembler) { | 362 void Intrinsifier::TypedDataLength(Assembler* assembler) { |
| 363 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 363 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 364 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset())); | 364 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset())); |
| 365 __ ret(); | 365 __ ret(); |
| 366 } | 366 } |
| 367 | 367 |
| 368 | 368 |
| 369 void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) { | 369 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) { |
| 370 Label fall_through; | 370 Label fall_through; |
| 371 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 371 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 372 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 372 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 373 __ testq(RCX, Immediate(kSmiTagMask)); | 373 __ testq(RCX, Immediate(kSmiTagMask)); |
| 374 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 374 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 375 // Range check. | 375 // Range check. |
| 376 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); | 376 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); |
| 377 // Runtime throws exception. | 377 // Runtime throws exception. |
| 378 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 378 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 379 | 379 |
| 380 __ SmiUntag(RCX); | 380 __ SmiUntag(RCX); |
| 381 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, TypedData::data_offset())); | 381 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, TypedData::data_offset())); |
| 382 __ SmiTag(RAX); | 382 __ SmiTag(RAX); |
| 383 __ ret(); | 383 __ ret(); |
| 384 __ Bind(&fall_through); | 384 __ Bind(&fall_through); |
| 385 } | 385 } |
| 386 | 386 |
| 387 | 387 |
| 388 void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) { | 388 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) { |
| 389 Label fall_through; | 389 Label fall_through; |
| 390 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 390 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 391 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 391 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 392 __ testq(RCX, Immediate(kSmiTagMask)); | 392 __ testq(RCX, Immediate(kSmiTagMask)); |
| 393 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 393 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 394 // Range check. | 394 // Range check. |
| 395 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); | 395 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); |
| 396 // Runtime throws exception. | 396 // Runtime throws exception. |
| 397 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 397 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 398 | 398 |
| 399 __ movq(RAX, FieldAddress(RAX, ExternalTypedData::data_offset())); | 399 __ movq(RAX, FieldAddress(RAX, ExternalTypedData::data_offset())); |
| 400 __ SmiUntag(RCX); | 400 __ SmiUntag(RCX); |
| 401 __ movzxb(RAX, Address(RAX, RCX, TIMES_1, 0)); | 401 __ movzxb(RAX, Address(RAX, RCX, TIMES_1, 0)); |
| 402 __ SmiTag(RAX); | 402 __ SmiTag(RAX); |
| 403 __ ret(); | 403 __ ret(); |
| 404 __ Bind(&fall_through); | 404 __ Bind(&fall_through); |
| 405 } | 405 } |
| 406 | 406 |
| 407 | 407 |
| 408 void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) { | 408 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) { |
| 409 Label fall_through; | 409 Label fall_through; |
| 410 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 410 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 411 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 411 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 412 __ testq(RCX, Immediate(kSmiTagMask)); | 412 __ testq(RCX, Immediate(kSmiTagMask)); |
| 413 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 413 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 414 // Range check. | 414 // Range check. |
| 415 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); | 415 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); |
| 416 // Runtime throws exception. | 416 // Runtime throws exception. |
| 417 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 417 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 418 | 418 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 431 &fall_through, | 431 &fall_through, |
| 432 Assembler::kNearJump, | 432 Assembler::kNearJump, |
| 433 RAX, // Result register. | 433 RAX, // Result register. |
| 434 kNoRegister); | 434 kNoRegister); |
| 435 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); | 435 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); |
| 436 __ ret(); | 436 __ ret(); |
| 437 __ Bind(&fall_through); | 437 __ Bind(&fall_through); |
| 438 } | 438 } |
| 439 | 439 |
| 440 | 440 |
| 441 void Intrinsifier::Float64Array_setIndexed(Assembler* assembler) { | 441 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) { |
| 442 Label fall_through; | 442 Label fall_through; |
| 443 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. | 443 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. |
| 444 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array. | 444 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array. |
| 445 __ testq(RCX, Immediate(kSmiTagMask)); | 445 __ testq(RCX, Immediate(kSmiTagMask)); |
| 446 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 446 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 447 // Range check. | 447 // Range check. |
| 448 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); | 448 __ cmpq(RCX, FieldAddress(RAX, TypedData::length_offset())); |
| 449 // Runtime throws exception. | 449 // Runtime throws exception. |
| 450 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 450 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 451 | 451 |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 __ ret(); | 1157 __ ret(); |
| 1158 __ Bind(&is_zero); | 1158 __ Bind(&is_zero); |
| 1159 // Check for negative zero (get the sign bit). | 1159 // Check for negative zero (get the sign bit). |
| 1160 __ movmskpd(RAX, XMM0); | 1160 __ movmskpd(RAX, XMM0); |
| 1161 __ testq(RAX, Immediate(1)); | 1161 __ testq(RAX, Immediate(1)); |
| 1162 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); | 1162 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| 1163 __ jmp(&is_false, Assembler::kNearJump); | 1163 __ jmp(&is_false, Assembler::kNearJump); |
| 1164 } | 1164 } |
| 1165 | 1165 |
| 1166 | 1166 |
| 1167 void Intrinsifier::Double_toInt(Assembler* assembler) { | 1167 void Intrinsifier::DoubleToInteger(Assembler* assembler) { |
| 1168 __ movq(RAX, Address(RSP, +1 * kWordSize)); | 1168 __ movq(RAX, Address(RSP, +1 * kWordSize)); |
| 1169 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); | 1169 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); |
| 1170 __ cvttsd2siq(RAX, XMM0); | 1170 __ cvttsd2siq(RAX, XMM0); |
| 1171 // Overflow is signalled with minint. | 1171 // Overflow is signalled with minint. |
| 1172 Label fall_through; | 1172 Label fall_through; |
| 1173 // Check for overflow and that it fits into Smi. | 1173 // Check for overflow and that it fits into Smi. |
| 1174 __ movq(RCX, RAX); | 1174 __ movq(RCX, RAX); |
| 1175 __ shlq(RCX, Immediate(1)); | 1175 __ shlq(RCX, Immediate(1)); |
| 1176 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); | 1176 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); |
| 1177 __ SmiTag(RAX); | 1177 __ SmiTag(RAX); |
| 1178 __ ret(); | 1178 __ ret(); |
| 1179 __ Bind(&fall_through); | 1179 __ Bind(&fall_through); |
| 1180 } | 1180 } |
| 1181 | 1181 |
| 1182 | 1182 |
| 1183 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 1183 void Intrinsifier::MathSqrt(Assembler* assembler) { |
| 1184 Label fall_through, is_smi, double_op; | 1184 Label fall_through, is_smi, double_op; |
| 1185 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 1185 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| 1186 // Argument is double and is in RAX. | 1186 // Argument is double and is in RAX. |
| 1187 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); | 1187 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); |
| 1188 __ Bind(&double_op); | 1188 __ Bind(&double_op); |
| 1189 __ sqrtsd(XMM0, XMM1); | 1189 __ sqrtsd(XMM0, XMM1); |
| 1190 const Class& double_class = Class::Handle( | 1190 const Class& double_class = Class::Handle( |
| 1191 Isolate::Current()->object_store()->double_class()); | 1191 Isolate::Current()->object_store()->double_class()); |
| 1192 __ TryAllocate(double_class, | 1192 __ TryAllocate(double_class, |
| 1193 &fall_through, | 1193 &fall_through, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1234 __ imulq(RCX, RAX); | 1234 __ imulq(RCX, RAX); |
| 1235 __ movl(RDX, addr_1); | 1235 __ movl(RDX, addr_1); |
| 1236 __ addq(RDX, RCX); | 1236 __ addq(RDX, RCX); |
| 1237 __ movl(addr_0, RDX); | 1237 __ movl(addr_0, RDX); |
| 1238 __ shrq(RDX, Immediate(32)); | 1238 __ shrq(RDX, Immediate(32)); |
| 1239 __ movl(addr_1, RDX); | 1239 __ movl(addr_1, RDX); |
| 1240 __ ret(); | 1240 __ ret(); |
| 1241 } | 1241 } |
| 1242 | 1242 |
| 1243 // Identity comparison. | 1243 // Identity comparison. |
| 1244 void Intrinsifier::Object_equal(Assembler* assembler) { | 1244 void Intrinsifier::ObjectEquals(Assembler* assembler) { |
| 1245 Label is_true; | 1245 Label is_true; |
| 1246 const intptr_t kReceiverOffset = 2; | 1246 const intptr_t kReceiverOffset = 2; |
| 1247 const intptr_t kArgumentOffset = 1; | 1247 const intptr_t kArgumentOffset = 1; |
| 1248 | 1248 |
| 1249 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); | 1249 __ movq(RAX, Address(RSP, + kArgumentOffset * kWordSize)); |
| 1250 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); | 1250 __ cmpq(RAX, Address(RSP, + kReceiverOffset * kWordSize)); |
| 1251 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1251 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1252 __ LoadObject(RAX, Bool::False(), PP); | 1252 __ LoadObject(RAX, Bool::False(), PP); |
| 1253 __ ret(); | 1253 __ ret(); |
| 1254 __ Bind(&is_true); | 1254 __ Bind(&is_true); |
| 1255 __ LoadObject(RAX, Bool::True(), PP); | 1255 __ LoadObject(RAX, Bool::True(), PP); |
| 1256 __ ret(); | 1256 __ ret(); |
| 1257 } | 1257 } |
| 1258 | 1258 |
| 1259 | 1259 |
| 1260 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1260 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
| 1261 Label fall_through; | 1261 Label fall_through; |
| 1262 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1262 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1263 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1263 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); |
| 1264 __ cmpq(RAX, Immediate(0)); | 1264 __ cmpq(RAX, Immediate(0)); |
| 1265 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1265 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 1266 __ ret(); | 1266 __ ret(); |
| 1267 __ Bind(&fall_through); | 1267 __ Bind(&fall_through); |
| 1268 // Hash not yet computed. | 1268 // Hash not yet computed. |
| 1269 } | 1269 } |
| 1270 | 1270 |
| 1271 | 1271 |
| 1272 void Intrinsifier::String_getLength(Assembler* assembler) { | 1272 void Intrinsifier::StringBaseLength(Assembler* assembler) { |
| 1273 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1273 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1274 __ movq(RAX, FieldAddress(RAX, String::length_offset())); | 1274 __ movq(RAX, FieldAddress(RAX, String::length_offset())); |
| 1275 __ ret(); | 1275 __ ret(); |
| 1276 } | 1276 } |
| 1277 | 1277 |
| 1278 | 1278 |
| 1279 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { | 1279 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { |
| 1280 Label fall_through, try_two_byte_string; | 1280 Label fall_through, try_two_byte_string; |
| 1281 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. | 1281 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. |
| 1282 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // String. | 1282 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // String. |
| 1283 __ testq(RCX, Immediate(kSmiTagMask)); | 1283 __ testq(RCX, Immediate(kSmiTagMask)); |
| 1284 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 1284 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 1285 // Range check. | 1285 // Range check. |
| 1286 __ cmpq(RCX, FieldAddress(RAX, String::length_offset())); | 1286 __ cmpq(RCX, FieldAddress(RAX, String::length_offset())); |
| 1287 // Runtime throws exception. | 1287 // Runtime throws exception. |
| 1288 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 1288 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| 1289 __ CompareClassId(RAX, kOneByteStringCid); | 1289 __ CompareClassId(RAX, kOneByteStringCid); |
| 1290 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); | 1290 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); |
| 1291 __ SmiUntag(RCX); | 1291 __ SmiUntag(RCX); |
| 1292 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); | 1292 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); |
| 1293 __ SmiTag(RAX); | 1293 __ SmiTag(RAX); |
| 1294 __ ret(); | 1294 __ ret(); |
| 1295 | 1295 |
| 1296 __ Bind(&try_two_byte_string); | 1296 __ Bind(&try_two_byte_string); |
| 1297 __ CompareClassId(RAX, kTwoByteStringCid); | 1297 __ CompareClassId(RAX, kTwoByteStringCid); |
| 1298 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1298 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
| 1299 ASSERT(kSmiTagShift == 1); | 1299 ASSERT(kSmiTagShift == 1); |
| 1300 __ movzxw(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); | 1300 __ movzxw(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); |
| 1301 __ SmiTag(RAX); | 1301 __ SmiTag(RAX); |
| 1302 __ ret(); | 1302 __ ret(); |
| 1303 | 1303 |
| 1304 __ Bind(&fall_through); | 1304 __ Bind(&fall_through); |
| 1305 } | 1305 } |
| 1306 | 1306 |
| 1307 | 1307 |
| 1308 void Intrinsifier::String_getIsEmpty(Assembler* assembler) { | 1308 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { |
| 1309 Label is_true; | 1309 Label is_true; |
| 1310 // Get length. | 1310 // Get length. |
| 1311 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. | 1311 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. |
| 1312 __ movq(RAX, FieldAddress(RAX, String::length_offset())); | 1312 __ movq(RAX, FieldAddress(RAX, String::length_offset())); |
| 1313 __ cmpq(RAX, Immediate(Smi::RawValue(0))); | 1313 __ cmpq(RAX, Immediate(Smi::RawValue(0))); |
| 1314 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1314 __ j(EQUAL, &is_true, Assembler::kNearJump); |
| 1315 __ LoadObject(RAX, Bool::False(), PP); | 1315 __ LoadObject(RAX, Bool::False(), PP); |
| 1316 __ ret(); | 1316 __ ret(); |
| 1317 __ Bind(&is_true); | 1317 __ Bind(&is_true); |
| 1318 __ LoadObject(RAX, Bool::True(), PP); | 1318 __ LoadObject(RAX, Bool::True(), PP); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX); | 1510 __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX); |
| 1511 __ incq(RDX); | 1511 __ incq(RDX); |
| 1512 __ Bind(&check); | 1512 __ Bind(&check); |
| 1513 __ cmpq(RDX, RCX); | 1513 __ cmpq(RDX, RCX); |
| 1514 __ j(LESS, &loop, Assembler::kNearJump); | 1514 __ j(LESS, &loop, Assembler::kNearJump); |
| 1515 __ ret(); | 1515 __ ret(); |
| 1516 __ Bind(&fall_through); | 1516 __ Bind(&fall_through); |
| 1517 } | 1517 } |
| 1518 | 1518 |
| 1519 | 1519 |
| 1520 void Intrinsifier::OneByteString_setAt(Assembler* assembler) { | 1520 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { |
| 1521 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Value. | 1521 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Value. |
| 1522 __ movq(RBX, Address(RSP, + 2 * kWordSize)); // Index. | 1522 __ movq(RBX, Address(RSP, + 2 * kWordSize)); // Index. |
| 1523 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // OneByteString. | 1523 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // OneByteString. |
| 1524 __ SmiUntag(RBX); | 1524 __ SmiUntag(RBX); |
| 1525 __ SmiUntag(RCX); | 1525 __ SmiUntag(RCX); |
| 1526 __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX); | 1526 __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX); |
| 1527 __ ret(); | 1527 __ ret(); |
| 1528 } | 1528 } |
| 1529 | 1529 |
| 1530 | 1530 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 // Set return value to Isolate::current_tag_. | 1651 // Set return value to Isolate::current_tag_. |
| 1652 __ movq(RAX, Address(RBX, Isolate::current_tag_offset())); | 1652 __ movq(RAX, Address(RBX, Isolate::current_tag_offset())); |
| 1653 __ ret(); | 1653 __ ret(); |
| 1654 } | 1654 } |
| 1655 | 1655 |
| 1656 #undef __ | 1656 #undef __ |
| 1657 | 1657 |
| 1658 } // namespace dart | 1658 } // namespace dart |
| 1659 | 1659 |
| 1660 #endif // defined TARGET_ARCH_X64 | 1660 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |