diff options
author | 2018-09-07 13:56:57 +0100 | |
---|---|---|
committer | 2018-09-07 15:27:46 +0100 | |
commit | 1d775d2ecfe847395e67310d588626962744c2d0 (patch) | |
tree | c0ad085c62a87400a003fb7eaeb8100a1705bf67 | |
parent | 1c29d5e65d01f9b37b0dbf24903977ea178bc2ea (diff) |
Check that the String class is not movable in String.equals intrinsics.
Test: art/test.py
Bug: 68181300
Bug: 67628039
Change-Id: I66afa3ea010f758125f8aec79509f0255cb5ea03
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 10 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_arm_vixl.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 8 |
8 files changed, 60 insertions, 0 deletions
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 21efe11f31..1407ea92cb 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -20,6 +20,7 @@ #include "art_method-inl.h" #include "base/utils.h" #include "class_linker.h" +#include "class_root.h" #include "dex/invoke_type.h" #include "driver/compiler_options.h" #include "gc/space/image_space.h" @@ -535,4 +536,13 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo return info; } +void IntrinsicVisitor::AssertNonMovableStringClass() { + if (kIsDebugBuild) { + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, *Locks::mutator_lock_); + ObjPtr<mirror::Class> string_class = GetClassRoot<art::mirror::String>(); + CHECK(!art::Runtime::Current()->GetHeap()->IsMovableObject(string_class)); + } +} + } // namespace art diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 2d93f234be..7594d4a50b 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -165,6 +165,8 @@ class IntrinsicVisitor : public ValueObject { protected: IntrinsicVisitor() {} + static void AssertNonMovableStringClass(); + private: DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); }; diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 7684dc79f2..fcd278837f 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1464,8 +1464,16 @@ void IntrinsicCodeGeneratorARM64::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // /* HeapReference<Class> */ temp = str->klass_ __ Ldr(temp, MemOperand(str.X(), class_offset)); + // /* HeapReference<Class> */ temp1 = arg->klass_ __ Ldr(temp1, MemOperand(arg.X(), class_offset)); + // Also, because we use the previously loaded class references only in the + // following comparison, we don't need to unpoison them. __ Cmp(temp, temp1); __ B(&return_false, ne); } diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index bc59fcf50c..f0a418454d 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -1528,8 +1528,16 @@ void IntrinsicCodeGeneratorARMVIXL::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // /* HeapReference<Class> */ temp = str->klass_ __ Ldr(temp, MemOperand(str, class_offset)); + // /* HeapReference<Class> */ out = arg->klass_ __ Ldr(out, MemOperand(arg, class_offset)); + // Also, because we use the previously loaded class references only in the + // following comparison, we don't need to unpoison them. __ Cmp(temp, out); __ B(ne, &return_false, /* far_target */ false); } diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 6f7f5e49c1..2ca12b6533 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1575,8 +1575,16 @@ void IntrinsicCodeGeneratorMIPS::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // /* HeapReference<Class> */ temp1 = str->klass_ __ Lw(temp1, str, class_offset); + // /* HeapReference<Class> */ temp2 = arg->klass_ __ Lw(temp2, arg, class_offset); + // Also, because we use the previously loaded class references only in the + // following comparison, we don't need to unpoison them. __ Bne(temp1, temp2, &return_false); } diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 2eb252908c..cbe3b42cbf 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1429,8 +1429,16 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // /* HeapReference<Class> */ temp1 = str->klass_ __ Lw(temp1, str, class_offset); + // /* HeapReference<Class> */ temp2 = arg->klass_ __ Lw(temp2, arg, class_offset); + // Also, because we use the previously loaded class references only in the + // following comparison, we don't need to unpoison them. __ Bnec(temp1, temp2, &return_false); } diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index 3504d7a6f8..3b23798758 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -967,7 +967,15 @@ void IntrinsicCodeGeneratorX86::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // Also, because we use the loaded class references only to compare them, we + // don't need to unpoison them. + // /* HeapReference<Class> */ ecx = str->klass_ __ movl(ecx, Address(str, class_offset)); + // if (ecx != /* HeapReference<Class> */ arg->klass_) return false __ cmpl(ecx, Address(arg, class_offset)); __ j(kNotEqual, &return_false); } diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 96f6eaaf33..0469b02129 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -1275,7 +1275,15 @@ void IntrinsicCodeGeneratorX86_64::VisitStringEquals(HInvoke* invoke) { // All string objects must have the same type since String cannot be subclassed. // Receiver must be a string object, so its class field is equal to all strings' class fields. // If the argument is a string object, its class field must be equal to receiver's class field. + // + // As the String class is expected to be non-movable, we can read the class + // field from String.equals' arguments without read barriers. + AssertNonMovableStringClass(); + // Also, because we use the loaded class references only to compare them, we + // don't need to unpoison them. + // /* HeapReference<Class> */ rcx = str->klass_ __ movl(rcx, Address(str, class_offset)); + // if (rcx != /* HeapReference<Class> */ arg->klass_) return false __ cmpl(rcx, Address(arg, class_offset)); __ j(kNotEqual, &return_false); } |