Avoid PushLocalFrame(0) CHECK failure

This makes EnsureLocalCapacity(0) and PushLocalFrame(0) correct,
which we believe is the spec intent.

Also simplify test for ridiculously large argument.

Bug: 230854166
Test: Build and boot AOSP
Change-Id: Id4bb3b6bb2f52ff0c3e78f13326405dac06de730
Merged-In: Id4bb3b6bb2f52ff0c3e78f13326405dac06de730
(cherry picked from commit 6e9408c407a1c8e195b065c094a8e15f85aef103)
diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc
index fbe678b..ebf382f 100644
--- a/runtime/indirect_reference_table.cc
+++ b/runtime/indirect_reference_table.cc
@@ -561,8 +561,14 @@
 }
 
 bool IndirectReferenceTable::EnsureFreeCapacity(size_t free_capacity, std::string* error_msg) {
+  DCHECK_GE(free_capacity, static_cast<size_t>(1));
+  if (free_capacity > kMaxTableSizeInBytes) {
+    // Arithmetic might even overflow.
+    *error_msg = "Requested table size implausibly large";
+    return false;
+  }
   size_t top_index = segment_state_.top_index;
-  if (top_index < max_entries_ && top_index + free_capacity <= max_entries_) {
+  if (top_index + free_capacity <= max_entries_) {
     return true;
   }
 
@@ -573,13 +579,6 @@
   }
 
   // Try to increase the table size.
-
-  // Would this overflow?
-  if (std::numeric_limits<size_t>::max() - free_capacity < top_index) {
-    *error_msg = "Cannot resize table, overflow.";
-    return false;
-  }
-
   if (!Resize(top_index + free_capacity, error_msg)) {
     LOG(WARNING) << "JNI ERROR: Unable to reserve space in EnsureFreeCapacity (" << free_capacity
                  << "): " << std::endl
diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h
index 084b534..e279422 100644
--- a/runtime/indirect_reference_table.h
+++ b/runtime/indirect_reference_table.h
@@ -336,6 +336,7 @@
   }
 
   // Ensure that at least free_capacity elements are available, or return false.
+  // Caller ensures free_capacity > 0.
   bool EnsureFreeCapacity(size_t free_capacity, std::string* error_msg)
       REQUIRES_SHARED(Locks::mutator_lock_);
   // See implementation of EnsureFreeCapacity. We'll only state here how much is trivially free,
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 7a25b4b..e3153fd 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -2847,17 +2847,19 @@
   static jint EnsureLocalCapacityInternal(ScopedObjectAccess& soa, jint desired_capacity,
                                           const char* caller)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (desired_capacity < 0) {
+    if (desired_capacity > 0) {
+      std::string error_msg;
+      if (!soa.Env()->locals_.EnsureFreeCapacity(static_cast<size_t>(desired_capacity),
+                                                 &error_msg)) {
+        std::string caller_error = android::base::StringPrintf("%s: %s", caller,
+                                                               error_msg.c_str());
+        soa.Self()->ThrowOutOfMemoryError(caller_error.c_str());
+        return JNI_ERR;
+      }
+    } else if (desired_capacity < 0) {
       LOG(ERROR) << "Invalid capacity given to " << caller << ": " << desired_capacity;
       return JNI_ERR;
-    }
-
-    std::string error_msg;
-    if (!soa.Env()->locals_.EnsureFreeCapacity(static_cast<size_t>(desired_capacity), &error_msg)) {
-      std::string caller_error = android::base::StringPrintf("%s: %s", caller, error_msg.c_str());
-      soa.Self()->ThrowOutOfMemoryError(caller_error.c_str());
-      return JNI_ERR;
-    }
+    }  // The zero case is a no-op.
     return JNI_OK;
   }