Implement Integer.valueOf() intrinsic for PIC.

And fix the intrinsic for JIT even in case when someone
messes up the IntegerCache using reflection. Two cases are
exposed with a regression test (one that previously failed
randomly and one that failed 100%) but other crashes were
possible; for example, we would need a read barrier for
array reads when elements are not guaranteed to be in the
boot image.

The new approach loads references only from the boot image
live objects array which cannot be touched by reflection.
The referenced objects and IntegerCache.cache are exposed
and can lead to weird behavior but not crashes.

On x86, the pc_relative_fixups_86 actually checks the cache
an additional time but discrepancies between this check and
the location building at the beginning of codegen should be
OK as the HIsX86ComputeBaseMethodAddress should be added
for PIC regardless of whether pc_relative_fixups_86 thinks
the method is intrinsified or not.

Test: 717-integer-value-of
Test: Pixel 2 XL boots.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --pictest --npictest
Test: testrunner.py --host --jit
Test: testrunner.py --target --optimizing --pictest --npictest
Test: testrunner.py --target --jit
Bug: 71526895
Change-Id: I89b3245a62aba22980c86a99e2af480bfa250af1
diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc
index 9a9ae71..510040b 100644
--- a/compiler/optimizing/intrinsics_mips64.cc
+++ b/compiler/optimizing/intrinsics_mips64.cc
@@ -2267,7 +2267,7 @@
 }
 
 void IntrinsicCodeGeneratorMIPS64::VisitIntegerValueOf(HInvoke* invoke) {
-  IntrinsicVisitor::IntegerValueOfInfo info = IntrinsicVisitor::ComputeIntegerValueOfInfo();
+  IntrinsicVisitor::IntegerValueOfInfo info = IntrinsicVisitor::ComputeIntegerValueOfInfo(invoke);
   LocationSummary* locations = invoke->GetLocations();
   Mips64Assembler* assembler = GetAssembler();
   InstructionCodeGeneratorMIPS64* icodegen =
@@ -2275,22 +2275,18 @@
 
   GpuRegister out = locations->Out().AsRegister<GpuRegister>();
   InvokeRuntimeCallingConvention calling_convention;
+  GpuRegister argument = calling_convention.GetRegisterAt(0);
   if (invoke->InputAt(0)->IsConstant()) {
     int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
-    if (value >= info.low && value <= info.high) {
+    if (info.value_boot_image_offset != 0u) {
       // Just embed the j.l.Integer in the code.
-      ScopedObjectAccess soa(Thread::Current());
-      mirror::Object* boxed = info.cache->Get(value + (-info.low));
-      DCHECK(boxed != nullptr && Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(boxed));
-      uint32_t address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(boxed));
-      __ LoadConst64(out, address);
+      codegen_->LoadBootImageAddress(out, info.value_boot_image_offset);
     } else {
+      DCHECK(locations->CanCall());
       // Allocate and initialize a new j.l.Integer.
       // TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
       // JIT object table.
-      uint32_t address =
-          dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.integer));
-      __ LoadConst64(calling_convention.GetRegisterAt(0), address);
+      codegen_->LoadBootImageAddress(argument, info.integer_boot_image_offset);
       codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
       CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
       __ StoreConstToOffset(kStoreWord, value, out, info.value_offset, TMP);
@@ -2299,22 +2295,18 @@
       icodegen->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
     }
   } else {
+    DCHECK(locations->CanCall());
     GpuRegister in = locations->InAt(0).AsRegister<GpuRegister>();
     Mips64Label allocate, done;
-    int32_t count = static_cast<uint32_t>(info.high) - info.low + 1;
 
-    // Is (info.low <= in) && (in <= info.high)?
     __ Addiu32(out, in, -info.low);
-    // As unsigned quantities is out < (info.high - info.low + 1)?
-    __ LoadConst32(AT, count);
-    // Branch if out >= (info.high - info.low + 1).
-    // This means that "in" is outside of the range [info.low, info.high].
+    // As unsigned quantities is out < info.length ?
+    __ LoadConst32(AT, info.length);
+    // Branch if out >= info.length . This means that "in" is outside of the valid range.
     __ Bgeuc(out, AT, &allocate);
 
     // If the value is within the bounds, load the j.l.Integer directly from the array.
-    uint32_t data_offset = mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value();
-    uint32_t address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.cache));
-    __ LoadConst64(TMP, data_offset + address);
+    codegen_->LoadBootImageAddress(TMP, info.array_data_boot_image_offset);
     __ Dlsa(out, out, TMP, TIMES_4);
     __ Lwu(out, out, 0);
     __ MaybeUnpoisonHeapReference(out);
@@ -2322,8 +2314,7 @@
 
     __ Bind(&allocate);
     // Otherwise allocate and initialize a new j.l.Integer.
-    address = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(info.integer));
-    __ LoadConst64(calling_convention.GetRegisterAt(0), address);
+    codegen_->LoadBootImageAddress(argument, info.integer_boot_image_offset);
     codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
     CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
     __ StoreToOffset(kStoreWord, in, out, info.value_offset);