| 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_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" | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|    24   const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |    24   const intptr_t kTypeArgumentsOffset = 1 * kWordSize; | 
|    25   const intptr_t kArrayLengthOffset = 0 * kWordSize; |    25   const intptr_t kArrayLengthOffset = 0 * kWordSize; | 
|    26   Label fall_through; |    26   Label fall_through; | 
|    27  |    27  | 
|    28   // Compute the size to be allocated, it is based on the array length |    28   // Compute the size to be allocated, it is based on the array length | 
|    29   // and is computed as: |    29   // and is computed as: | 
|    30   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |    30   // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 
|    31   __ lw(T3, Address(SP, kArrayLengthOffset));  // Array length. |    31   __ lw(T3, Address(SP, kArrayLengthOffset));  // Array length. | 
|    32  |    32  | 
|    33   // Check that length is a positive Smi. |    33   // Check that length is a positive Smi. | 
|    34   __ andi(CMPRES, T3, Immediate(kSmiTagMask)); |    34   __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | 
|    35   __ bne(CMPRES, ZR, &fall_through); |    35   __ bne(CMPRES1, ZR, &fall_through); | 
|    36   __ bltz(T3, &fall_through); |    36   __ bltz(T3, &fall_through); | 
|    37  |    37  | 
|    38   // Check for maximum allowed length. |    38   // Check for maximum allowed length. | 
|    39   const intptr_t max_len = |    39   const intptr_t max_len = | 
|    40       reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); |    40       reinterpret_cast<int32_t>(Smi::New(Array::kMaxElements)); | 
|    41   __ BranchUnsignedGreater(T3, max_len, &fall_through); |    41   __ BranchUnsignedGreater(T3, max_len, &fall_through); | 
|    42  |    42  | 
|    43   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |    43   const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 
|    44   __ LoadImmediate(T2, fixed_size); |    44   __ LoadImmediate(T2, fixed_size); | 
|    45   __ sll(T3, T3, 1);  // T3 is  a Smi. |    45   __ sll(T3, T3, 1);  // T3 is  a Smi. | 
|    46   __ addu(T2, T2, T3); |    46   __ addu(T2, T2, T3); | 
|    47   ASSERT(kSmiTagShift == 1); |    47   ASSERT(kSmiTagShift == 1); | 
|    48   __ LoadImmediate(T3, ~(kObjectAlignment - 1)); |    48   __ LoadImmediate(T3, ~(kObjectAlignment - 1)); | 
|    49   __ and_(T2, T2, T3); |    49   __ and_(T2, T2, T3); | 
|    50  |    50  | 
|    51   // T2: Allocation size. |    51   // T2: Allocation size. | 
|    52  |    52  | 
|    53   Isolate* isolate = Isolate::Current(); |    53   Isolate* isolate = Isolate::Current(); | 
|    54   Heap* heap = isolate->heap(); |    54   Heap* heap = isolate->heap(); | 
|    55  |    55  | 
|    56   __ LoadImmediate(T3, heap->TopAddress()); |    56   __ LoadImmediate(T3, heap->TopAddress()); | 
|    57   __ lw(T0, Address(T3, 0));  // Potential new object start. |    57   __ lw(T0, Address(T3, 0));  // Potential new object start. | 
|    58  |    58  | 
|    59   __ AdduDetectOverflow(T1, T0, T2, CMPRES);  // Potential next object start. |    59   __ AdduDetectOverflow(T1, T0, T2, CMPRES1);  // Potential next object start. | 
|    60   __ bltz(CMPRES, &fall_through);  // CMPRES < 0 on overflow. |    60   __ bltz(CMPRES1, &fall_through);  // CMPRES1 < 0 on overflow. | 
|    61  |    61  | 
|    62   // Check if the allocation fits into the remaining space. |    62   // Check if the allocation fits into the remaining space. | 
|    63   // T0: potential new object start. |    63   // T0: potential new object start. | 
|    64   // T1: potential next object start. |    64   // T1: potential next object start. | 
|    65   // T2: allocation size. |    65   // T2: allocation size. | 
|    66   __ LoadImmediate(T4, heap->TopAddress()); |    66   __ LoadImmediate(T4, heap->TopAddress()); | 
|    67   __ lw(T4, Address(T4, 0)); |    67   __ lw(T4, Address(T4, 0)); | 
|    68   __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); |    68   __ BranchUnsignedGreaterEqual(T1, T4, &fall_through); | 
|    69  |    69  | 
|    70   // Successfully allocated the object(s), now update top to point to |    70   // Successfully allocated the object(s), now update top to point to | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|    83  |    83  | 
|    84     __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); |    84     __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); | 
|    85     __ b(&done); |    85     __ b(&done); | 
|    86     __ delay_slot()->sll(T2, T2, shift); |    86     __ delay_slot()->sll(T2, T2, shift); | 
|    87     __ Bind(&overflow); |    87     __ Bind(&overflow); | 
|    88     __ mov(T2, ZR); |    88     __ mov(T2, ZR); | 
|    89     __ Bind(&done); |    89     __ Bind(&done); | 
|    90  |    90  | 
|    91     // Get the class index and insert it into the tags. |    91     // Get the class index and insert it into the tags. | 
|    92     // T2: size and bit tags. |    92     // T2: size and bit tags. | 
|    93     __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(cls.id())); |    93     __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); | 
|    94     __ or_(T2, T2, TMP1); |    94     __ or_(T2, T2, TMP); | 
|    95     __ sw(T2, FieldAddress(T0, Array::tags_offset()));  // Store tags. |    95     __ sw(T2, FieldAddress(T0, Array::tags_offset()));  // Store tags. | 
|    96   } |    96   } | 
|    97  |    97  | 
|    98   // T0: new object start as a tagged pointer. |    98   // T0: new object start as a tagged pointer. | 
|    99   // T1: new object end address. |    99   // T1: new object end address. | 
|   100   // Store the type argument field. |   100   // Store the type argument field. | 
|   101   __ lw(T2, Address(SP, kTypeArgumentsOffset));  // Type argument. |   101   __ lw(T2, Address(SP, kTypeArgumentsOffset));  // Type argument. | 
|   102   __ StoreIntoObjectNoBarrier(T0, |   102   __ StoreIntoObjectNoBarrier(T0, | 
|   103                               FieldAddress(T0, Array::type_arguments_offset()), |   103                               FieldAddress(T0, Array::type_arguments_offset()), | 
|   104                               T2); |   104                               T2); | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   143 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { |   143 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { | 
|   144   return Array_getLength(assembler); |   144   return Array_getLength(assembler); | 
|   145 } |   145 } | 
|   146  |   146  | 
|   147  |   147  | 
|   148 void Intrinsifier::Array_getIndexed(Assembler* assembler) { |   148 void Intrinsifier::Array_getIndexed(Assembler* assembler) { | 
|   149   Label fall_through; |   149   Label fall_through; | 
|   150  |   150  | 
|   151   __ lw(T0, Address(SP, + 0 * kWordSize));  // Index |   151   __ lw(T0, Address(SP, + 0 * kWordSize));  // Index | 
|   152  |   152  | 
|   153   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |   153   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|   154   __ bne(CMPRES, ZR, &fall_through);  // Index is not an smi, fall through |   154   __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through | 
|   155   __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize));  // Array |   155   __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize));  // Array | 
|   156  |   156  | 
|   157   // range check |   157   // range check | 
|   158   __ lw(T2, FieldAddress(T1, Array::length_offset())); |   158   __ lw(T2, FieldAddress(T1, Array::length_offset())); | 
|   159   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); |   159   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | 
|   160  |   160  | 
|   161   ASSERT(kSmiTagShift == 1); |   161   ASSERT(kSmiTagShift == 1); | 
|   162   // array element at T1 + T0*2 + Array::data_offset - 1 |   162   // array element at T1 + T0*2 + Array::data_offset - 1 | 
|   163   __ sll(T2, T0, 1); |   163   __ sll(T2, T0, 1); | 
|   164   __ addu(T2, T1, T2); |   164   __ addu(T2, T1, T2); | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   210     // Check if it's dynamic. |   210     // Check if it's dynamic. | 
|   211     // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. |   211     // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. | 
|   212     __ LoadClassId(CMPRES1, T1); |   212     __ LoadClassId(CMPRES1, T1); | 
|   213     __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through); |   213     __ BranchNotEqual(CMPRES1, kTypeArgumentsCid, &fall_through); | 
|   214  |   214  | 
|   215     // Get type at index 0. |   215     // Get type at index 0. | 
|   216     __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0))); |   216     __ lw(T0, FieldAddress(T1, TypeArguments::type_at_offset(0))); | 
|   217     __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok); |   217     __ BranchEqual(T0, Type::ZoneHandle(Type::DynamicType()), &checked_ok); | 
|   218  |   218  | 
|   219     // Check for int and num. |   219     // Check for int and num. | 
|   220     __ andi(CMPRES, T2, Immediate(kSmiTagMask)); |   220     __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); | 
|   221     __ bne(CMPRES, ZR, &fall_through);  // Non-smi value. |   221     __ bne(CMPRES1, ZR, &fall_through);  // Non-smi value. | 
|   222  |   222  | 
|   223     __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok); |   223     __ BranchEqual(T0, Type::ZoneHandle(Type::IntType()), &checked_ok); | 
|   224     __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through); |   224     __ BranchNotEqual(T0, Type::ZoneHandle(Type::Number()), &fall_through); | 
|   225     __ Bind(&checked_ok); |   225     __ Bind(&checked_ok); | 
|   226   } |   226   } | 
|   227   __ lw(T1, Address(SP, 1 * kWordSize));  // Index. |   227   __ lw(T1, Address(SP, 1 * kWordSize));  // Index. | 
|   228   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |   228   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|   229   // Index not Smi. |   229   // Index not Smi. | 
|   230   __ bne(CMPRES, ZR, &fall_through); |   230   __ bne(CMPRES1, ZR, &fall_through); | 
|   231  |   231  | 
|   232   __ lw(T0, Address(SP, 2 * kWordSize));  // Array. |   232   __ lw(T0, Address(SP, 2 * kWordSize));  // Array. | 
|   233   // Range check. |   233   // Range check. | 
|   234   __ lw(T3, FieldAddress(T0, Array::length_offset()));  // Array length. |   234   __ lw(T3, FieldAddress(T0, Array::length_offset()));  // Array length. | 
|   235   // Runtime throws exception. |   235   // Runtime throws exception. | 
|   236   __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); |   236   __ BranchUnsignedGreaterEqual(T1, T3, &fall_through); | 
|   237  |   237  | 
|   238   // Note that T1 is Smi, i.e, times 2. |   238   // Note that T1 is Smi, i.e, times 2. | 
|   239   ASSERT(kSmiTagShift == 1); |   239   ASSERT(kSmiTagShift == 1); | 
|   240   __ lw(T2, Address(SP, 0 * kWordSize));  // Value. |   240   __ lw(T2, Address(SP, 0 * kWordSize));  // Value. | 
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   330   __ Ret(); |   330   __ Ret(); | 
|   331   __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); |   331   __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); | 
|   332 } |   332 } | 
|   333  |   333  | 
|   334  |   334  | 
|   335 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { |   335 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { | 
|   336   Label fall_through; |   336   Label fall_through; | 
|   337  |   337  | 
|   338   __ lw(T0, Address(SP, 0 * kWordSize));  // Index |   338   __ lw(T0, Address(SP, 0 * kWordSize));  // Index | 
|   339  |   339  | 
|   340   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |   340   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|   341   __ bne(CMPRES, ZR, &fall_through);  // Index is not an smi, fall through |   341   __ bne(CMPRES1, ZR, &fall_through);  // Index is not an smi, fall through | 
|   342   __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize));  // Array |   342   __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize));  // Array | 
|   343  |   343  | 
|   344   // range check |   344   // range check | 
|   345   __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset())); |   345   __ lw(T2, FieldAddress(T1, GrowableObjectArray::length_offset())); | 
|   346   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); |   346   __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | 
|   347  |   347  | 
|   348   __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset()));  // data |   348   __ lw(T2, FieldAddress(T1, GrowableObjectArray::data_offset()));  // data | 
|   349  |   349  | 
|   350   ASSERT(kSmiTagShift == 1); |   350   ASSERT(kSmiTagShift == 1); | 
|   351   // array element at T2 + T0 * 2 + Array::data_offset - 1 |   351   // array element at T2 + T0 * 2 + Array::data_offset - 1 | 
|   352   __ sll(T3, T0, 1); |   352   __ sll(T3, T0, 1); | 
|   353   __ addu(T2, T2, T3); |   353   __ addu(T2, T2, T3); | 
|   354   __ Ret(); |   354   __ Ret(); | 
|   355   __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); |   355   __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); | 
|   356   __ Bind(&fall_through); |   356   __ Bind(&fall_through); | 
|   357 } |   357 } | 
|   358  |   358  | 
|   359  |   359  | 
|   360 // Set value into growable object array at specified index. |   360 // Set value into growable object array at specified index. | 
|   361 // On stack: growable array (+2), index (+1), value (+0). |   361 // On stack: growable array (+2), index (+1), value (+0). | 
|   362 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { |   362 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { | 
|   363   if (FLAG_enable_type_checks) { |   363   if (FLAG_enable_type_checks) { | 
|   364     return; |   364     return; | 
|   365   } |   365   } | 
|   366   Label fall_through; |   366   Label fall_through; | 
|   367   __ lw(T1, Address(SP, 1 * kWordSize));  // Index. |   367   __ lw(T1, Address(SP, 1 * kWordSize));  // Index. | 
|   368   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |   368   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|   369   __ bne(CMPRES, ZR, &fall_through);  // Non-smi index. |   369   __ bne(CMPRES1, ZR, &fall_through);  // Non-smi index. | 
|   370   __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize));  // GrowableArray. |   370   __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize));  // GrowableArray. | 
|   371   // Range check using _length field. |   371   // Range check using _length field. | 
|   372   __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset())); |   372   __ lw(T2, FieldAddress(T0, GrowableObjectArray::length_offset())); | 
|   373   // Runtime throws exception. |   373   // Runtime throws exception. | 
|   374   __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); |   374   __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); | 
|   375   __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset()));  // data. |   375   __ lw(T0, FieldAddress(T0, GrowableObjectArray::data_offset()));  // data. | 
|   376   __ lw(T2, Address(SP, 0 * kWordSize));  // Value. |   376   __ lw(T2, Address(SP, 0 * kWordSize));  // Value. | 
|   377   // Note that T1 is Smi, i.e, times 2. |   377   // Note that T1 is Smi, i.e, times 2. | 
|   378   ASSERT(kSmiTagShift == 1); |   378   ASSERT(kSmiTagShift == 1); | 
|   379   __ sll(T1, T1, 1); |   379   __ sll(T1, T1, 1); | 
|   380   __ addu(T1, T0, T1); |   380   __ addu(T1, T0, T1); | 
|   381   __ StoreIntoObject(T0, |   381   __ StoreIntoObject(T0, | 
|   382                      FieldAddress(T1, Array::data_offset()), |   382                      FieldAddress(T1, Array::data_offset()), | 
|   383                      T2); |   383                      T2); | 
|   384   __ Ret(); |   384   __ Ret(); | 
|   385   __ Bind(&fall_through); |   385   __ Bind(&fall_through); | 
|   386 } |   386 } | 
|   387  |   387  | 
|   388  |   388  | 
|   389 // Set length of growable object array. The length cannot |   389 // Set length of growable object array. The length cannot | 
|   390 // be greater than the length of the data container. |   390 // be greater than the length of the data container. | 
|   391 // On stack: growable array (+1), length (+0). |   391 // On stack: growable array (+1), length (+0). | 
|   392 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { |   392 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { | 
|   393   Label fall_through; |   393   Label fall_through; | 
|   394   __ lw(T1, Address(SP, 0 * kWordSize));  // Length value. |   394   __ lw(T1, Address(SP, 0 * kWordSize));  // Length value. | 
|   395   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |   395   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|   396   __ bne(CMPRES, ZR, &fall_through);  // Non-smi length. |   396   __ bne(CMPRES1, ZR, &fall_through);  // Non-smi length. | 
|   397   __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize));  // Growable array. |   397   __ delay_slot()->lw(T0, Address(SP, 1 * kWordSize));  // Growable array. | 
|   398   __ Ret(); |   398   __ Ret(); | 
|   399   __ delay_slot()->sw(T1, |   399   __ delay_slot()->sw(T1, | 
|   400       FieldAddress(T0, GrowableObjectArray::length_offset())); |   400       FieldAddress(T0, GrowableObjectArray::length_offset())); | 
|   401   __ Bind(&fall_through); |   401   __ Bind(&fall_through); | 
|   402 } |   402 } | 
|   403  |   403  | 
|   404  |   404  | 
|   405 // Set data of growable object array. |   405 // Set data of growable object array. | 
|   406 // On stack: growable array (+1), data (+0). |   406 // On stack: growable array (+1), data (+0). | 
|   407 void Intrinsifier::GrowableList_setData(Assembler* assembler) { |   407 void Intrinsifier::GrowableList_setData(Assembler* assembler) { | 
|   408   if (FLAG_enable_type_checks) { |   408   if (FLAG_enable_type_checks) { | 
|   409     return; |   409     return; | 
|   410   } |   410   } | 
|   411   Label fall_through; |   411   Label fall_through; | 
|   412   __ lw(T1, Address(SP, 0 * kWordSize));  // Data. |   412   __ lw(T1, Address(SP, 0 * kWordSize));  // Data. | 
|   413   // Check that data is an ObjectArray. |   413   // Check that data is an ObjectArray. | 
|   414   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |   414   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|   415   __ beq(CMPRES, ZR, &fall_through);  // Data is Smi. |   415   __ beq(CMPRES1, ZR, &fall_through);  // Data is Smi. | 
|   416   __ LoadClassId(CMPRES1, T1); |   416   __ LoadClassId(CMPRES1, T1); | 
|   417   __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); |   417   __ BranchNotEqual(CMPRES1, kArrayCid, &fall_through); | 
|   418   __ lw(T0, Address(SP, 1 * kWordSize));  // Growable array. |   418   __ lw(T0, Address(SP, 1 * kWordSize));  // Growable array. | 
|   419   __ StoreIntoObject(T0, |   419   __ StoreIntoObject(T0, | 
|   420                      FieldAddress(T0, GrowableObjectArray::data_offset()), |   420                      FieldAddress(T0, GrowableObjectArray::data_offset()), | 
|   421                      T1); |   421                      T1); | 
|   422   __ Ret(); |   422   __ Ret(); | 
|   423   __ Bind(&fall_through); |   423   __ Bind(&fall_through); | 
|   424 } |   424 } | 
|   425  |   425  | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   457   __ Bind(&fall_through); |   457   __ Bind(&fall_through); | 
|   458 } |   458 } | 
|   459  |   459  | 
|   460  |   460  | 
|   461 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \ |   461 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \ | 
|   462   Label fall_through;                                                          \ |   462   Label fall_through;                                                          \ | 
|   463   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \ |   463   const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \ | 
|   464   __ lw(T2, Address(SP, kArrayLengthStackOffset));  /* Array length. */        \ |   464   __ lw(T2, Address(SP, kArrayLengthStackOffset));  /* Array length. */        \ | 
|   465   /* Check that length is a positive Smi. */                                   \ |   465   /* Check that length is a positive Smi. */                                   \ | 
|   466   /* T2: requested array length argument. */                                   \ |   466   /* T2: requested array length argument. */                                   \ | 
|   467   __ andi(CMPRES, T2, Immediate(kSmiTagMask));                                 \ |   467   __ andi(CMPRES1, T2, Immediate(kSmiTagMask));                                \ | 
|   468   __ bne(CMPRES, ZR, &fall_through);                                           \ |   468   __ bne(CMPRES1, ZR, &fall_through);                                          \ | 
|   469   __ BranchSignedLess(T2, 0, &fall_through);                                   \ |   469   __ BranchSignedLess(T2, 0, &fall_through);                                   \ | 
|   470   __ SmiUntag(T2);                                                             \ |   470   __ SmiUntag(T2);                                                             \ | 
|   471   /* Check for maximum allowed length. */                                      \ |   471   /* Check for maximum allowed length. */                                      \ | 
|   472   /* T2: untagged array length. */                                             \ |   472   /* T2: untagged array length. */                                             \ | 
|   473   __ BranchSignedGreater(T2, max_len, &fall_through);                          \ |   473   __ BranchSignedGreater(T2, max_len, &fall_through);                          \ | 
|   474   __ sll(T2, T2, scale_shift);                                                 \ |   474   __ sll(T2, T2, scale_shift);                                                 \ | 
|   475   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \ |   475   const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1;   \ | 
|   476   __ AddImmediate(T2, fixed_size);                                             \ |   476   __ AddImmediate(T2, fixed_size);                                             \ | 
|   477   __ LoadImmediate(TMP, -kObjectAlignment);                                    \ |   477   __ LoadImmediate(TMP, -kObjectAlignment);                                    \ | 
|   478   __ and_(T2, T2, TMP);                                                        \ |   478   __ and_(T2, T2, TMP);                                                        \ | 
|   479   Heap* heap = Isolate::Current()->heap();                                     \ |   479   Heap* heap = Isolate::Current()->heap();                                     \ | 
|   480                                                                                \ |   480                                                                                \ | 
|   481   __ LoadImmediate(V0, heap->TopAddress());                                    \ |   481   __ LoadImmediate(V0, heap->TopAddress());                                    \ | 
|   482   __ lw(V0, Address(V0, 0));                                                   \ |   482   __ lw(V0, Address(V0, 0));                                                   \ | 
|   483                                                                                \ |   483                                                                                \ | 
|   484   /* T2: allocation size. */                                                   \ |   484   /* T2: allocation size. */                                                   \ | 
|   485   __ AdduDetectOverflow(T1, V0, T2, CMPRES);                                   \ |   485   __ AdduDetectOverflow(T1, V0, T2, CMPRES1);                                  \ | 
|   486   __ bltz(CMPRES, &fall_through);                                              \ |   486   __ bltz(CMPRES1, &fall_through);                                             \ | 
|   487                                                                                \ |   487                                                                                \ | 
|   488   /* Check if the allocation fits into the remaining space. */                 \ |   488   /* Check if the allocation fits into the remaining space. */                 \ | 
|   489   /* V0: potential new object start. */                                        \ |   489   /* V0: potential new object start. */                                        \ | 
|   490   /* T1: potential next object start. */                                       \ |   490   /* T1: potential next object start. */                                       \ | 
|   491   /* T2: allocation size. */                                                   \ |   491   /* T2: allocation size. */                                                   \ | 
|   492   __ LoadImmediate(T3, heap->EndAddress());                                    \ |   492   __ LoadImmediate(T3, heap->EndAddress());                                    \ | 
|   493   __ lw(T3, Address(T3, 0));                                                   \ |   493   __ lw(T3, Address(T3, 0));                                                   \ | 
|   494   __ BranchUnsignedGreaterEqual(T1, T3, &fall_through);                        \ |   494   __ BranchUnsignedGreaterEqual(T1, T3, &fall_through);                        \ | 
|   495                                                                                \ |   495                                                                                \ | 
|   496   /* Successfully allocated the object(s), now update top to point to */       \ |   496   /* Successfully allocated the object(s), now update top to point to */       \ | 
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   581 } |   581 } | 
|   582 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) |   582 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) | 
|   583 #undef TYPED_DATA_ALLOCATOR |   583 #undef TYPED_DATA_ALLOCATOR | 
|   584  |   584  | 
|   585  |   585  | 
|   586 // Loads args from stack into T0 and T1 |   586 // Loads args from stack into T0 and T1 | 
|   587 // Tests if they are smis, jumps to label not_smi if not. |   587 // Tests if they are smis, jumps to label not_smi if not. | 
|   588 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { |   588 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { | 
|   589   __ lw(T0, Address(SP, 0 * kWordSize)); |   589   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|   590   __ lw(T1, Address(SP, 1 * kWordSize)); |   590   __ lw(T1, Address(SP, 1 * kWordSize)); | 
|   591   __ or_(CMPRES, T0, T1); |   591   __ or_(CMPRES1, T0, T1); | 
|   592   __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); |   592   __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); | 
|   593   __ bne(CMPRES, ZR, not_smi); |   593   __ bne(CMPRES1, ZR, not_smi); | 
|   594   return; |   594   return; | 
|   595 } |   595 } | 
|   596  |   596  | 
|   597  |   597  | 
|   598 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { |   598 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { | 
|   599   Label fall_through; |   599   Label fall_through; | 
|   600  |   600  | 
|   601   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two Smis. |   601   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two Smis. | 
|   602   __ AdduDetectOverflow(V0, T0, T1, CMPRES);  // Add. |   602   __ AdduDetectOverflow(V0, T0, T1, CMPRES1);  // Add. | 
|   603   __ bltz(CMPRES, &fall_through);  // Fall through on overflow. |   603   __ bltz(CMPRES1, &fall_through);  // Fall through on overflow. | 
|   604   __ Ret();  // Nothing in branch delay slot. |   604   __ Ret();  // Nothing in branch delay slot. | 
|   605   __ Bind(&fall_through); |   605   __ Bind(&fall_through); | 
|   606 } |   606 } | 
|   607  |   607  | 
|   608  |   608  | 
|   609 void Intrinsifier::Integer_add(Assembler* assembler) { |   609 void Intrinsifier::Integer_add(Assembler* assembler) { | 
|   610   return Integer_addFromInteger(assembler); |   610   return Integer_addFromInteger(assembler); | 
|   611 } |   611 } | 
|   612  |   612  | 
|   613  |   613  | 
|   614 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) { |   614 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) { | 
|   615   Label fall_through; |   615   Label fall_through; | 
|   616  |   616  | 
|   617   TestBothArgumentsSmis(assembler, &fall_through); |   617   TestBothArgumentsSmis(assembler, &fall_through); | 
|   618   __ SubuDetectOverflow(V0, T0, T1, CMPRES);  // Subtract. |   618   __ SubuDetectOverflow(V0, T0, T1, CMPRES1);  // Subtract. | 
|   619   __ bltz(CMPRES, &fall_through);  // Fall through on overflow. |   619   __ bltz(CMPRES1, &fall_through);  // Fall through on overflow. | 
|   620   __ Ret(); |   620   __ Ret(); | 
|   621   __ Bind(&fall_through); |   621   __ Bind(&fall_through); | 
|   622 } |   622 } | 
|   623  |   623  | 
|   624  |   624  | 
|   625 void Intrinsifier::Integer_sub(Assembler* assembler) { |   625 void Intrinsifier::Integer_sub(Assembler* assembler) { | 
|   626   Label fall_through; |   626   Label fall_through; | 
|   627  |   627  | 
|   628   TestBothArgumentsSmis(assembler, &fall_through); |   628   TestBothArgumentsSmis(assembler, &fall_through); | 
|   629   __ SubuDetectOverflow(V0, T1, T0, CMPRES);  // Subtract. |   629   __ SubuDetectOverflow(V0, T1, T0, CMPRES1);  // Subtract. | 
|   630   __ bltz(CMPRES, &fall_through);  // Fall through on overflow. |   630   __ bltz(CMPRES1, &fall_through);  // Fall through on overflow. | 
|   631   __ Ret();  // Nothing in branch delay slot. |   631   __ Ret();  // Nothing in branch delay slot. | 
|   632   __ Bind(&fall_through); |   632   __ Bind(&fall_through); | 
|   633 } |   633 } | 
|   634  |   634  | 
|   635  |   635  | 
|   636 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { |   636 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { | 
|   637   Label fall_through; |   637   Label fall_through; | 
|   638  |   638  | 
|   639   TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis |   639   TestBothArgumentsSmis(assembler, &fall_through);  // checks two smis | 
|   640   __ SmiUntag(T0);  // untags T0. only want result shifted by one |   640   __ SmiUntag(T0);  // untags T0. only want result shifted by one | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   699 //      res = res - right; |   699 //      res = res - right; | 
|   700 //    } else { |   700 //    } else { | 
|   701 //      res = res + right; |   701 //      res = res + right; | 
|   702 //    } |   702 //    } | 
|   703 //  } |   703 //  } | 
|   704 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { |   704 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { | 
|   705   Label fall_through, subtract; |   705   Label fall_through, subtract; | 
|   706   // Test arguments for smi. |   706   // Test arguments for smi. | 
|   707   __ lw(T1, Address(SP, 0 * kWordSize)); |   707   __ lw(T1, Address(SP, 0 * kWordSize)); | 
|   708   __ lw(T0, Address(SP, 1 * kWordSize)); |   708   __ lw(T0, Address(SP, 1 * kWordSize)); | 
|   709   __ or_(CMPRES, T0, T1); |   709   __ or_(CMPRES1, T0, T1); | 
|   710   __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); |   710   __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); | 
|   711   __ bne(CMPRES, ZR, &fall_through); |   711   __ bne(CMPRES1, ZR, &fall_through); | 
|   712   // T1: Tagged left (dividend). |   712   // T1: Tagged left (dividend). | 
|   713   // T0: Tagged right (divisor). |   713   // T0: Tagged right (divisor). | 
|   714   // Check if modulo by zero -> exception thrown in main function. |   714   // Check if modulo by zero -> exception thrown in main function. | 
|   715   __ beq(T0, ZR, &fall_through); |   715   __ beq(T0, ZR, &fall_through); | 
|   716   EmitRemainderOperation(assembler); |   716   EmitRemainderOperation(assembler); | 
|   717   // Untagged right in T0. Untagged remainder result in V0. |   717   // Untagged right in T0. Untagged remainder result in V0. | 
|   718  |   718  | 
|   719   Label done; |   719   Label done; | 
|   720   __ bgez(V0, &done); |   720   __ bgez(V0, &done); | 
|   721   __ bltz(T0, &subtract); |   721   __ bltz(T0, &subtract); | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|   752   __ Ret(); |   752   __ Ret(); | 
|   753   __ delay_slot()->SmiTag(V0); |   753   __ delay_slot()->SmiTag(V0); | 
|   754   __ Bind(&fall_through); |   754   __ Bind(&fall_through); | 
|   755 } |   755 } | 
|   756  |   756  | 
|   757  |   757  | 
|   758 void Intrinsifier::Integer_negate(Assembler* assembler) { |   758 void Intrinsifier::Integer_negate(Assembler* assembler) { | 
|   759   Label fall_through; |   759   Label fall_through; | 
|   760  |   760  | 
|   761   __ lw(T0, Address(SP, + 0 * kWordSize));  // Grabs first argument. |   761   __ lw(T0, Address(SP, + 0 * kWordSize));  // Grabs first argument. | 
|   762   __ andi(CMPRES, T0, Immediate(kSmiTagMask));  // Test for Smi. |   762   __ andi(CMPRES1, T0, Immediate(kSmiTagMask));  // Test for Smi. | 
|   763   __ bne(CMPRES, ZR, &fall_through);  // Fall through if not a Smi. |   763   __ bne(CMPRES1, ZR, &fall_through);  // Fall through if not a Smi. | 
|   764   __ SubuDetectOverflow(V0, ZR, T0, CMPRES); |   764   __ SubuDetectOverflow(V0, ZR, T0, CMPRES1); | 
|   765   __ bltz(CMPRES, &fall_through);  // There was overflow. |   765   __ bltz(CMPRES1, &fall_through);  // There was overflow. | 
|   766   __ Ret(); |   766   __ Ret(); | 
|   767   __ Bind(&fall_through); |   767   __ Bind(&fall_through); | 
|   768 } |   768 } | 
|   769  |   769  | 
|   770  |   770  | 
|   771 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { |   771 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { | 
|   772   Label fall_through; |   772   Label fall_through; | 
|   773  |   773  | 
|   774   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis. |   774   TestBothArgumentsSmis(assembler, &fall_through);  // Checks two smis. | 
|   775   __ Ret(); |   775   __ Ret(); | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   862   __ Bind(&fall_through); |   862   __ Bind(&fall_through); | 
|   863 } |   863 } | 
|   864  |   864  | 
|   865  |   865  | 
|   866 static void Get64SmiOrMint(Assembler* assembler, |   866 static void Get64SmiOrMint(Assembler* assembler, | 
|   867                            Register res_hi, |   867                            Register res_hi, | 
|   868                            Register res_lo, |   868                            Register res_lo, | 
|   869                            Register reg, |   869                            Register reg, | 
|   870                            Label* not_smi_or_mint) { |   870                            Label* not_smi_or_mint) { | 
|   871   Label not_smi, done; |   871   Label not_smi, done; | 
|   872   __ andi(CMPRES, reg, Immediate(kSmiTagMask)); |   872   __ andi(CMPRES1, reg, Immediate(kSmiTagMask)); | 
|   873   __ bne(CMPRES, ZR, ¬_smi); |   873   __ bne(CMPRES1, ZR, ¬_smi); | 
|   874   __ SmiUntag(reg); |   874   __ SmiUntag(reg); | 
|   875  |   875  | 
|   876   // Sign extend to 64 bit |   876   // Sign extend to 64 bit | 
|   877   __ mov(res_lo, reg); |   877   __ mov(res_lo, reg); | 
|   878   __ b(&done); |   878   __ b(&done); | 
|   879   __ delay_slot()->sra(res_hi, reg, 31); |   879   __ delay_slot()->sra(res_hi, reg, 31); | 
|   880  |   880  | 
|   881   __ Bind(¬_smi); |   881   __ Bind(¬_smi); | 
|   882   __ LoadClassId(CMPRES1, reg); |   882   __ LoadClassId(CMPRES1, reg); | 
|   883   __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint); |   883   __ BranchNotEqual(CMPRES1, kMintCid, not_smi_or_mint); | 
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   990 // This is called for Smi, Mint and Bigint receivers. The right argument |   990 // This is called for Smi, Mint and Bigint receivers. The right argument | 
|   991 // can be Smi, Mint, Bigint or double. |   991 // can be Smi, Mint, Bigint or double. | 
|   992 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { |   992 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { | 
|   993   Label fall_through, true_label, check_for_mint; |   993   Label fall_through, true_label, check_for_mint; | 
|   994   // For integer receiver '===' check first. |   994   // For integer receiver '===' check first. | 
|   995   __ lw(T0, Address(SP, 0 * kWordSize)); |   995   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|   996   __ lw(T1, Address(SP, 1 * kWordSize)); |   996   __ lw(T1, Address(SP, 1 * kWordSize)); | 
|   997   __ beq(T0, T1, &true_label); |   997   __ beq(T0, T1, &true_label); | 
|   998  |   998  | 
|   999   __ or_(T2, T0, T1); |   999   __ or_(T2, T0, T1); | 
|  1000   __ andi(CMPRES, T2, Immediate(kSmiTagMask)); |  1000   __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); | 
|  1001   // If T0 or T1 is not a smi do Mint checks. |  1001   // If T0 or T1 is not a smi do Mint checks. | 
|  1002   __ bne(CMPRES, ZR, &check_for_mint); |  1002   __ bne(CMPRES1, ZR, &check_for_mint); | 
|  1003  |  1003  | 
|  1004   // Both arguments are smi, '===' is good enough. |  1004   // Both arguments are smi, '===' is good enough. | 
|  1005   __ LoadObject(V0, Bool::False()); |  1005   __ LoadObject(V0, Bool::False()); | 
|  1006   __ Ret(); |  1006   __ Ret(); | 
|  1007   __ Bind(&true_label); |  1007   __ Bind(&true_label); | 
|  1008   __ LoadObject(V0, Bool::True()); |  1008   __ LoadObject(V0, Bool::True()); | 
|  1009   __ Ret(); |  1009   __ Ret(); | 
|  1010  |  1010  | 
|  1011   // At least one of the arguments was not Smi. |  1011   // At least one of the arguments was not Smi. | 
|  1012   Label receiver_not_smi; |  1012   Label receiver_not_smi; | 
|  1013   __ Bind(&check_for_mint); |  1013   __ Bind(&check_for_mint); | 
|  1014  |  1014  | 
|  1015   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |  1015   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|  1016   __ bne(CMPRES, ZR, &receiver_not_smi);  // Check receiver. |  1016   __ bne(CMPRES1, ZR, &receiver_not_smi);  // Check receiver. | 
|  1017  |  1017  | 
|  1018   // Left (receiver) is Smi, return false if right is not Double. |  1018   // Left (receiver) is Smi, return false if right is not Double. | 
|  1019   // Note that an instance of Mint or Bigint never contains a value that can be |  1019   // Note that an instance of Mint or Bigint never contains a value that can be | 
|  1020   // represented by Smi. |  1020   // represented by Smi. | 
|  1021  |  1021  | 
|  1022   __ LoadClassId(CMPRES1, T0); |  1022   __ LoadClassId(CMPRES1, T0); | 
|  1023   __ BranchEqual(CMPRES1, kDoubleCid, &fall_through); |  1023   __ BranchEqual(CMPRES1, kDoubleCid, &fall_through); | 
|  1024   __ LoadObject(V0, Bool::False());  // Smi == Mint -> false. |  1024   __ LoadObject(V0, Bool::False());  // Smi == Mint -> false. | 
|  1025   __ Ret(); |  1025   __ Ret(); | 
|  1026  |  1026  | 
|  1027   __ Bind(&receiver_not_smi); |  1027   __ Bind(&receiver_not_smi); | 
|  1028   // T1:: receiver. |  1028   // T1:: receiver. | 
|  1029  |  1029  | 
|  1030   __ LoadClassId(CMPRES1, T1); |  1030   __ LoadClassId(CMPRES1, T1); | 
|  1031   __ BranchNotEqual(CMPRES1, kMintCid, &fall_through); |  1031   __ BranchNotEqual(CMPRES1, kMintCid, &fall_through); | 
|  1032   // Receiver is Mint, return false if right is Smi. |  1032   // Receiver is Mint, return false if right is Smi. | 
|  1033   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |  1033   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|  1034   __ bne(CMPRES, ZR, &fall_through); |  1034   __ bne(CMPRES1, ZR, &fall_through); | 
|  1035   __ LoadObject(V0, Bool::False()); |  1035   __ LoadObject(V0, Bool::False()); | 
|  1036   __ Ret(); |  1036   __ Ret(); | 
|  1037   // TODO(srdjan): Implement Mint == Mint comparison. |  1037   // TODO(srdjan): Implement Mint == Mint comparison. | 
|  1038  |  1038  | 
|  1039   __ Bind(&fall_through); |  1039   __ Bind(&fall_through); | 
|  1040 } |  1040 } | 
|  1041  |  1041  | 
|  1042  |  1042  | 
|  1043 void Intrinsifier::Integer_equal(Assembler* assembler) { |  1043 void Intrinsifier::Integer_equal(Assembler* assembler) { | 
|  1044   return Integer_equalToInteger(assembler); |  1044   return Integer_equalToInteger(assembler); | 
|  1045 } |  1045 } | 
|  1046  |  1046  | 
|  1047  |  1047  | 
|  1048 void Intrinsifier::Integer_sar(Assembler* assembler) { |  1048 void Intrinsifier::Integer_sar(Assembler* assembler) { | 
|  1049   Label fall_through; |  1049   Label fall_through; | 
|  1050  |  1050  | 
|  1051   TestBothArgumentsSmis(assembler, &fall_through); |  1051   TestBothArgumentsSmis(assembler, &fall_through); | 
|  1052   // Shift amount in T0. Value to shift in T1. |  1052   // Shift amount in T0. Value to shift in T1. | 
|  1053  |  1053  | 
|  1054   __ SmiUntag(T0); |  1054   __ SmiUntag(T0); | 
|  1055   __ bltz(T0, &fall_through); |  1055   __ bltz(T0, &fall_through); | 
|  1056  |  1056  | 
|  1057   __ LoadImmediate(T2, 0x1F); |  1057   __ LoadImmediate(T2, 0x1F); | 
|  1058   __ slt(CMPRES, T2, T0);  // CMPRES <- 0x1F < T0 ? 1 : 0 |  1058   __ slt(CMPRES1, T2, T0);  // CMPRES1 <- 0x1F < T0 ? 1 : 0 | 
|  1059   __ movn(T0, T2, CMPRES);  // T0 <- 0x1F < T0 ? 0x1F : T0 |  1059   __ movn(T0, T2, CMPRES1);  // T0 <- 0x1F < T0 ? 0x1F : T0 | 
|  1060  |  1060  | 
|  1061   __ SmiUntag(T1); |  1061   __ SmiUntag(T1); | 
|  1062   __ srav(V0, T1, T0); |  1062   __ srav(V0, T1, T0); | 
|  1063   __ Ret(); |  1063   __ Ret(); | 
|  1064   __ delay_slot()->SmiTag(V0); |  1064   __ delay_slot()->SmiTag(V0); | 
|  1065   __ Bind(&fall_through); |  1065   __ Bind(&fall_through); | 
|  1066 } |  1066 } | 
|  1067  |  1067  | 
|  1068  |  1068  | 
|  1069 void Intrinsifier::Smi_bitNegate(Assembler* assembler) { |  1069 void Intrinsifier::Smi_bitNegate(Assembler* assembler) { | 
|  1070   __ lw(T0, Address(SP, 0 * kWordSize)); |  1070   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|  1071   __ nor(V0, T0, ZR); |  1071   __ nor(V0, T0, ZR); | 
|  1072   __ Ret(); |  1072   __ Ret(); | 
|  1073   __ delay_slot()->addiu(V0, V0, Immediate(-1));  // Remove inverted smi-tag. |  1073   __ delay_slot()->addiu(V0, V0, Immediate(-1));  // Remove inverted smi-tag. | 
|  1074 } |  1074 } | 
|  1075  |  1075  | 
|  1076  |  1076  | 
|  1077 void Intrinsifier::Smi_bitLength(Assembler* assembler) { |  1077 void Intrinsifier::Smi_bitLength(Assembler* assembler) { | 
|  1078   // TODO(sra): Implement. |  1078   // TODO(sra): Implement. | 
|  1079 } |  1079 } | 
|  1080  |  1080  | 
|  1081  |  1081  | 
|  1082 // Check if the last argument is a double, jump to label 'is_smi' if smi |  1082 // Check if the last argument is a double, jump to label 'is_smi' if smi | 
|  1083 // (easy to convert to double), otherwise jump to label 'not_double_smi', |  1083 // (easy to convert to double), otherwise jump to label 'not_double_smi', | 
|  1084 // Returns the last argument in T0. |  1084 // Returns the last argument in T0. | 
|  1085 static void TestLastArgumentIsDouble(Assembler* assembler, |  1085 static void TestLastArgumentIsDouble(Assembler* assembler, | 
|  1086                                      Label* is_smi, |  1086                                      Label* is_smi, | 
|  1087                                      Label* not_double_smi) { |  1087                                      Label* not_double_smi) { | 
|  1088   __ lw(T0, Address(SP, 0 * kWordSize)); |  1088   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|  1089   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |  1089   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|  1090   __ beq(CMPRES, ZR, is_smi); |  1090   __ beq(CMPRES1, ZR, is_smi); | 
|  1091   __ LoadClassId(CMPRES1, T0); |  1091   __ LoadClassId(CMPRES1, T0); | 
|  1092   __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi); |  1092   __ BranchNotEqual(CMPRES1, kDoubleCid, not_double_smi); | 
|  1093   // Fall through with Double in T0. |  1093   // Fall through with Double in T0. | 
|  1094 } |  1094 } | 
|  1095  |  1095  | 
|  1096  |  1096  | 
|  1097 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown |  1097 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown | 
|  1098 // type. Return true or false object in the register V0. Any NaN argument |  1098 // type. Return true or false object in the register V0. Any NaN argument | 
|  1099 // returns false. Any non-double arg1 causes control flow to fall through to the |  1099 // returns false. Any non-double arg1 causes control flow to fall through to the | 
|  1100 // slow case (compiled method body). |  1100 // slow case (compiled method body). | 
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1221 void Intrinsifier::Double_div(Assembler* assembler) { |  1221 void Intrinsifier::Double_div(Assembler* assembler) { | 
|  1222   return DoubleArithmeticOperations(assembler, Token::kDIV); |  1222   return DoubleArithmeticOperations(assembler, Token::kDIV); | 
|  1223 } |  1223 } | 
|  1224  |  1224  | 
|  1225  |  1225  | 
|  1226 // Left is double right is integer (Bigint, Mint or Smi) |  1226 // Left is double right is integer (Bigint, Mint or Smi) | 
|  1227 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { |  1227 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { | 
|  1228   Label fall_through; |  1228   Label fall_through; | 
|  1229   // Only smis allowed. |  1229   // Only smis allowed. | 
|  1230   __ lw(T0, Address(SP, 0 * kWordSize)); |  1230   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|  1231   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |  1231   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|  1232   __ bne(CMPRES, ZR, &fall_through); |  1232   __ bne(CMPRES1, ZR, &fall_through); | 
|  1233  |  1233  | 
|  1234   // Is Smi. |  1234   // Is Smi. | 
|  1235   __ SmiUntag(T0); |  1235   __ SmiUntag(T0); | 
|  1236   __ mtc1(T0, F4); |  1236   __ mtc1(T0, F4); | 
|  1237   __ cvtdw(D1, F4); |  1237   __ cvtdw(D1, F4); | 
|  1238  |  1238  | 
|  1239   __ lw(T0, Address(SP, 1 * kWordSize)); |  1239   __ lw(T0, Address(SP, 1 * kWordSize)); | 
|  1240   __ lwc1(F0, FieldAddress(T0, Double::value_offset())); |  1240   __ lwc1(F0, FieldAddress(T0, Double::value_offset())); | 
|  1241   __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); |  1241   __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize)); | 
|  1242   __ muld(D0, D0, D1); |  1242   __ muld(D0, D0, D1); | 
|  1243   const Class& double_class = Class::Handle( |  1243   const Class& double_class = Class::Handle( | 
|  1244       Isolate::Current()->object_store()->double_class()); |  1244       Isolate::Current()->object_store()->double_class()); | 
|  1245   __ TryAllocate(double_class, &fall_through, V0);  // Result register. |  1245   __ TryAllocate(double_class, &fall_through, V0);  // Result register. | 
|  1246   __ swc1(F0, FieldAddress(V0, Double::value_offset())); |  1246   __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 
|  1247   __ Ret(); |  1247   __ Ret(); | 
|  1248   __ delay_slot()->swc1(F1, |  1248   __ delay_slot()->swc1(F1, | 
|  1249                         FieldAddress(V0, Double::value_offset() + kWordSize)); |  1249                         FieldAddress(V0, Double::value_offset() + kWordSize)); | 
|  1250   __ Bind(&fall_through); |  1250   __ Bind(&fall_through); | 
|  1251 } |  1251 } | 
|  1252  |  1252  | 
|  1253  |  1253  | 
|  1254 void Intrinsifier::Double_fromInteger(Assembler* assembler) { |  1254 void Intrinsifier::Double_fromInteger(Assembler* assembler) { | 
|  1255   Label fall_through; |  1255   Label fall_through; | 
|  1256  |  1256  | 
|  1257   __ lw(T0, Address(SP, 0 * kWordSize)); |  1257   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|  1258   __ andi(CMPRES, T0, Immediate(kSmiTagMask)); |  1258   __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 
|  1259   __ bne(T0, ZR, &fall_through); |  1259   __ bne(T0, ZR, &fall_through); | 
|  1260  |  1260  | 
|  1261   // Is Smi. |  1261   // Is Smi. | 
|  1262   __ SmiUntag(T0); |  1262   __ SmiUntag(T0); | 
|  1263   __ mtc1(T0, F4); |  1263   __ mtc1(T0, F4); | 
|  1264   __ cvtdw(D0, F4); |  1264   __ cvtdw(D0, F4); | 
|  1265   const Class& double_class = Class::Handle( |  1265   const Class& double_class = Class::Handle( | 
|  1266       Isolate::Current()->object_store()->double_class()); |  1266       Isolate::Current()->object_store()->double_class()); | 
|  1267   __ TryAllocate(double_class, &fall_through, V0);  // Result register. |  1267   __ TryAllocate(double_class, &fall_through, V0);  // Result register. | 
|  1268   __ swc1(F0, FieldAddress(V0, Double::value_offset())); |  1268   __ swc1(F0, FieldAddress(V0, Double::value_offset())); | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1309   __ Ret(); |  1309   __ Ret(); | 
|  1310  |  1310  | 
|  1311   __ Bind(&is_false); |  1311   __ Bind(&is_false); | 
|  1312   __ LoadObject(V0, Bool::False()); |  1312   __ LoadObject(V0, Bool::False()); | 
|  1313   __ Ret(); |  1313   __ Ret(); | 
|  1314  |  1314  | 
|  1315   __ Bind(&is_zero); |  1315   __ Bind(&is_zero); | 
|  1316   // Check for negative zero by looking at the sign bit. |  1316   // Check for negative zero by looking at the sign bit. | 
|  1317   __ mfc1(T0, F1);  // Moves bits 32...63 of D0 to T0. |  1317   __ mfc1(T0, F1);  // Moves bits 32...63 of D0 to T0. | 
|  1318   __ srl(T0, T0, 31);  // Get the sign bit down to bit 0 of T0. |  1318   __ srl(T0, T0, 31);  // Get the sign bit down to bit 0 of T0. | 
|  1319   __ andi(CMPRES, T0, Immediate(1));  // Check if the bit is set. |  1319   __ andi(CMPRES1, T0, Immediate(1));  // Check if the bit is set. | 
|  1320   __ bne(T0, ZR, &is_true);  // Sign bit set. True. |  1320   __ bne(T0, ZR, &is_true);  // Sign bit set. True. | 
|  1321   __ b(&is_false); |  1321   __ b(&is_false); | 
|  1322 } |  1322 } | 
|  1323  |  1323  | 
|  1324  |  1324  | 
|  1325 void Intrinsifier::Double_toInt(Assembler* assembler) { |  1325 void Intrinsifier::Double_toInt(Assembler* assembler) { | 
|  1326   __ lw(T0, Address(SP, 0 * kWordSize)); |  1326   __ lw(T0, Address(SP, 0 * kWordSize)); | 
|  1327   __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); |  1327   __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag); | 
|  1328  |  1328  | 
|  1329   __ cvtwd(F2, D0); |  1329   __ cvtwd(F2, D0); | 
|  1330   __ mfc1(V0, F2); |  1330   __ mfc1(V0, F2); | 
|  1331  |  1331  | 
|  1332   // Overflow is signaled with minint. |  1332   // Overflow is signaled with minint. | 
|  1333   Label fall_through; |  1333   Label fall_through; | 
|  1334   // Check for overflow and that it fits into Smi. |  1334   // Check for overflow and that it fits into Smi. | 
|  1335   __ LoadImmediate(TMP, 0xC0000000); |  1335   __ LoadImmediate(TMP, 0xC0000000); | 
|  1336   __ subu(CMPRES, V0, TMP); |  1336   __ subu(CMPRES1, V0, TMP); | 
|  1337   __ bltz(CMPRES, &fall_through); |  1337   __ bltz(CMPRES1, &fall_through); | 
|  1338   __ Ret(); |  1338   __ Ret(); | 
|  1339   __ delay_slot()->SmiTag(V0); |  1339   __ delay_slot()->SmiTag(V0); | 
|  1340   __ Bind(&fall_through); |  1340   __ Bind(&fall_through); | 
|  1341 } |  1341 } | 
|  1342  |  1342  | 
|  1343  |  1343  | 
|  1344 void Intrinsifier::Math_sqrt(Assembler* assembler) { |  1344 void Intrinsifier::Math_sqrt(Assembler* assembler) { | 
|  1345   Label fall_through, is_smi, double_op; |  1345   Label fall_through, is_smi, double_op; | 
|  1346   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |  1346   TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); | 
|  1347   // Argument is double and is in T0. |  1347   // Argument is double and is in T0. | 
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1452 } |  1452 } | 
|  1453  |  1453  | 
|  1454  |  1454  | 
|  1455 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { |  1455 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { | 
|  1456   Label fall_through, try_two_byte_string; |  1456   Label fall_through, try_two_byte_string; | 
|  1457  |  1457  | 
|  1458   __ lw(T1, Address(SP, 0 * kWordSize));  // Index. |  1458   __ lw(T1, Address(SP, 0 * kWordSize));  // Index. | 
|  1459   __ lw(T0, Address(SP, 1 * kWordSize));  // String. |  1459   __ lw(T0, Address(SP, 1 * kWordSize));  // String. | 
|  1460  |  1460  | 
|  1461   // Checks. |  1461   // Checks. | 
|  1462   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |  1462   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|  1463   __ bne(T1, ZR, &fall_through);  // Index is not a Smi. |  1463   __ bne(T1, ZR, &fall_through);  // Index is not a Smi. | 
|  1464   __ lw(T2, FieldAddress(T0, String::length_offset()));  // Range check. |  1464   __ lw(T2, FieldAddress(T0, String::length_offset()));  // Range check. | 
|  1465   // Runtime throws exception. |  1465   // Runtime throws exception. | 
|  1466   __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); |  1466   __ BranchUnsignedGreaterEqual(T1, T2, &fall_through); | 
|  1467   __ LoadClassId(CMPRES1, T0);  // Class ID check. |  1467   __ LoadClassId(CMPRES1, T0);  // Class ID check. | 
|  1468   __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); |  1468   __ BranchNotEqual(CMPRES1, kOneByteStringCid, &try_two_byte_string); | 
|  1469  |  1469  | 
|  1470   // Grab byte and return. |  1470   // Grab byte and return. | 
|  1471   __ SmiUntag(T1); |  1471   __ SmiUntag(T1); | 
|  1472   __ addu(T2, T0, T1); |  1472   __ addu(T2, T0, T1); | 
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1583   __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); |  1583   __ LoadImmediate(TMP, ~(kObjectAlignment - 1)); | 
|  1584   __ and_(length_reg, length_reg, TMP); |  1584   __ and_(length_reg, length_reg, TMP); | 
|  1585  |  1585  | 
|  1586   Isolate* isolate = Isolate::Current(); |  1586   Isolate* isolate = Isolate::Current(); | 
|  1587   Heap* heap = isolate->heap(); |  1587   Heap* heap = isolate->heap(); | 
|  1588  |  1588  | 
|  1589   __ LoadImmediate(T3, heap->TopAddress()); |  1589   __ LoadImmediate(T3, heap->TopAddress()); | 
|  1590   __ lw(V0, Address(T3, 0)); |  1590   __ lw(V0, Address(T3, 0)); | 
|  1591  |  1591  | 
|  1592   // length_reg: allocation size. |  1592   // length_reg: allocation size. | 
|  1593   __ AdduDetectOverflow(T1, V0, length_reg, CMPRES); |  1593   __ AdduDetectOverflow(T1, V0, length_reg, CMPRES1); | 
|  1594   __ bltz(CMPRES, failure);  // Fail on overflow. |  1594   __ bltz(CMPRES1, failure);  // Fail on overflow. | 
|  1595  |  1595  | 
|  1596   // Check if the allocation fits into the remaining space. |  1596   // Check if the allocation fits into the remaining space. | 
|  1597   // V0: potential new object start. |  1597   // V0: potential new object start. | 
|  1598   // T1: potential next object start. |  1598   // T1: potential next object start. | 
|  1599   // T2: allocation size. |  1599   // T2: allocation size. | 
|  1600   // T3: heap->TopAddress(). |  1600   // T3: heap->TopAddress(). | 
|  1601   __ LoadImmediate(T4, heap->EndAddress()); |  1601   __ LoadImmediate(T4, heap->EndAddress()); | 
|  1602   __ lw(T4, Address(T4, 0)); |  1602   __ lw(T4, Address(T4, 0)); | 
|  1603   __ BranchUnsignedGreaterEqual(T1, T4, failure); |  1603   __ BranchUnsignedGreaterEqual(T1, T4, failure); | 
|  1604  |  1604  | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  1619  |  1619  | 
|  1620     __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); |  1620     __ BranchUnsignedGreater(T2, RawObject::SizeTag::kMaxSizeTag, &overflow); | 
|  1621     __ b(&done); |  1621     __ b(&done); | 
|  1622     __ delay_slot()->sll(T2, T2, shift); |  1622     __ delay_slot()->sll(T2, T2, shift); | 
|  1623     __ Bind(&overflow); |  1623     __ Bind(&overflow); | 
|  1624     __ mov(T2, ZR); |  1624     __ mov(T2, ZR); | 
|  1625     __ Bind(&done); |  1625     __ Bind(&done); | 
|  1626  |  1626  | 
|  1627     // Get the class index and insert it into the tags. |  1627     // Get the class index and insert it into the tags. | 
|  1628     // T2: size and bit tags. |  1628     // T2: size and bit tags. | 
|  1629     __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(cls.id())); |  1629     __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cls.id())); | 
|  1630     __ or_(T2, T2, TMP1); |  1630     __ or_(T2, T2, TMP); | 
|  1631     __ sw(T2, FieldAddress(V0, String::tags_offset()));  // Store tags. |  1631     __ sw(T2, FieldAddress(V0, String::tags_offset()));  // Store tags. | 
|  1632   } |  1632   } | 
|  1633  |  1633  | 
|  1634   // Set the length field using the saved length (T6). |  1634   // Set the length field using the saved length (T6). | 
|  1635   __ StoreIntoObjectNoBarrier(V0, |  1635   __ StoreIntoObjectNoBarrier(V0, | 
|  1636                               FieldAddress(V0, String::length_offset()), |  1636                               FieldAddress(V0, String::length_offset()), | 
|  1637                               T6); |  1637                               T6); | 
|  1638   // Clear hash. |  1638   // Clear hash. | 
|  1639   __ b(ok); |  1639   __ b(ok); | 
|  1640   __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); |  1640   __ delay_slot()->sw(ZR, FieldAddress(V0, String::hash_offset())); | 
|  1641 } |  1641 } | 
|  1642  |  1642  | 
|  1643  |  1643  | 
|  1644 // Arg0: OneByteString (receiver). |  1644 // Arg0: OneByteString (receiver). | 
|  1645 // Arg1: Start index as Smi. |  1645 // Arg1: Start index as Smi. | 
|  1646 // Arg2: End index as Smi. |  1646 // Arg2: End index as Smi. | 
|  1647 // The indexes must be valid. |  1647 // The indexes must be valid. | 
|  1648 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { |  1648 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { | 
|  1649   const intptr_t kStringOffset = 2 * kWordSize; |  1649   const intptr_t kStringOffset = 2 * kWordSize; | 
|  1650   const intptr_t kStartIndexOffset = 1 * kWordSize; |  1650   const intptr_t kStartIndexOffset = 1 * kWordSize; | 
|  1651   const intptr_t kEndIndexOffset = 0 * kWordSize; |  1651   const intptr_t kEndIndexOffset = 0 * kWordSize; | 
|  1652   Label fall_through, ok; |  1652   Label fall_through, ok; | 
|  1653  |  1653  | 
|  1654   __ lw(T2, Address(SP, kEndIndexOffset)); |  1654   __ lw(T2, Address(SP, kEndIndexOffset)); | 
|  1655   __ lw(TMP, Address(SP, kStartIndexOffset)); |  1655   __ lw(TMP, Address(SP, kStartIndexOffset)); | 
|  1656   __ or_(CMPRES, T2, TMP); |  1656   __ or_(CMPRES1, T2, TMP); | 
|  1657   __ andi(CMPRES, CMPRES, Immediate(kSmiTagMask)); |  1657   __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); | 
|  1658   __ bne(CMPRES, ZR, &fall_through);  // 'start', 'end' not Smi. |  1658   __ bne(CMPRES1, ZR, &fall_through);  // 'start', 'end' not Smi. | 
|  1659  |  1659  | 
|  1660   __ subu(T2, T2, TMP); |  1660   __ subu(T2, T2, TMP); | 
|  1661   TryAllocateOnebyteString(assembler, &ok, &fall_through); |  1661   TryAllocateOnebyteString(assembler, &ok, &fall_through); | 
|  1662   __ Bind(&ok); |  1662   __ Bind(&ok); | 
|  1663   // V0: new string as tagged pointer. |  1663   // V0: new string as tagged pointer. | 
|  1664   // Copy string. |  1664   // Copy string. | 
|  1665   __ lw(T3, Address(SP, kStringOffset)); |  1665   __ lw(T3, Address(SP, kStringOffset)); | 
|  1666   __ lw(T1, Address(SP, kStartIndexOffset)); |  1666   __ lw(T1, Address(SP, kStartIndexOffset)); | 
|  1667   __ SmiUntag(T1); |  1667   __ SmiUntag(T1); | 
|  1668   __ addu(T3, T3, T1); |  1668   __ addu(T3, T3, T1); | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1727 // TODO(srdjan): Add combinations (one-byte/two-byte/external strings). |  1727 // TODO(srdjan): Add combinations (one-byte/two-byte/external strings). | 
|  1728 void StringEquality(Assembler* assembler, intptr_t string_cid) { |  1728 void StringEquality(Assembler* assembler, intptr_t string_cid) { | 
|  1729   Label fall_through, is_true, is_false, loop; |  1729   Label fall_through, is_true, is_false, loop; | 
|  1730   __ lw(T0, Address(SP, 1 * kWordSize));  // This. |  1730   __ lw(T0, Address(SP, 1 * kWordSize));  // This. | 
|  1731   __ lw(T1, Address(SP, 0 * kWordSize));  // Other. |  1731   __ lw(T1, Address(SP, 0 * kWordSize));  // Other. | 
|  1732  |  1732  | 
|  1733   // Are identical? |  1733   // Are identical? | 
|  1734   __ beq(T0, T1, &is_true); |  1734   __ beq(T0, T1, &is_true); | 
|  1735  |  1735  | 
|  1736   // Is other OneByteString? |  1736   // Is other OneByteString? | 
|  1737   __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |  1737   __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 
|  1738   __ beq(CMPRES, ZR, &fall_through);  // Other is Smi. |  1738   __ beq(CMPRES1, ZR, &fall_through);  // Other is Smi. | 
|  1739   __ LoadClassId(CMPRES1, T1);  // Class ID check. |  1739   __ LoadClassId(CMPRES1, T1);  // Class ID check. | 
|  1740   __ BranchNotEqual(CMPRES1, string_cid, &fall_through); |  1740   __ BranchNotEqual(CMPRES1, string_cid, &fall_through); | 
|  1741  |  1741  | 
|  1742   // Have same length? |  1742   // Have same length? | 
|  1743   __ lw(T2, FieldAddress(T0, String::length_offset())); |  1743   __ lw(T2, FieldAddress(T0, String::length_offset())); | 
|  1744   __ lw(T3, FieldAddress(T1, String::length_offset())); |  1744   __ lw(T3, FieldAddress(T1, String::length_offset())); | 
|  1745   __ bne(T2, T3, &is_false); |  1745   __ bne(T2, T3, &is_false); | 
|  1746  |  1746  | 
|  1747   // Check contents, no fall-through possible. |  1747   // Check contents, no fall-through possible. | 
|  1748   ASSERT((string_cid == kOneByteStringCid) || |  1748   ASSERT((string_cid == kOneByteStringCid) || | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1783 } |  1783 } | 
|  1784  |  1784  | 
|  1785  |  1785  | 
|  1786 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { |  1786 void Intrinsifier::TwoByteString_equality(Assembler* assembler) { | 
|  1787   StringEquality(assembler, kTwoByteStringCid); |  1787   StringEquality(assembler, kTwoByteStringCid); | 
|  1788 } |  1788 } | 
|  1789  |  1789  | 
|  1790 }  // namespace dart |  1790 }  // namespace dart | 
|  1791  |  1791  | 
|  1792 #endif  // defined TARGET_ARCH_MIPS |  1792 #endif  // defined TARGET_ARCH_MIPS | 
| OLD | NEW |