Chromium Code Reviews| Index: runtime/vm/intrinsifier_mips.cc |
| diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc |
| index 748f06dff9d7bdda74aa590ac74a56fae2844ae1..ec2b362c3e32de39a56568ac5034e6e81ab3b980 100644 |
| --- a/runtime/vm/intrinsifier_mips.cc |
| +++ b/runtime/vm/intrinsifier_mips.cc |
| @@ -1668,15 +1668,109 @@ void Intrinsifier::ObjectEquals(Assembler* assembler) { |
| } |
| +enum RangeCheckCondition { |
| + kIfNotInRange, kIfInRange |
| +}; |
| + |
| + |
| +static void RangeCheck(Assembler* assembler, |
| + Register val, |
| + Register tmp, |
| + intptr_t low, |
| + intptr_t high, |
| + RangeCheckCondition cc, |
| + Label* target) { |
| + __ AddImmediate(tmp, val, -low); |
| + if (cc == kIfInRange) { |
| + __ BranchUnsignedLessEqual(tmp, Immediate(high - low), target); |
| + } else { |
| + ASSERT(cc == kIfNotInRange); |
| + __ BranchUnsignedGreater(tmp, Immediate(high - low), target); |
| + } |
| +} |
| + |
| + |
| +static void JumpIfInteger(Assembler* assembler, |
| + Register cid, |
| + Register tmp, |
| + Label* target) { |
| + RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target); |
| +} |
| + |
| + |
| +static void JumpIfNotInteger(Assembler* assembler, |
| + Register cid, |
| + Register tmp, |
| + Label* target) { |
| + RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target); |
| +} |
| + |
| + |
| +static void JumpIfString(Assembler* assembler, |
| + Register cid, |
| + Register tmp, |
| + Label* target) { |
| + RangeCheck(assembler, |
| + cid, |
| + tmp, |
| + kOneByteStringCid, |
| + kExternalTwoByteStringCid, |
| + kIfInRange, |
| + target); |
| +} |
| + |
| + |
| +static void JumpIfNotString(Assembler* assembler, |
| + Register cid, |
| + Register tmp, |
| + Label* target) { |
| + RangeCheck(assembler, |
| + cid, |
| + tmp, |
| + kOneByteStringCid, |
| + kExternalTwoByteStringCid, |
| + kIfNotInRange, |
| + target); |
| +} |
| + |
| + |
| // Return type quickly for simple types (not parameterized and not signature). |
| void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
| - Label fall_through; |
| + Label fall_through, use_canonical_type, not_integer, not_double; |
| __ lw(T0, Address(SP, 0 * kWordSize)); |
| __ LoadClassIdMayBeSmi(T1, T0); |
| + |
| + // Closures are handled in the runtime. |
| __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); |
| - __ LoadClassById(T2, T1); |
| - // T2: class of instance (T0). |
| + __ BranchUnsignedGreaterEqual( |
| + T1, Immediate(kNumPredefinedCids), &use_canonical_type); |
| + |
| + __ BranchNotEqual(T1, Immediate(kDoubleCid), ¬_double); |
| + // Object is a double. |
| + __ LoadIsolate(T1); |
| + __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| + __ LoadFromOffset(V0, T1, ObjectStore::double_type_offset()); |
| + __ Ret(); |
| + |
| + __ Bind(¬_double); |
| + JumpIfNotInteger(assembler, T1, T2, ¬_integer); |
| + // Object is an integer. |
| + __ LoadIsolate(T1); |
| + __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| + __ LoadFromOffset(V0, T1, ObjectStore::int_type_offset()); |
| + __ Ret(); |
| + |
| + __ Bind(¬_integer); |
| + JumpIfNotString(assembler, T1, T2, &use_canonical_type); |
| + // Object is a string. |
| + __ LoadIsolate(T1); |
| + __ LoadFromOffset(T1, T1, Isolate::object_store_offset()); |
| + __ LoadFromOffset(V0, T1, ObjectStore::string_type_offset()); |
| + __ Ret(); |
| + |
| + __ Bind(&use_canonical_type); |
| + __ LoadClassById(T2, T1); |
| __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); |
| __ BranchNotEqual(T1, Immediate(0), &fall_through); |
| @@ -1688,6 +1782,59 @@ void Intrinsifier::ObjectRuntimeType(Assembler* assembler) { |
| } |
| +void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler) { |
| + Label fall_through, different_cids, equal, not_equal, not_integer; |
| + |
| + __ lw(T0, Address(SP, 0 * kWordSize)); |
| + __ LoadClassIdMayBeSmi(T1, T0); |
| + |
| + // Closures are handled in the runtime. |
| + __ BranchEqual(T1, Immediate(kClosureCid), &fall_through); |
| + |
| + __ lw(T0, Address(SP, 1 * kWordSize)); |
| + __ LoadClassIdMayBeSmi(T2, T0); |
| + |
| + // Check whether class ids match. If class ids don't match objects can still |
| + // have the same runtime type (e.g. multiple string implementation classes |
| + // map to a single String type). |
| + __ BranchNotEqual(T1, T2, &different_cids); |
| + |
| + // Objects have the same class and neither is a closure. |
| + // Check if there are no type arguments. In this case we can return true. |
| + // Otherwise fall through into the runtime to handle comparison. |
| + __ LoadClassById(T2, T1); |
| + __ lhu(T1, FieldAddress(T2, Class::num_type_arguments_offset())); |
|
regis
2016/10/08 09:10:37
ditto
Vyacheslav Egorov (Google)
2016/10/24 20:23:03
Acknowledged.
|
| + __ BranchNotEqual(T1, Immediate(0), &fall_through); |
| + |
| + __ Bind(&equal); |
| + __ LoadObject(V0, Bool::True()); |
| + __ Ret(); |
| + |
| + // Class ids are different. Check if we are comparing runtime types of |
| + // two strings (with different representations) or two integers. |
| + __ Bind(&different_cids); |
| + __ BranchUnsignedGreaterEqual( |
| + T1, Immediate(kNumPredefinedCids), ¬_equal); |
| + |
| + // Check if both are integers. |
| + JumpIfNotInteger(assembler, T1, T0, ¬_integer); |
| + JumpIfInteger(assembler, T2, T0, &equal); |
| + __ b(¬_equal); |
| + |
| + __ Bind(¬_integer); |
| + // Check if both are strings. |
| + JumpIfNotString(assembler, T1, T0, ¬_equal); |
| + JumpIfString(assembler, T2, T0, &equal); |
| + |
| + // Neither strings nor integers and have different class ids. |
| + __ Bind(¬_equal); |
| + __ LoadObject(V0, Bool::False()); |
| + __ Ret(); |
| + |
| + __ Bind(&fall_through); |
| +} |
| + |
| + |
| void Intrinsifier::String_getHashCode(Assembler* assembler) { |
| Label fall_through; |
| __ lw(T0, Address(SP, 0 * kWordSize)); |