Merge "Add implicit null and stack checks for x86"
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index fdbc9c2..289dc1d 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -26,7 +26,7 @@
 #include <fstream>
 #include <memory>
 
-#include "../../external/icu4c/common/unicode/uvernum.h"
+#include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/stringprintf.h"
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index a1d001e..ad0a4f43 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -17,9 +17,9 @@
 #ifndef ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_INL_H_
 #define ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_INL_H_
 
+#include "atomic.h"
 #include "base/logging.h"
 #include "card_table.h"
-#include "cutils/atomic-inline.h"
 #include "space_bitmap.h"
 #include "utils.h"
 
@@ -28,18 +28,23 @@
 namespace accounting {
 
 static inline bool byte_cas(byte old_value, byte new_value, byte* address) {
+#if defined(__i386__) || defined(__x86_64__)
+  Atomic<byte>* byte_atomic = reinterpret_cast<Atomic<byte>*>(address);
+  return byte_atomic->CompareExchangeWeakRelaxed(old_value, new_value);
+#else
   // Little endian means most significant byte is on the left.
   const size_t shift_in_bytes = reinterpret_cast<uintptr_t>(address) % sizeof(uintptr_t);
   // Align the address down.
   address -= shift_in_bytes;
   const size_t shift_in_bits = shift_in_bytes * kBitsPerByte;
-  int32_t* word_address = reinterpret_cast<int32_t*>(address);
+  AtomicInteger* word_atomic = reinterpret_cast<AtomicInteger*>(address);
+
   // Word with the byte we are trying to cas cleared.
-  const int32_t cur_word = *word_address & ~(0xFF << shift_in_bits);
+  const int32_t cur_word = word_atomic->LoadRelaxed() & ~(0xFF << shift_in_bits);
   const int32_t old_word = cur_word | (static_cast<int32_t>(old_value) << shift_in_bits);
   const int32_t new_word = cur_word | (static_cast<int32_t>(new_value) << shift_in_bits);
-  bool success = android_atomic_cas(old_word, new_word, word_address) == 0;
-  return success;
+  return word_atomic->CompareExchangeWeakRelaxed(old_word, new_word);
+#endif
 }
 
 template <typename Visitor>
@@ -174,8 +179,8 @@
       for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
         new_bytes[i] = visitor(expected_bytes[i]);
       }
-      if (LIKELY(android_atomic_cas(expected_word, new_word,
-                                    reinterpret_cast<int32_t*>(word_cur)) == 0)) {
+      Atomic<uintptr_t>* atomic_word = reinterpret_cast<Atomic<uintptr_t>*>(word_cur);
+      if (LIKELY(atomic_word->CompareExchangeWeakRelaxed(expected_word, new_word))) {
         for (size_t i = 0; i < sizeof(uintptr_t); ++i) {
           const byte expected_byte = expected_bytes[i];
           const byte new_byte = new_bytes[i];
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 6d70a38..511e9f8 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -981,6 +981,7 @@
   friend class VerifyReferenceCardVisitor;
   friend class VerifyReferenceVisitor;
   friend class VerifyObjectVisitor;
+  friend class ScopedHeapFill;
   friend class ScopedHeapLock;
   friend class space::SpaceTest;
 
@@ -997,6 +998,25 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(Heap);
 };
 
+// ScopedHeapFill changes the bytes allocated counter to be equal to the growth limit. This
+// causes the next allocation to perform a GC and possibly an OOM. It can be used to ensure that a
+// GC happens in specific methods such as ThrowIllegalMonitorStateExceptionF in Monitor::Wait.
+class ScopedHeapFill {
+ public:
+  explicit ScopedHeapFill(Heap* heap)
+      : heap_(heap),
+        delta_(heap_->GetMaxMemory() - heap_->GetBytesAllocated()) {
+    heap_->num_bytes_allocated_.FetchAndAddSequentiallyConsistent(delta_);
+  }
+  ~ScopedHeapFill() {
+    heap_->num_bytes_allocated_.FetchAndSubSequentiallyConsistent(delta_);
+  }
+
+ private:
+  Heap* const heap_;
+  const int64_t delta_;
+};
+
 }  // namespace gc
 }  // namespace art
 
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index c7fb884..9f04b90 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -772,8 +772,13 @@
     // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
     Class* found = Runtime::Current()->GetClassLinker()->FindClass(
         self, descriptor.c_str(), NullHandle<mirror::ClassLoader>());
-    CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
-        << PrettyDescriptor(descriptor);
+    if (found == NULL) {
+      if (!self->IsExceptionPending()) {
+        AbortTransaction(self, "Class.forName failed in un-started runtime for class: %s",
+                         PrettyDescriptor(descriptor).c_str());
+      }
+      return;
+    }
     result->SetL(found);
   } else if (name == "java.lang.Class java.lang.Void.lookupType()") {
     result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
diff --git a/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index 73cc9eb..458ad69 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -111,11 +111,6 @@
   }
 
   const struct sigaction& action = user_sigactions[sig].GetAction();
-
-  // Only deliver the signal if the signal was not masked out.
-  if (sigismember(&action.sa_mask, sig)) {
-     return;
-  }
   if ((action.sa_flags & SA_SIGINFO) == 0) {
     if (action.sa_handler != NULL) {
       action.sa_handler(sig);
diff --git a/test/082-inline-execute/src/Main.java b/test/082-inline-execute/src/Main.java
index 2e1c6d9..f412034 100644
--- a/test/082-inline-execute/src/Main.java
+++ b/test/082-inline-execute/src/Main.java
@@ -61,6 +61,9 @@
     test_Memory_pokeShort();
     test_Memory_pokeInt();
     test_Memory_pokeLong();
+    test_AtomicBoolean_compareAndSet();
+    test_AtomicInteger_compareAndSet();
+    test_AtomicLong_compareAndSet();
   }
 
   /*
@@ -93,6 +96,60 @@
     Assert.assertNotNull(Thread.currentThread());
   }
 
+  /**
+   * Will test inlining CAS, by inclusion of AtomicBoolean in core.oat.
+   */
+  public static void test_AtomicBoolean_compareAndSet() {
+    java.util.concurrent.atomic.AtomicBoolean ab = new java.util.concurrent.atomic.AtomicBoolean();
+    Assert.assertEquals(ab.compareAndSet(false, false), true);
+    Assert.assertEquals(ab.compareAndSet(true, false), false);
+    Assert.assertEquals(ab.compareAndSet(true, true), false);
+    Assert.assertEquals(ab.compareAndSet(false, true), true);
+    Assert.assertEquals(ab.compareAndSet(false, true), false);
+    Assert.assertEquals(ab.compareAndSet(false, false), false);
+    Assert.assertEquals(ab.compareAndSet(true, true), true);
+    Assert.assertEquals(ab.compareAndSet(true, false), true);
+    Assert.assertEquals(ab.compareAndSet(true, false), false);
+    Assert.assertEquals(ab.compareAndSet(true, true), false);
+    Assert.assertEquals(ab.compareAndSet(false, false), true);
+  }
+
+  /**
+   * Will test inlining CAS, by inclusion of AtomicInteger in core.oat.
+   */
+  public static void test_AtomicInteger_compareAndSet() {
+    java.util.concurrent.atomic.AtomicInteger ab = new java.util.concurrent.atomic.AtomicInteger();
+    Assert.assertEquals(ab.compareAndSet(0, 0), true);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0), false);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0x12345678), false);
+    Assert.assertEquals(ab.compareAndSet(0, 0x12345678), true);
+    Assert.assertEquals(ab.compareAndSet(0, 0x12345678), false);
+    Assert.assertEquals(ab.compareAndSet(0, 0), false);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0x12345678), true);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0), true);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0), false);
+    Assert.assertEquals(ab.compareAndSet(0x12345678, 0x12345678), false);
+    Assert.assertEquals(ab.compareAndSet(0, 0), true);
+  }
+
+  /**
+   * Will test inlining CAS, by inclusion of AtomicLong in core.oat.
+   */
+  public static void test_AtomicLong_compareAndSet() {
+    java.util.concurrent.atomic.AtomicLong ab = new java.util.concurrent.atomic.AtomicLong();
+    Assert.assertEquals(ab.compareAndSet(0l, 0l), true);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0l), false);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0x1234567890l), false);
+    Assert.assertEquals(ab.compareAndSet(0l, 0x1234567890l), true);
+    Assert.assertEquals(ab.compareAndSet(0l, 0x1234567890l), false);
+    Assert.assertEquals(ab.compareAndSet(0l, 0l), false);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0x1234567890l), true);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0l), true);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0l), false);
+    Assert.assertEquals(ab.compareAndSet(0x1234567890l, 0x1234567890l), false);
+    Assert.assertEquals(ab.compareAndSet(0l, 0l), true);
+  }
+
   public static void test_String_length() {
     String str0 = "";
     String str1 = "x";