Fix native allocation watermark clamping.

The main issue causing the test to fail is that
native_footprint_gc_watermark_ becoming > growth_limit_ due to no
clamping.

Temporary runFinalization fix is calling runFinalization 2x.

Bug: 17371542
Change-Id: I188cb530a44dd109e066a22091f12f8d2d4350c3
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index ce914e5..b2873e5 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2831,7 +2831,7 @@
   } else if (target_size < native_size + min_free_) {
     target_size = native_size + min_free_;
   }
-  native_footprint_gc_watermark_ = target_size;
+  native_footprint_gc_watermark_ = std::min(growth_limit_, target_size);
 }
 
 collector::GarbageCollector* Heap::FindCollectorByGcType(collector::GcType gc_type) {
@@ -3085,9 +3085,11 @@
   }
   env->CallStaticVoidMethod(WellKnownClasses::java_lang_System,
                             WellKnownClasses::java_lang_System_runFinalization);
+  env->CallStaticVoidMethod(WellKnownClasses::java_lang_System,
+                            WellKnownClasses::java_lang_System_runFinalization);
 }
 
-void Heap::RegisterNativeAllocation(JNIEnv* env, int bytes) {
+void Heap::RegisterNativeAllocation(JNIEnv* env, size_t bytes) {
   Thread* self = ThreadForEnv(env);
   if (native_need_to_run_finalization_) {
     RunFinalization(env);
@@ -3129,19 +3131,19 @@
   }
 }
 
-void Heap::RegisterNativeFree(JNIEnv* env, int bytes) {
-  int expected_size, new_size;
+void Heap::RegisterNativeFree(JNIEnv* env, size_t bytes) {
+  size_t expected_size;
   do {
     expected_size = native_bytes_allocated_.LoadRelaxed();
-    new_size = expected_size - bytes;
-    if (UNLIKELY(new_size < 0)) {
+    if (UNLIKELY(bytes > expected_size)) {
       ScopedObjectAccess soa(env);
       env->ThrowNew(WellKnownClasses::java_lang_RuntimeException,
-                    StringPrintf("Attempted to free %d native bytes with only %d native bytes "
+                    StringPrintf("Attempted to free %zd native bytes with only %zd native bytes "
                                  "registered as allocated", bytes, expected_size).c_str());
       break;
     }
-  } while (!native_bytes_allocated_.CompareExchangeWeakRelaxed(expected_size, new_size));
+  } while (!native_bytes_allocated_.CompareExchangeWeakRelaxed(expected_size,
+                                                               expected_size - bytes));
 }
 
 size_t Heap::GetTotalMemory() const {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index a0fcf53..d3d613f 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -211,8 +211,8 @@
   void CheckPreconditionsForAllocObject(mirror::Class* c, size_t byte_count)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void RegisterNativeAllocation(JNIEnv* env, int bytes);
-  void RegisterNativeFree(JNIEnv* env, int bytes);
+  void RegisterNativeAllocation(JNIEnv* env, size_t bytes);
+  void RegisterNativeFree(JNIEnv* env, size_t bytes);
 
   // Change the allocator, updates entrypoints.
   void ChangeAllocator(AllocatorType allocator)
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index b0b64aa..19e6550 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -184,7 +184,7 @@
     ThrowRuntimeException("allocation size negative %d", bytes);
     return;
   }
-  Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, bytes);
+  Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, static_cast<size_t>(bytes));
 }
 
 static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) {
@@ -193,7 +193,7 @@
     ThrowRuntimeException("allocation size negative %d", bytes);
     return;
   }
-  Runtime::Current()->GetHeap()->RegisterNativeFree(env, bytes);
+  Runtime::Current()->GetHeap()->RegisterNativeFree(env, static_cast<size_t>(bytes));
 }
 
 static void VMRuntime_updateProcessState(JNIEnv* env, jobject, jint process_state) {