dex2oat: Abort app compilation without boot image.

Also avoid crash in GraphChecker for bad instructions that
throw into catch block but do not have an environment. And
DCHECK() that java_lang_Double_doubleToRawLongBits and
java_lang_Float_floatToRawIntBits are intrinsics.

(cherry picked from commit d42902692d1fbb101a3c60ba314df69005da9c83)

Test: New test Dex2oatTest.MissingBootImageTest.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 188684102
Merged-In: I13ec2ee8a7968c0a5652aa67ec6291d07a986c80
Change-Id: I531b87c25e937f8c5f7d471cb7878e086e9662b5
diff --git a/compiler/optimizing/critical_native_abi_fixup_arm.cc b/compiler/optimizing/critical_native_abi_fixup_arm.cc
index 11d42a4..3c4db4b 100644
--- a/compiler/optimizing/critical_native_abi_fixup_arm.cc
+++ b/compiler/optimizing/critical_native_abi_fixup_arm.cc
@@ -49,6 +49,7 @@
                                          : WellKnownClasses::java_lang_Float_floatToRawIntBits;
       ArtMethod* resolved_method = jni::DecodeArtMethod(known_method);
       DCHECK(resolved_method != nullptr);
+      DCHECK(resolved_method->IsIntrinsic());
       MethodReference target_method(nullptr, 0);
       {
         ScopedObjectAccess soa(Thread::Current());
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 44de54e..d1769ce 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -507,7 +507,12 @@
     }
   }
 
-  if (instruction->CanThrowIntoCatchBlock()) {
+  if (instruction->CanThrow() && !instruction->HasEnvironment()) {
+    AddError(StringPrintf("Throwing instruction %s:%d in block %d does not have an environment.",
+                          instruction->DebugName(),
+                          instruction->GetId(),
+                          current_block_->GetBlockId()));
+  } else if (instruction->CanThrowIntoCatchBlock()) {
     // Find the top-level environment. This corresponds to the environment of
     // the catch block since we do not inline methods with try/catch.
     HEnvironment* environment = instruction->GetEnvironment();
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 58221c3..c613e33 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1565,6 +1565,12 @@
         LOG(ERROR) << "Missing required boot image(s) for boot image extension.";
         return dex2oat::ReturnCode::kOther;
       }
+    } else {
+      // Check that we loaded at least the primary boot image for app compilation.
+      if (runtime_->GetHeap()->GetBootImageSpaces().empty()) {
+        LOG(ERROR) << "Missing primary boot image for app compilation.";
+        return dex2oat::ReturnCode::kOther;
+      }
     }
 
     if (!compilation_reason_.empty()) {
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index e2ad018..c4c39c2 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -1419,6 +1419,22 @@
                                   }));
 }
 
+TEST_F(Dex2oatTest, MissingBootImageTest) {
+  std::string out_dir = GetScratchDir();
+  const std::string base_oat_name = out_dir + "/base.oat";
+  std::string error_msg;
+  int status = GenerateOdexForTestWithStatus(
+      { GetTestDexFileName("MainUncompressedAligned") },
+      base_oat_name,
+      CompilerFilter::Filter::kVerify,
+      &error_msg,
+      // Note: Extra options go last and the second `--boot-image` option overrides the first.
+      { "--boot-image=/nonx/boot.art" });
+  // Expect to fail with code 1 and not SIGSEGV or SIGABRT.
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(WEXITSTATUS(status), 1) << error_msg;
+}
+
 TEST_F(Dex2oatTest, EmptyUncompressedDexTest) {
   std::string out_dir = GetScratchDir();
   const std::string base_oat_name = out_dir + "/base.oat";