Add basic support for object pointer poisoning

ObjPtr is a pointer that checks for heap corruption and is meant
to replace mirror::Object* in places where a mirror::Object* is a
local variable. Whenever there is a possible suspend point, the
current thread's object pointers are all invalidated. This is done
by storing a cookie in the object pointer associated with what thread
created it.

Added test case in object_test.

Example failure:
object_test F 25379 25379 object_pointer.h:70] Check failed:
IsValid() Invalid cookie, expected 0 but got 2

Bug: 31113334

Test: test-art-host-gtest-object_test

Change-Id: I9fa80ccaf2f0448621942935af702a243a3e1ee6
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index afd6115..f4ecfb5 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -35,6 +35,7 @@
 #include "gc/heap.h"
 #include "handle_scope-inl.h"
 #include "iftable-inl.h"
+#include "obj_ptr.h"
 #include "object-inl.h"
 #include "object_array-inl.h"
 #include "scoped_thread_state_change.h"
@@ -738,5 +739,62 @@
   EXPECT_NE(hash_code, 0);
 }
 
+TEST_F(ObjectTest, ObjectPointer) {
+  ScopedObjectAccess soa(Thread::Current());
+  jobject jclass_loader = LoadDex("XandY");
+  StackHandleScope<2> hs(soa.Self());
+  ObjPtr<mirror::Object, /*kPoison*/ true> null_ptr;
+  EXPECT_TRUE(null_ptr.IsNull());
+  EXPECT_TRUE(null_ptr.IsValid());
+  EXPECT_TRUE(null_ptr.Get() == nullptr);
+  EXPECT_TRUE(null_ptr == nullptr);
+  EXPECT_TRUE(null_ptr == null_ptr);
+  EXPECT_FALSE(null_ptr != null_ptr);
+  EXPECT_FALSE(null_ptr != nullptr);
+  null_ptr.AssertValid();
+  Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader)));
+  Handle<mirror::Class> h_X(
+      hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)));
+  ObjPtr<Class, /*kPoison*/ true> X(h_X.Get());
+  EXPECT_TRUE(!X.IsNull());
+  EXPECT_TRUE(X.IsValid());
+  EXPECT_TRUE(X.Get() != nullptr);
+  EXPECT_EQ(h_X.Get(), X.Get());
+  // FindClass may cause thread suspension, it should invalidate X.
+  ObjPtr<Class, /*kPoison*/ true> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader));
+  EXPECT_TRUE(!Y.IsNull());
+  EXPECT_TRUE(Y.IsValid());
+  EXPECT_TRUE(Y.Get() != nullptr);
+
+  // Should IsNull be safe to call on null ObjPtr? I'll allow it for now.
+  EXPECT_TRUE(!X.IsNull());
+  EXPECT_TRUE(!X.IsValid());
+  // Make X valid again by copying out of handle.
+  X.Assign(h_X.Get());
+  EXPECT_TRUE(!X.IsNull());
+  EXPECT_TRUE(X.IsValid());
+  EXPECT_EQ(h_X.Get(), X.Get());
+
+  // Allow thread suspension to invalidate Y.
+  soa.Self()->AllowThreadSuspension();
+  EXPECT_TRUE(!Y.IsNull());
+  EXPECT_TRUE(!Y.IsValid());
+
+  // Test unpoisoned.
+  ObjPtr<mirror::Object, /*kPoison*/ false> unpoisoned;
+  EXPECT_TRUE(unpoisoned.IsNull());
+  EXPECT_TRUE(unpoisoned.IsValid());
+  EXPECT_TRUE(unpoisoned.Get() == nullptr);
+  EXPECT_TRUE(unpoisoned == nullptr);
+  EXPECT_TRUE(unpoisoned == unpoisoned);
+  EXPECT_FALSE(unpoisoned != unpoisoned);
+  EXPECT_FALSE(unpoisoned != nullptr);
+
+  unpoisoned = h_X.Get();
+  EXPECT_FALSE(unpoisoned.IsNull());
+  EXPECT_TRUE(unpoisoned == h_X.Get());
+  EXPECT_EQ(unpoisoned.Get(), h_X.Get());
+}
+
 }  // namespace mirror
 }  // namespace art