Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: runtime/vm/intrinsifier_mips.cc

Issue 468793004: VM: Improve performance of method recognizer and unify the it with the intrinsifier. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
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/object.h" 12 #include "vm/object.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 20
21 #define __ assembler-> 21 #define __ assembler->
22 22
23 23
24 void Intrinsifier::Array_getLength(Assembler* assembler) { 24 void Intrinsifier::ObjectArrayLength(Assembler* assembler) {
25 __ lw(V0, Address(SP, 0 * kWordSize)); 25 __ lw(V0, Address(SP, 0 * kWordSize));
26 __ Ret(); 26 __ Ret();
27 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); 27 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset()));
28 } 28 }
29 29
30 30
31 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { 31 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) {
32 Array_getLength(assembler); 32 ObjectArrayLength(assembler);
33 } 33 }
34 34
35 35
36 void Intrinsifier::Array_getIndexed(Assembler* assembler) { 36 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) {
37 Label fall_through; 37 Label fall_through;
38 38
39 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index 39 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index
40 40
41 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 41 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
42 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through 42 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through
43 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array 43 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array
44 44
45 // Range check. 45 // Range check.
46 __ lw(T2, FieldAddress(T1, Array::length_offset())); 46 __ lw(T2, FieldAddress(T1, Array::length_offset()));
47 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 47 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
48 48
49 ASSERT(kSmiTagShift == 1); 49 ASSERT(kSmiTagShift == 1);
50 // array element at T1 + T0*2 + Array::data_offset - 1 50 // array element at T1 + T0*2 + Array::data_offset - 1
51 __ sll(T2, T0, 1); 51 __ sll(T2, T0, 1);
52 __ addu(T2, T1, T2); 52 __ addu(T2, T1, T2);
53 __ Ret(); 53 __ Ret();
54 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); 54 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset()));
55 __ Bind(&fall_through); 55 __ Bind(&fall_through);
56 } 56 }
57 57
58 58
59 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { 59 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) {
60 Array_getIndexed(assembler); 60 ObjectArrayGetIndexed(assembler);
61 } 61 }
62 62
63 63
64 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 64 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
65 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 65 const Library& core_lib = Library::Handle(Library::CoreLibrary());
66 const Class& cls = Class::Handle( 66 const Class& cls = Class::Handle(
67 core_lib.LookupClassAllowPrivate(Symbols::_List())); 67 core_lib.LookupClassAllowPrivate(Symbols::_List()));
68 ASSERT(!cls.IsNull()); 68 ASSERT(!cls.IsNull());
69 ASSERT(cls.NumTypeArguments() == 1); 69 ASSERT(cls.NumTypeArguments() == 1);
70 const intptr_t field_offset = cls.type_arguments_field_offset(); 70 const intptr_t field_offset = cls.type_arguments_field_offset();
71 ASSERT(field_offset != Class::kNoTypeArguments); 71 ASSERT(field_offset != Class::kNoTypeArguments);
72 return field_offset; 72 return field_offset;
73 } 73 }
74 74
75 75
76 // Intrinsify only for Smi value and index. Non-smi values need a store buffer 76 // Intrinsify only for Smi value and index. Non-smi values need a store buffer
77 // update. Array length is always a Smi. 77 // update. Array length is always a Smi.
78 void Intrinsifier::Array_setIndexed(Assembler* assembler) { 78 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
79 Label fall_through; 79 Label fall_through;
80 80
81 if (FLAG_enable_type_checks) { 81 if (FLAG_enable_type_checks) {
82 const intptr_t type_args_field_offset = 82 const intptr_t type_args_field_offset =
83 ComputeObjectArrayTypeArgumentsOffset(); 83 ComputeObjectArrayTypeArgumentsOffset();
84 // Inline simple tests (Smi, null), fallthrough if not positive. 84 // Inline simple tests (Smi, null), fallthrough if not positive.
85 Label checked_ok; 85 Label checked_ok;
86 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 86 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
87 87
88 // Null value is valid for any type. 88 // Null value is valid for any type.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 FieldAddress(T1, Array::data_offset()), 128 FieldAddress(T1, Array::data_offset()),
129 T2); 129 T2);
130 // Caller is responsible for preserving the value if necessary. 130 // Caller is responsible for 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 (+1), data (+0). 137 // On stack: type argument (+1), data (+0).
138 void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { 138 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
139 // The newly allocated object is returned in V0. 139 // The newly allocated object is returned in V0.
140 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 140 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
141 const intptr_t kArrayOffset = 0 * kWordSize; 141 const intptr_t kArrayOffset = 0 * kWordSize;
142 Label fall_through; 142 Label fall_through;
143 143
144 // Try allocating in new space. 144 // Try allocating in new space.
145 const Class& cls = Class::Handle( 145 const Class& cls = Class::Handle(
146 Isolate::Current()->object_store()->growable_object_array_class()); 146 Isolate::Current()->object_store()->growable_object_array_class());
147 __ TryAllocate(cls, &fall_through, V0, T1); 147 __ TryAllocate(cls, &fall_through, V0, T1);
148 148
(...skipping 14 matching lines...) Expand all
163 T1); 163 T1);
164 // Set the length field in the growable array object to 0. 164 // Set the length field in the growable array object to 0.
165 __ Ret(); // Returns the newly allocated object in V0. 165 __ Ret(); // Returns the newly allocated object in V0.
166 __ delay_slot()->sw(ZR, 166 __ delay_slot()->sw(ZR,
167 FieldAddress(V0, GrowableObjectArray::length_offset())); 167 FieldAddress(V0, GrowableObjectArray::length_offset()));
168 168
169 __ Bind(&fall_through); 169 __ Bind(&fall_through);
170 } 170 }
171 171
172 172
173 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { 173 void Intrinsifier::GrowableArrayLength(Assembler* assembler) {
174 __ lw(V0, Address(SP, 0 * kWordSize)); 174 __ lw(V0, Address(SP, 0 * kWordSize));
175 __ Ret(); 175 __ Ret();
176 __ delay_slot()->lw(V0, 176 __ delay_slot()->lw(V0,
177 FieldAddress(V0, GrowableObjectArray::length_offset())); 177 FieldAddress(V0, GrowableObjectArray::length_offset()));
178 } 178 }
179 179
180 180
181 void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { 181 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) {
182 __ lw(V0, Address(SP, 0 * kWordSize)); 182 __ lw(V0, Address(SP, 0 * kWordSize));
183 __ lw(V0, FieldAddress(V0, GrowableObjectArray::data_offset())); 183 __ lw(V0, FieldAddress(V0, GrowableObjectArray::data_offset()));
184 __ Ret(); 184 __ Ret();
185 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); 185 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset()));
186 } 186 }
187 187
188 188
189 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { 189 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
190 Label fall_through; 190 Label fall_through;
191 191
192 __ lw(T0, Address(SP, 0 * kWordSize)); // Index 192 __ lw(T0, Address(SP, 0 * kWordSize)); // Index
193 193
194 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 194 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
195 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through 195 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through
196 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array 196 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array
197 197
198 // Range check. 198 // Range check.
199 __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset())); 199 __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset()));
200 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 200 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
201 201
202 __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset())); // data 202 __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset())); // data
203 203
204 ASSERT(kSmiTagShift == 1); 204 ASSERT(kSmiTagShift == 1);
205 // array element at T2 + T0 * 2 + Array::data_offset - 1 205 // array element at T2 + T0 * 2 + Array::data_offset - 1
206 __ sll(T3, T0, 1); 206 __ sll(T3, T0, 1);
207 __ addu(T2, T2, T3); 207 __ addu(T2, T2, T3);
208 __ Ret(); 208 __ Ret();
209 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); 209 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset()));
210 __ Bind(&fall_through); 210 __ Bind(&fall_through);
211 } 211 }
212 212
213 213
214 // Set value into growable object array at specified index. 214 // Set value into growable object array at specified index.
215 // On stack: growable array (+2), index (+1), value (+0). 215 // On stack: growable array (+2), index (+1), value (+0).
216 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { 216 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
217 if (FLAG_enable_type_checks) { 217 if (FLAG_enable_type_checks) {
218 return; 218 return;
219 } 219 }
220 Label fall_through; 220 Label fall_through;
221 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. 221 __ lw(T1, Address(SP, 1 * kWordSize)); // Index.
222 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 222 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
223 __ bne(CMPRES1, ZR, &fall_through); // Non-smi index. 223 __ bne(CMPRES1, ZR, &fall_through); // Non-smi index.
224 __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // GrowableArray. 224 __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // GrowableArray.
225 // Range check using _length field. 225 // Range check using _length field.
226 __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset())); 226 __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset()));
227 // Runtime throws exception. 227 // Runtime throws exception.
228 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); 228 __ BranchUnsignedGreaterEqual(T1, T2, &fall_through);
229 __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset())); // data. 229 __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset())); // data.
230 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 230 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
231 // Note that T1 is Smi, i.e, times 2. 231 // Note that T1 is Smi, i.e, times 2.
232 ASSERT(kSmiTagShift == 1); 232 ASSERT(kSmiTagShift == 1);
233 __ sll(T1, T1, 1); 233 __ sll(T1, T1, 1);
234 __ addu(T1, T0, T1); 234 __ addu(T1, T0, T1);
235 __ StoreIntoObject(T0, 235 __ StoreIntoObject(T0,
236 FieldAddress(T1, Array::data_offset()), 236 FieldAddress(T1, Array::data_offset()),
237 T2); 237 T2);
238 __ Ret(); 238 __ Ret();
239 __ Bind(&fall_through); 239 __ Bind(&fall_through);
240 } 240 }
241 241
242 242
243 // Set length of growable object array. The length cannot 243 // Set length of growable object array. The length cannot
244 // be greater than the length of the data container. 244 // be greater than the length of the data container.
245 // On stack: growable array (+1), length (+0). 245 // On stack: growable array (+1), length (+0).
246 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { 246 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
247 Label fall_through; 247 Label fall_through;
248 __ lw(T1, Address(SP, 0 * kWordSize)); // Length value. 248 __ lw(T1, Address(SP, 0 * kWordSize)); // Length value.
249 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 249 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
250 __ bne(CMPRES1, ZR, &fall_through); // Non-smi length. 250 __ bne(CMPRES1, ZR, &fall_through); // Non-smi length.
251 __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize)); // Growable array. 251 __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize)); // Growable array.
252 __ Ret(); 252 __ Ret();
253 __ delay_slot()->sw(T1, 253 __ delay_slot()->sw(T1,
254 FieldAddress(T0, GrowableObjectArray::length_offset())); 254 FieldAddress(T0, GrowableObjectArray::length_offset()));
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 (+1), data (+0). 260 // On stack: growable array (+1), data (+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 __ lw(T1, Address(SP, 0 * kWordSize)); // Data. 266 __ lw(T1, Address(SP, 0 * kWordSize)); // Data.
267 // Check that data is an ObjectArray. 267 // Check that data is an ObjectArray.
268 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 268 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
269 __ beq(CMPRES1, ZR, &fall_through); // Data is Smi. 269 __ beq(CMPRES1, ZR, &fall_through); // Data is Smi.
270 __ LoadClassId(CMPRES1, T1); 270 __ LoadClassId(CMPRES1, T1);
271 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); 271 __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through);
272 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array. 272 __ lw(T0, Address(SP, 1 * kWordSize)); // Growable array.
273 __ StoreIntoObject(T0, 273 __ StoreIntoObject(T0,
274 FieldAddress(T0, GrowableObjectArray::data_offset()), 274 FieldAddress(T0, GrowableObjectArray::data_offset()),
275 T1); 275 T1);
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 (+1), value (+0). 283 // On stack: growable array (+1), value (+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 Label fall_through; 287 Label fall_through;
288 __ lw(T0, Address(SP, 1 * kWordSize)); // Array. 288 __ lw(T0, Address(SP, 1 * kWordSize)); // Array.
289 __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset())); 289 __ lw(T1, FieldAddress(T0, GrowableObjectArray::length_offset()));
290 // T1: length. 290 // T1: length.
291 __ lw(T2, FieldAddress(T0, GrowableObjectArray::data_offset())); 291 __ lw(T2, FieldAddress(T0, GrowableObjectArray::data_offset()));
292 // T2: data. 292 // T2: data.
293 __ lw(T3, FieldAddress(T2, Array::length_offset())); 293 __ lw(T3, FieldAddress(T2, Array::length_offset()));
294 // Compare length with capacity. 294 // Compare length with capacity.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 __ sw(ZR, Address(T2, 0)); \ 393 __ sw(ZR, Address(T2, 0)); \
394 __ b(&init_loop); \ 394 __ b(&init_loop); \
395 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \ 395 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \
396 __ Bind(&done); \ 396 __ Bind(&done); \
397 \ 397 \
398 __ Ret(); \ 398 __ Ret(); \
399 __ Bind(&fall_through); \ 399 __ Bind(&fall_through); \
400 400
401 401
402 // Gets the length of a TypedData. 402 // Gets the length of a TypedData.
403 void Intrinsifier::TypedData_getLength(Assembler* assembler) { 403 void Intrinsifier::TypedDataLength(Assembler* assembler) {
404 __ lw(T0, Address(SP, 0 * kWordSize)); 404 __ lw(T0, Address(SP, 0 * kWordSize));
405 __ Ret(); 405 __ Ret();
406 __ delay_slot()->lw(V0, FieldAddress(T0, TypedData::length_offset())); 406 __ delay_slot()->lw(V0, FieldAddress(T0, TypedData::length_offset()));
407 } 407 }
408 408
409 409
410 void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) { 410 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) {
411 Label fall_through; 411 Label fall_through;
412 412
413 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. 413 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index.
414 414
415 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 415 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
416 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. 416 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through.
417 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. 417 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array.
418 418
419 // Range check. 419 // Range check.
420 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); 420 __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
421 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 421 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
422 422
423 __ SmiUntag(T0); 423 __ SmiUntag(T0);
424 __ addu(T1, T1, T0); 424 __ addu(T1, T1, T0);
425 __ lbu(V0, FieldAddress(T1, TypedData::data_offset())); 425 __ lbu(V0, FieldAddress(T1, TypedData::data_offset()));
426 __ Ret(); 426 __ Ret();
427 __ delay_slot()->SmiTag(V0); 427 __ delay_slot()->SmiTag(V0);
428 428
429 __ Bind(&fall_through); 429 __ Bind(&fall_through);
430 } 430 }
431 431
432 432
433 void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) { 433 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) {
434 Label fall_through; 434 Label fall_through;
435 435
436 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. 436 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index.
437 437
438 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 438 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
439 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. 439 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through.
440 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. 440 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array.
441 441
442 // Range check. 442 // Range check.
443 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); 443 __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
444 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); 444 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through);
445 445
446 __ lw(T1, FieldAddress(T1, ExternalTypedData::data_offset())); 446 __ lw(T1, FieldAddress(T1, ExternalTypedData::data_offset()));
447 __ SmiUntag(T0); 447 __ SmiUntag(T0);
448 __ addu(T1, T1, T0); 448 __ addu(T1, T1, T0);
449 __ lbu(V0, Address(T1, 0)); 449 __ lbu(V0, Address(T1, 0));
450 __ Ret(); 450 __ Ret();
451 __ delay_slot()->SmiTag(V0); 451 __ delay_slot()->SmiTag(V0);
452 452
453 __ Bind(&fall_through); 453 __ Bind(&fall_through);
454 } 454 }
455 455
456 456
457 void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) { 457 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) {
458 Label fall_through; 458 Label fall_through;
459 459
460 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. 460 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index.
461 461
462 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 462 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
463 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. 463 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through.
464 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. 464 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array.
465 465
466 // Range check. 466 // Range check.
467 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); 467 __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
(...skipping 14 matching lines...) Expand all
482 __ TryAllocate(double_class, 482 __ TryAllocate(double_class,
483 &fall_through, 483 &fall_through,
484 V0, // Result register. 484 V0, // Result register.
485 T1); 485 T1);
486 __ StoreDToOffset(D0, V0, Double::value_offset() - kHeapObjectTag); 486 __ StoreDToOffset(D0, V0, Double::value_offset() - kHeapObjectTag);
487 __ Ret(); 487 __ Ret();
488 __ Bind(&fall_through); 488 __ Bind(&fall_through);
489 } 489 }
490 490
491 491
492 void Intrinsifier::Float64Array_setIndexed(Assembler* assembler) { 492 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) {
493 Label fall_through; 493 Label fall_through;
494 494
495 __ lw(T0, Address(SP, + 1 * kWordSize)); // Index. 495 __ lw(T0, Address(SP, + 1 * kWordSize)); // Index.
496 496
497 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); 497 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
498 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. 498 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through.
499 __ delay_slot()->lw(T1, Address(SP, + 2 * kWordSize)); // Array. 499 __ delay_slot()->lw(T1, Address(SP, + 2 * kWordSize)); // Array.
500 500
501 // Range check. 501 // Range check.
502 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); 502 __ lw(T2, FieldAddress(T1, TypedData::length_offset()));
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 __ Bind(&is_zero); 1286 __ Bind(&is_zero);
1287 // Check for negative zero by looking at the sign bit. 1287 // Check for negative zero by looking at the sign bit.
1288 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0. 1288 __ mfc1(T0, F1); // Moves bits 32...63 of D0 to T0.
1289 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0. 1289 __ srl(T0, T0, 31); // Get the sign bit down to bit 0 of T0.
1290 __ andi(CMPRES1, T0, Immediate(1)); // Check if the bit is set. 1290 __ andi(CMPRES1, T0, Immediate(1)); // Check if the bit is set.
1291 __ bne(T0, ZR, &is_true); // Sign bit set. True. 1291 __ bne(T0, ZR, &is_true); // Sign bit set. True.
1292 __ b(&is_false); 1292 __ b(&is_false);
1293 } 1293 }
1294 1294
1295 1295
1296 void Intrinsifier::Double_toInt(Assembler* assembler) { 1296 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1297 __ lw(T0, Address(SP, 0 * kWordSize)); 1297 __ lw(T0, Address(SP, 0 * kWordSize));
1298 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); 1298 __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
1299 1299
1300 __ cvtwd(F2, D0); 1300 __ cvtwd(F2, D0);
1301 __ mfc1(V0, F2); 1301 __ mfc1(V0, F2);
1302 1302
1303 // Overflow is signaled with minint. 1303 // Overflow is signaled with minint.
1304 Label fall_through; 1304 Label fall_through;
1305 // Check for overflow and that it fits into Smi. 1305 // Check for overflow and that it fits into Smi.
1306 __ LoadImmediate(TMP, 0xC0000000); 1306 __ LoadImmediate(TMP, 0xC0000000);
1307 __ subu(CMPRES1, V0, TMP); 1307 __ subu(CMPRES1, V0, TMP);
1308 __ bltz(CMPRES1, &fall_through); 1308 __ bltz(CMPRES1, &fall_through);
1309 __ Ret(); 1309 __ Ret();
1310 __ delay_slot()->SmiTag(V0); 1310 __ delay_slot()->SmiTag(V0);
1311 __ Bind(&fall_through); 1311 __ Bind(&fall_through);
1312 } 1312 }
1313 1313
1314 1314
1315 void Intrinsifier::Math_sqrt(Assembler* assembler) { 1315 void Intrinsifier::MathSqrt(Assembler* assembler) {
1316 Label fall_through, is_smi, double_op; 1316 Label fall_through, is_smi, double_op;
1317 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1317 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1318 // Argument is double and is in T0. 1318 // Argument is double and is in T0.
1319 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag); 1319 __ LoadDFromOffset(D1, T0, Double::value_offset() - kHeapObjectTag);
1320 __ Bind(&double_op); 1320 __ Bind(&double_op);
1321 __ sqrtd(D0, D1); 1321 __ sqrtd(D0, D1);
1322 const Class& double_class = Class::Handle( 1322 const Class& double_class = Class::Handle(
1323 Isolate::Current()->object_store()->double_class()); 1323 Isolate::Current()->object_store()->double_class());
1324 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register. 1324 __ TryAllocate(double_class, &fall_through, V0, T1); // Result register.
1325 __ swc1(F0, FieldAddress(V0, Double::value_offset())); 1325 __ swc1(F0, FieldAddress(V0, Double::value_offset()));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 // 64-bit multiply and accumulate into T6:T3. 1375 // 64-bit multiply and accumulate into T6:T3.
1376 __ maddu(T0, T2); // HI:LO <- HI:LO + T0 * T2. 1376 __ maddu(T0, T2); // HI:LO <- HI:LO + T0 * T2.
1377 __ mflo(T3); 1377 __ mflo(T3);
1378 __ mfhi(T6); 1378 __ mfhi(T6);
1379 __ sw(T3, addr_0); 1379 __ sw(T3, addr_0);
1380 __ sw(T6, addr_1); 1380 __ sw(T6, addr_1);
1381 __ Ret(); 1381 __ Ret();
1382 } 1382 }
1383 1383
1384 1384
1385 void Intrinsifier::Object_equal(Assembler* assembler) { 1385 void Intrinsifier::ObjectEquals(Assembler* assembler) {
1386 Label is_true; 1386 Label is_true;
1387 1387
1388 __ lw(T0, Address(SP, 0 * kWordSize)); 1388 __ lw(T0, Address(SP, 0 * kWordSize));
1389 __ lw(T1, Address(SP, 1 * kWordSize)); 1389 __ lw(T1, Address(SP, 1 * kWordSize));
1390 __ beq(T0, T1, &is_true); 1390 __ beq(T0, T1, &is_true);
1391 __ LoadObject(V0, Bool::False()); 1391 __ LoadObject(V0, Bool::False());
1392 __ Ret(); 1392 __ Ret();
1393 __ Bind(&is_true); 1393 __ Bind(&is_true);
1394 __ LoadObject(V0, Bool::True()); 1394 __ LoadObject(V0, Bool::True());
1395 __ Ret(); 1395 __ Ret();
1396 } 1396 }
1397 1397
1398 1398
1399 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1399 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1400 Label fall_through; 1400 Label fall_through;
1401 __ lw(T0, Address(SP, 0 * kWordSize)); 1401 __ lw(T0, Address(SP, 0 * kWordSize));
1402 __ lw(V0, FieldAddress(T0, String::hash_offset())); 1402 __ lw(V0, FieldAddress(T0, String::hash_offset()));
1403 __ beq(V0, ZR, &fall_through); 1403 __ beq(V0, ZR, &fall_through);
1404 __ Ret(); 1404 __ Ret();
1405 __ Bind(&fall_through); // Hash not yet computed. 1405 __ Bind(&fall_through); // Hash not yet computed.
1406 } 1406 }
1407 1407
1408 1408
1409 void Intrinsifier::String_getLength(Assembler* assembler) { 1409 void Intrinsifier::StringBaseLength(Assembler* assembler) {
1410 __ lw(T0, Address(SP, 0 * kWordSize)); 1410 __ lw(T0, Address(SP, 0 * kWordSize));
1411 __ Ret(); 1411 __ Ret();
1412 __ delay_slot()->lw(V0, FieldAddress(T0, String::length_offset())); 1412 __ delay_slot()->lw(V0, FieldAddress(T0, String::length_offset()));
1413 } 1413 }
1414 1414
1415 1415
1416 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1416 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1417 Label fall_through, try_two_byte_string; 1417 Label fall_through, try_two_byte_string;
1418 1418
1419 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. 1419 __ lw(T1, Address(SP, 0 * kWordSize)); // Index.
1420 __ lw(T0, Address(SP, 1 * kWordSize)); // String. 1420 __ lw(T0, Address(SP, 1 * kWordSize)); // String.
1421 1421
1422 // Checks. 1422 // Checks.
1423 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); 1423 __ andi(CMPRES1, T1, Immediate(kSmiTagMask));
1424 __ bne(T1, ZR, &fall_through); // Index is not a Smi. 1424 __ bne(T1, ZR, &fall_through); // Index is not a Smi.
1425 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. 1425 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check.
1426 // Runtime throws exception. 1426 // Runtime throws exception.
(...skipping 13 matching lines...) Expand all
1440 ASSERT(kSmiTagShift == 1); 1440 ASSERT(kSmiTagShift == 1);
1441 __ addu(T2, T0, T1); 1441 __ addu(T2, T0, T1);
1442 __ lhu(V0, FieldAddress(T2, OneByteString::data_offset())); 1442 __ lhu(V0, FieldAddress(T2, OneByteString::data_offset()));
1443 __ Ret(); 1443 __ Ret();
1444 __ delay_slot()->SmiTag(V0); 1444 __ delay_slot()->SmiTag(V0);
1445 1445
1446 __ Bind(&fall_through); 1446 __ Bind(&fall_through);
1447 } 1447 }
1448 1448
1449 1449
1450 void Intrinsifier::String_getIsEmpty(Assembler* assembler) { 1450 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) {
1451 Label is_true; 1451 Label is_true;
1452 1452
1453 __ lw(T0, Address(SP, 0 * kWordSize)); 1453 __ lw(T0, Address(SP, 0 * kWordSize));
1454 __ lw(T0, FieldAddress(T0, String::length_offset())); 1454 __ lw(T0, FieldAddress(T0, String::length_offset()));
1455 1455
1456 __ beq(T0, ZR, &is_true); 1456 __ beq(T0, ZR, &is_true);
1457 __ LoadObject(V0, Bool::False()); 1457 __ LoadObject(V0, Bool::False());
1458 __ Ret(); 1458 __ Ret();
1459 __ Bind(&is_true); 1459 __ Bind(&is_true);
1460 __ LoadObject(V0, Bool::True()); 1460 __ LoadObject(V0, Bool::True());
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1655 __ sb(T1, FieldAddress(T7, OneByteString::data_offset())); 1655 __ sb(T1, FieldAddress(T7, OneByteString::data_offset()));
1656 __ bgtz(T2, &loop); 1656 __ bgtz(T2, &loop);
1657 __ delay_slot()->addiu(T7, T7, Immediate(1)); 1657 __ delay_slot()->addiu(T7, T7, Immediate(1));
1658 1658
1659 __ Bind(&done); 1659 __ Bind(&done);
1660 __ Ret(); 1660 __ Ret();
1661 __ Bind(&fall_through); 1661 __ Bind(&fall_through);
1662 } 1662 }
1663 1663
1664 1664
1665 void Intrinsifier::OneByteString_setAt(Assembler* assembler) { 1665 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) {
1666 __ lw(T2, Address(SP, 0 * kWordSize)); // Value. 1666 __ lw(T2, Address(SP, 0 * kWordSize)); // Value.
1667 __ lw(T1, Address(SP, 1 * kWordSize)); // Index. 1667 __ lw(T1, Address(SP, 1 * kWordSize)); // Index.
1668 __ lw(T0, Address(SP, 2 * kWordSize)); // OneByteString. 1668 __ lw(T0, Address(SP, 2 * kWordSize)); // OneByteString.
1669 __ SmiUntag(T1); 1669 __ SmiUntag(T1);
1670 __ SmiUntag(T2); 1670 __ SmiUntag(T2);
1671 __ addu(T3, T0, T1); 1671 __ addu(T3, T0, T1);
1672 __ Ret(); 1672 __ Ret();
1673 __ delay_slot()->sb(T2, FieldAddress(T3, OneByteString::data_offset())); 1673 __ delay_slot()->sb(T2, FieldAddress(T3, OneByteString::data_offset()));
1674 } 1674 }
1675 1675
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 Isolate* isolate = Isolate::Current(); 1786 Isolate* isolate = Isolate::Current();
1787 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); 1787 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate));
1788 // Set return value. 1788 // Set return value.
1789 __ Ret(); 1789 __ Ret();
1790 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); 1790 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset()));
1791 } 1791 }
1792 1792
1793 } // namespace dart 1793 } // namespace dart
1794 1794
1795 #endif // defined TARGET_ARCH_MIPS 1795 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_ia32.cc ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698